diff --git a/packages/app/src/cli/api/graphql/app-management/generated/active-app-release-from-api-key.ts b/packages/app/src/cli/api/graphql/app-management/generated/active-app-release-from-api-key.ts new file mode 100644 index 00000000000..afacbe0f56c --- /dev/null +++ b/packages/app/src/cli/api/graphql/app-management/generated/active-app-release-from-api-key.ts @@ -0,0 +1,164 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +import * as Types from './types.js' +import {JsonMapType} from '@shopify/cli-kit/node/toml' + +import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core' + +export type ActiveAppReleaseFromApiKeyQueryVariables = Types.Exact<{ + apiKey: Types.Scalars['String']['input'] +}> + +export type ActiveAppReleaseFromApiKeyQuery = { + app: { + id: string + key: string + activeRoot: {clientCredentials: {secrets: {key: string}[]}} + activeRelease: { + id: string + version: { + name: string + appModules: { + uuid: string + userIdentifier: string + handle: string + config: JsonMapType + specification: {identifier: string; externalIdentifier: string; name: string} + }[] + } + } + } +} + +export const ActiveAppReleaseFromApiKey = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: {kind: 'Name', value: 'ActiveAppReleaseFromApiKey'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'apiKey'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + alias: {kind: 'Name', value: 'app'}, + name: {kind: 'Name', value: 'appByKey'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'key'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'apiKey'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'FragmentSpread', name: {kind: 'Name', value: 'AppVersionInfo'}}, + {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, + ], + }, + }, + ], + }, + }, + { + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'ReleasedAppModule'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'AppModule'}}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'uuid'}}, + {kind: 'Field', name: {kind: 'Name', value: 'userIdentifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'handle'}}, + {kind: 'Field', name: {kind: 'Name', value: 'config'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'specification'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'identifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'externalIdentifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + ], + }, + }, + ], + }, + }, + { + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'AppVersionInfo'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'App'}}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + {kind: 'Field', name: {kind: 'Name', value: 'key'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRoot'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'clientCredentials'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'secrets'}, + selectionSet: { + kind: 'SelectionSet', + selections: [{kind: 'Field', name: {kind: 'Name', value: 'key'}}], + }, + }, + ], + }, + }, + ], + }, + }, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRelease'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'version'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'appModules'}, + selectionSet: { + kind: 'SelectionSet', + selections: [{kind: 'FragmentSpread', name: {kind: 'Name', value: 'ReleasedAppModule'}}], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode diff --git a/packages/app/src/cli/api/graphql/app-management/generated/active-app-release.ts b/packages/app/src/cli/api/graphql/app-management/generated/active-app-release.ts index 3f6ed301e94..18ca4c2fd29 100644 --- a/packages/app/src/cli/api/graphql/app-management/generated/active-app-release.ts +++ b/packages/app/src/cli/api/graphql/app-management/generated/active-app-release.ts @@ -29,6 +29,25 @@ export type ActiveAppReleaseQuery = { } } +export type AppVersionInfoFragment = { + id: string + key: string + activeRoot: {clientCredentials: {secrets: {key: string}[]}} + activeRelease: { + id: string + version: { + name: string + appModules: { + uuid: string + userIdentifier: string + handle: string + config: JsonMapType + specification: {identifier: string; externalIdentifier: string; name: string} + }[] + } + } +} + export type ReleasedAppModuleFragment = { uuid: string userIdentifier: string @@ -68,102 +87,134 @@ export const ReleasedAppModuleFragmentDoc = { }, ], } as unknown as DocumentNode -export const ActiveAppRelease = { +export const AppVersionInfoFragmentDoc = { kind: 'Document', definitions: [ { - kind: 'OperationDefinition', - operation: 'query', - name: {kind: 'Name', value: 'activeAppRelease'}, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: {kind: 'Variable', name: {kind: 'Name', value: 'appId'}}, - type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'ID'}}}, - }, - ], + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'AppVersionInfo'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'App'}}, selectionSet: { kind: 'SelectionSet', selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + {kind: 'Field', name: {kind: 'Name', value: 'key'}}, { kind: 'Field', - name: {kind: 'Name', value: 'app'}, - arguments: [ - { - kind: 'Argument', - name: {kind: 'Name', value: 'id'}, - value: {kind: 'Variable', name: {kind: 'Name', value: 'appId'}}, - }, - ], + name: {kind: 'Name', value: 'activeRoot'}, selectionSet: { kind: 'SelectionSet', selections: [ - {kind: 'Field', name: {kind: 'Name', value: 'id'}}, - {kind: 'Field', name: {kind: 'Name', value: 'key'}}, { kind: 'Field', - name: {kind: 'Name', value: 'activeRoot'}, + name: {kind: 'Name', value: 'clientCredentials'}, selectionSet: { kind: 'SelectionSet', selections: [ { kind: 'Field', - name: {kind: 'Name', value: 'clientCredentials'}, + name: {kind: 'Name', value: 'secrets'}, selectionSet: { kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: {kind: 'Name', value: 'secrets'}, - selectionSet: { - kind: 'SelectionSet', - selections: [ - {kind: 'Field', name: {kind: 'Name', value: 'key'}}, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, - ], - }, - }, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, - ], + selections: [{kind: 'Field', name: {kind: 'Name', value: 'key'}}], }, }, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, ], }, }, + ], + }, + }, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRelease'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, { kind: 'Field', - name: {kind: 'Name', value: 'activeRelease'}, + name: {kind: 'Name', value: 'version'}, selectionSet: { kind: 'SelectionSet', selections: [ - {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, { kind: 'Field', - name: {kind: 'Name', value: 'version'}, + name: {kind: 'Name', value: 'appModules'}, selectionSet: { kind: 'SelectionSet', - selections: [ - {kind: 'Field', name: {kind: 'Name', value: 'name'}}, - { - kind: 'Field', - name: {kind: 'Name', value: 'appModules'}, - selectionSet: { - kind: 'SelectionSet', - selections: [ - {kind: 'FragmentSpread', name: {kind: 'Name', value: 'ReleasedAppModule'}}, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, - ], - }, - }, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, - ], + selections: [{kind: 'FragmentSpread', name: {kind: 'Name', value: 'ReleasedAppModule'}}], }, }, - {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, ], }, }, + ], + }, + }, + ], + }, + }, + { + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'ReleasedAppModule'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'AppModule'}}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'uuid'}}, + {kind: 'Field', name: {kind: 'Name', value: 'userIdentifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'handle'}}, + {kind: 'Field', name: {kind: 'Name', value: 'config'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'specification'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'identifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'externalIdentifier'}}, + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode +export const ActiveAppRelease = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: {kind: 'Name', value: 'activeAppRelease'}, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: {kind: 'Variable', name: {kind: 'Name', value: 'appId'}}, + type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'ID'}}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'app'}, + arguments: [ + { + kind: 'Argument', + name: {kind: 'Name', value: 'id'}, + value: {kind: 'Variable', name: {kind: 'Name', value: 'appId'}}, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'FragmentSpread', name: {kind: 'Name', value: 'AppVersionInfo'}}, {kind: 'Field', name: {kind: 'Name', value: '__typename'}}, ], }, @@ -197,5 +248,71 @@ export const ActiveAppRelease = { ], }, }, + { + kind: 'FragmentDefinition', + name: {kind: 'Name', value: 'AppVersionInfo'}, + typeCondition: {kind: 'NamedType', name: {kind: 'Name', value: 'App'}}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + {kind: 'Field', name: {kind: 'Name', value: 'key'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRoot'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'clientCredentials'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: {kind: 'Name', value: 'secrets'}, + selectionSet: { + kind: 'SelectionSet', + selections: [{kind: 'Field', name: {kind: 'Name', value: 'key'}}], + }, + }, + ], + }, + }, + ], + }, + }, + { + kind: 'Field', + name: {kind: 'Name', value: 'activeRelease'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'id'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'version'}, + selectionSet: { + kind: 'SelectionSet', + selections: [ + {kind: 'Field', name: {kind: 'Name', value: 'name'}}, + { + kind: 'Field', + name: {kind: 'Name', value: 'appModules'}, + selectionSet: { + kind: 'SelectionSet', + selections: [{kind: 'FragmentSpread', name: {kind: 'Name', value: 'ReleasedAppModule'}}], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, ], } as unknown as DocumentNode diff --git a/packages/app/src/cli/api/graphql/app-management/queries/active-app-release-from-api-key.graphql b/packages/app/src/cli/api/graphql/app-management/queries/active-app-release-from-api-key.graphql new file mode 100644 index 00000000000..bc0d1e9b092 --- /dev/null +++ b/packages/app/src/cli/api/graphql/app-management/queries/active-app-release-from-api-key.graphql @@ -0,0 +1,5 @@ +query ActiveAppReleaseFromApiKey($apiKey: String!) { + app: appByKey(key: $apiKey) { + ...AppVersionInfo + } +} diff --git a/packages/app/src/cli/api/graphql/app-management/queries/active-app-release.graphql b/packages/app/src/cli/api/graphql/app-management/queries/active-app-release.graphql index 3408adc4edc..22c1a3e0bc7 100644 --- a/packages/app/src/cli/api/graphql/app-management/queries/active-app-release.graphql +++ b/packages/app/src/cli/api/graphql/app-management/queries/active-app-release.graphql @@ -1,22 +1,26 @@ query activeAppRelease($appId: ID!) { app(id: $appId) { - id - key - activeRoot { - clientCredentials { - secrets { - key - } + ...AppVersionInfo + } +} + +fragment AppVersionInfo on App { + id + key + activeRoot { + clientCredentials { + secrets { + key } } - activeRelease { - id - version { - name + } + activeRelease { + id + version { + name appModules { ...ReleasedAppModule } - } } } } diff --git a/packages/app/src/cli/commands/app/init.ts b/packages/app/src/cli/commands/app/init.ts index c90c77b05a1..39bacacb70f 100644 --- a/packages/app/src/cli/commands/app/init.ts +++ b/packages/app/src/cli/commands/app/init.ts @@ -1,7 +1,7 @@ import initPrompt, {visibleTemplates} from '../../prompts/init/init.js' import initService from '../../services/init/init.js' import {DeveloperPlatformClient, selectDeveloperPlatformClient} from '../../utilities/developer-platform-client.js' -import {appFromId, selectOrg} from '../../services/context.js' +import {appFromIdentifiers, selectOrg} from '../../services/context.js' import AppCommand, {AppCommandOutput} from '../../utilities/app-command.js' import {validateFlavorValue, validateTemplateValue} from '../../services/init/validate.js' import {MinimalOrganizationApp, Organization, OrganizationApp} from '../../models/organization.js' @@ -87,7 +87,7 @@ export default class Init extends AppCommand { let appName: string if (flags['client-id']) { // If a client-id is provided we don't need to prompt the user and can link directly to that app. - const selectedApp = await appFromId({apiKey: flags['client-id'], developerPlatformClient}) + const selectedApp = await appFromIdentifiers({apiKey: flags['client-id'], developerPlatformClient}) appName = selectedApp.title developerPlatformClient = selectedApp.developerPlatformClient ?? developerPlatformClient selectAppResult = {result: 'existing', app: selectedApp} @@ -158,7 +158,7 @@ async function selectAppOrNewAppName( } else { const app = await selectAppPrompt(searchForAppsByNameFactory(developerPlatformClient, org.id), apps, hasMorePages) - const fullSelectedApp = await developerPlatformClient.appFromId(app) + const fullSelectedApp = await developerPlatformClient.appFromIdentifiers(app) if (!fullSelectedApp) throw new AbortError(`App with id ${app.id} not found`) return {result: 'existing', app: fullSelectedApp} } 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 1b715f4ab68..2ea50a349d8 100644 --- a/packages/app/src/cli/models/app/app.test-data.ts +++ b/packages/app/src/cli/models/app/app.test-data.ts @@ -17,6 +17,7 @@ import { MinimalAppIdentifiers, OrganizationApp, MinimalOrganizationApp, + AppApiKeyAndOrgId, } from '../organization.js' import {RemoteSpecification} from '../../api/graphql/extension_specifications.js' import {ExtensionInstance} from '../extensions/extension-instance.js' @@ -1318,7 +1319,7 @@ export function testDeveloperPlatformClient(stubs: Partial Promise.resolve(testPartnersUserSession), refreshToken: () => Promise.resolve(testPartnersUserSession.token), accountInfo: () => Promise.resolve(testPartnersUserSession.accountInfo), - appFromId: (_app: MinimalAppIdentifiers) => Promise.resolve(testOrganizationApp()), + appFromIdentifiers: (_app: AppApiKeyAndOrgId) => Promise.resolve(testOrganizationApp()), organizations: () => Promise.resolve(organizationsResponse), orgFromId: (_organizationId: string) => Promise.resolve(testOrganization()), appsForOrg: (_organizationId: string) => Promise.resolve({apps: [testOrganizationApp()], hasMorePages: false}), diff --git a/packages/app/src/cli/models/app/app.ts b/packages/app/src/cli/models/app/app.ts index 9efb1c86aec..c423aa0d367 100644 --- a/packages/app/src/cli/models/app/app.ts +++ b/packages/app/src/cli/models/app/app.ts @@ -54,7 +54,6 @@ function removeTrailingPathSeparator(value: string[] | undefined) { */ export const AppSchema = zod.object({ client_id: zod.string(), - app_id: zod.string().optional(), organization_id: zod.string().optional(), build: zod .object({ diff --git a/packages/app/src/cli/models/organization.ts b/packages/app/src/cli/models/organization.ts index dee33504d99..65c46185273 100644 --- a/packages/app/src/cli/models/organization.ts +++ b/packages/app/src/cli/models/organization.ts @@ -12,12 +12,15 @@ export interface Organization { source?: OrganizationSource } -export interface MinimalAppIdentifiers { - id: string +export interface AppApiKeyAndOrgId { apiKey: string organizationId: string } +export type MinimalAppIdentifiers = AppApiKeyAndOrgId & { + id: string +} + export type MinimalOrganizationApp = MinimalAppIdentifiers & { title: string } diff --git a/packages/app/src/cli/services/app-context.test.ts b/packages/app/src/cli/services/app-context.test.ts index 507282a79e3..c6bc55bbcd5 100644 --- a/packages/app/src/cli/services/app-context.test.ts +++ b/packages/app/src/cli/services/app-context.test.ts @@ -1,7 +1,7 @@ import {linkedAppContext} from './app-context.js' import {fetchSpecifications} from './generate/fetch-extension-specifications.js' import link from './app/config/link.js' -import {appFromId} from './context.js' +import {appFromIdentifiers} from './context.js' import * as localStorage from './local-storage.js' import {fetchOrgFromId} from './dev/fetch.js' @@ -37,7 +37,7 @@ const mockRemoteApp = testOrganizationApp({ beforeEach(() => { vi.mocked(fetchSpecifications).mockResolvedValue([]) - vi.mocked(appFromId).mockResolvedValue(mockRemoteApp) + vi.mocked(appFromIdentifiers).mockResolvedValue(mockRemoteApp) vi.mocked(fetchOrgFromId).mockResolvedValue(mockOrganization) }) @@ -121,7 +121,7 @@ describe('linkedAppContext', () => { test('updates cached app info when remoteApp matches', async () => { await inTemporaryDirectory(async (tmp) => { // Given - vi.mocked(appFromId).mockResolvedValue({...mockRemoteApp, apiKey: 'test-api-key-new'}) + vi.mocked(appFromIdentifiers).mockResolvedValue({...mockRemoteApp, apiKey: 'test-api-key-new'}) const content = `client_id="test-api-key-new"` await writeAppConfig(tmp, content) localStorage.setCachedAppInfo({ @@ -159,7 +159,7 @@ describe('linkedAppContext', () => { await writeAppConfig(tmp, content) const newClientId = 'new-api-key' - vi.mocked(appFromId).mockResolvedValue({...mockRemoteApp, apiKey: newClientId}) + vi.mocked(appFromIdentifiers).mockResolvedValue({...mockRemoteApp, apiKey: newClientId}) // When const result = await linkedAppContext({ @@ -173,7 +173,7 @@ describe('linkedAppContext', () => { expect(link).not.toHaveBeenCalled() expect(result.remoteApp.apiKey).toBe(newClientId) expect(result.app.configuration.client_id).toEqual('new-api-key') - expect(appFromId).toHaveBeenCalledWith(expect.objectContaining({apiKey: newClientId})) + expect(appFromIdentifiers).toHaveBeenCalledWith(expect.objectContaining({apiKey: newClientId})) }) }) diff --git a/packages/app/src/cli/services/app-context.ts b/packages/app/src/cli/services/app-context.ts index 47b0dc08741..db2888d3f58 100644 --- a/packages/app/src/cli/services/app-context.ts +++ b/packages/app/src/cli/services/app-context.ts @@ -1,4 +1,4 @@ -import {appFromId} from './context.js' +import {appFromIdentifiers} from './context.js' import {getCachedAppInfo, setCachedAppInfo} from './local-storage.js' import {fetchSpecifications} from './generate/fetch-extension-specifications.js' import link from './app/config/link.js' @@ -74,8 +74,7 @@ export async function linkedAppContext({ if (!remoteApp) { const apiKey = configState.basicConfiguration.client_id const organizationId = configState.basicConfiguration.organization_id - const id = configState.basicConfiguration.app_id - remoteApp = await appFromId({apiKey, developerPlatformClient, organizationId, id}) + remoteApp = await appFromIdentifiers({apiKey, developerPlatformClient, organizationId}) } developerPlatformClient = remoteApp.developerPlatformClient ?? developerPlatformClient 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 417a72648c9..258ede171dc 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 @@ -1,7 +1,7 @@ import link from './link.js' import {testOrganizationApp, testDeveloperPlatformClient} from '../../../models/app/app.test-data.js' import {DeveloperPlatformClient, selectDeveloperPlatformClient} from '../../../utilities/developer-platform-client.js' -import {MinimalAppIdentifiers, OrganizationApp} from '../../../models/organization.js' +import {AppApiKeyAndOrgId, OrganizationApp} from '../../../models/organization.js' import {appNamePrompt, createAsNewAppPrompt, selectOrganizationPrompt} from '../../../prompts/dev.js' import {beforeEach, describe, expect, test, vi} from 'vitest' import {inTemporaryDirectory, readFile, writeFileSync} from '@shopify/cli-kit/node/fs' @@ -18,7 +18,7 @@ beforeEach(async () => {}) function buildDeveloperPlatformClient(): DeveloperPlatformClient { return testDeveloperPlatformClient({ - async appFromId({apiKey}: MinimalAppIdentifiers): Promise { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId): Promise { switch (apiKey) { case 'api-key': return testOrganizationApp({developerPlatformClient: this as DeveloperPlatformClient}) @@ -89,7 +89,6 @@ embedded = false ` expect(configuration).toEqual({ client_id: 'api-key', - app_id: '1', name: 'app1', application_url: '', embedded: true, 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 7f82e9cf5e0..7bc7f61bc81 100644 --- a/packages/app/src/cli/services/app/config/link.test.ts +++ b/packages/app/src/cli/services/app/config/link.test.ts @@ -8,12 +8,12 @@ import { } from '../../../models/app/app.test-data.js' import {selectConfigName} from '../../../prompts/config.js' import {loadApp} from '../../../models/app/loader.js' -import {InvalidApiKeyErrorMessage, fetchOrCreateOrganizationApp, appFromId} from '../../context.js' +import {InvalidApiKeyErrorMessage, fetchOrCreateOrganizationApp, appFromIdentifiers} from '../../context.js' import {getCachedCommandInfo} from '../../local-storage.js' import {AppInterface, CurrentAppConfiguration} from '../../../models/app/app.js' import {fetchAppRemoteConfiguration} from '../select-app.js' import {DeveloperPlatformClient} from '../../../utilities/developer-platform-client.js' -import {MinimalAppIdentifiers, OrganizationApp} from '../../../models/organization.js' +import {MinimalAppIdentifiers, AppApiKeyAndOrgId, OrganizationApp} from '../../../models/organization.js' import {beforeEach, describe, expect, test, vi} from 'vitest' import {fileExistsSync, inTemporaryDirectory, readFile, writeFileSync} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' @@ -49,7 +49,7 @@ const DEFAULT_REMOTE_CONFIGURATION = { function buildDeveloperPlatformClient(): DeveloperPlatformClient { return testDeveloperPlatformClient({ - async appFromId({apiKey}: MinimalAppIdentifiers): Promise { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId): Promise { switch (apiKey) { case 'api-key': return testOrganizationApp({developerPlatformClient: this as DeveloperPlatformClient}) @@ -85,7 +85,6 @@ describe('link', () => { expect(fileExistsSync(joinPath(tmp, 'shopify.app.default-value.toml'))).toBeTruthy() expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', extension_directories: [], application_url: 'https://example.com', @@ -165,7 +164,6 @@ embedded = false ` expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', extension_directories: [], application_url: 'https://example.com', @@ -274,7 +272,6 @@ embedded = false }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -407,7 +404,6 @@ url = "https://api-client-config.com/preferences" }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'new-title', application_url: 'https://api-client-config.com', embedded: false, @@ -539,7 +535,6 @@ embedded = false }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'my app', application_url: 'https://myapp.com', embedded: true, @@ -632,7 +627,6 @@ embedded = false ` expect(configuration).toEqual({ client_id: 'different-api-key', - app_id: '1', name: 'my app', application_url: 'https://myapp.com', embedded: true, @@ -713,7 +707,6 @@ embedded = false }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', extension_directories: [], name: 'app1', application_url: 'https://example.com', @@ -780,7 +773,6 @@ embedded = false expect(renderSuccess).not.toHaveBeenCalled() expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -814,8 +806,8 @@ test('fetches the remote app when an api key is provided', async () => { } vi.mocked(loadApp).mockResolvedValue(await mockApp(tmp)) vi.mocked(selectConfigName).mockResolvedValue('shopify.app.staging.toml') - vi.mocked(appFromId).mockImplementation(async ({apiKey}: {apiKey: string}) => { - return (await developerPlatformClient.appFromId({id: apiKey, apiKey, organizationId: '1'}))! + vi.mocked(appFromIdentifiers).mockImplementation(async ({apiKey}: {apiKey: string}) => { + return (await developerPlatformClient.appFromIdentifiers({apiKey, organizationId: '1'}))! }) // When @@ -826,7 +818,6 @@ test('fetches the remote app when an api key is provided', async () => { expect(content).toContain('name = "app1"') expect(configuration).toEqual({ client_id: 'api-key', - app_id: '1', extension_directories: [], name: 'app1', application_url: 'https://example.com', @@ -934,7 +925,6 @@ embedded = false ` expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -996,7 +986,6 @@ embedded = false expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -1063,7 +1052,6 @@ embedded = false expect(configuration).toEqual({ client_id: '12345', - app_id: '1', extension_directories: [], name: 'app1', application_url: 'https://example.com', @@ -1186,7 +1174,6 @@ embedded = false }) expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://example.com', embedded: true, @@ -1311,7 +1298,6 @@ embedded = false expect(configuration).toEqual({ client_id: '12345', - app_id: '1', name: 'app1', application_url: 'https://my-app-url.com', embedded: true, diff --git a/packages/app/src/cli/services/app/config/link.ts b/packages/app/src/cli/services/app/config/link.ts index a10bc64ed5a..2d147f594b7 100644 --- a/packages/app/src/cli/services/app/config/link.ts +++ b/packages/app/src/cli/services/app/config/link.ts @@ -20,7 +20,7 @@ import { import { fetchOrCreateOrganizationApp, logMetadataForLoadedContext, - appFromId, + appFromIdentifiers, InvalidApiKeyErrorMessage, } from '../../context.js' import { @@ -135,7 +135,7 @@ async function selectOrCreateRemoteAppToLinkTo(options: LinkOptions): Promise<{ if (options.apiKey) { // Remote API Key provided by the caller, so use that app specifically - const remoteApp = await appFromId({ + const remoteApp = await appFromIdentifiers({ apiKey: options.apiKey, id: options.appId, developerPlatformClient, @@ -387,7 +387,6 @@ async function overwriteLocalConfigFileWithRemoteAppConfiguration(options: { ...(localAppOptions.existingConfig ?? {}), }, { - app_id: remoteApp.id, client_id: remoteApp.apiKey, path: configFilePath, ...(developerPlatformClient.requiresOrganization ? {organization_id: remoteApp.organizationId} : {}), diff --git a/packages/app/src/cli/services/app/config/use.test.ts b/packages/app/src/cli/services/app/config/use.test.ts index 0adddfb0b4a..d8069bc188c 100644 --- a/packages/app/src/cli/services/app/config/use.test.ts +++ b/packages/app/src/cli/services/app/config/use.test.ts @@ -9,7 +9,7 @@ import { import {getAppConfigurationFileName, loadAppConfiguration} from '../../../models/app/loader.js' import {clearCurrentConfigFile, setCachedAppInfo} from '../../local-storage.js' import {selectConfigFile} from '../../../prompts/config.js' -import {appFromId, logMetadataForLoadedContext} from '../../context.js' +import {appFromIdentifiers, logMetadataForLoadedContext} from '../../context.js' import {describe, expect, test, vi} from 'vitest' import {inTemporaryDirectory, writeFileSync} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' @@ -303,7 +303,7 @@ describe('use', () => { remoteFlags: [], }) vi.mocked(getAppConfigurationFileName).mockReturnValue('shopify.app.something.toml') - vi.mocked(appFromId).mockResolvedValue(REMOTE_APP) + vi.mocked(appFromIdentifiers).mockResolvedValue(REMOTE_APP) createConfigFile(directory, 'shopify.app.something.toml') const options = {directory, configName: 'something', developerPlatformClient: testDeveloperPlatformClient()} diff --git a/packages/app/src/cli/services/app/write-app-configuration-file.test.ts b/packages/app/src/cli/services/app/write-app-configuration-file.test.ts index 2931fb28139..2506dc3cbd8 100644 --- a/packages/app/src/cli/services/app/write-app-configuration-file.test.ts +++ b/packages/app/src/cli/services/app/write-app-configuration-file.test.ts @@ -149,51 +149,4 @@ url = "https://example.com/prefs" expect(content).toContain('redirect_urls') }) }) - - test('includes app_id if organization_id is present', async () => { - await inTemporaryDirectory(async (tmp) => { - // Given - const filePath = joinPath(tmp, 'shopify.app.toml') - const {schema} = await buildVersionedAppSchema() - - // When - await writeAppConfigurationFile( - { - ...FULL_CONFIGURATION, - app_id: '1234', - organization_id: '1', - path: filePath, - } as CurrentAppConfiguration, - schema, - ) - - // Then - const content = await readFile(filePath) - expect(content).toContain('app_id') - expect(content).toContain('organization_id') - }) - }) - - test('does not include app_id if organization_id is absent', async () => { - await inTemporaryDirectory(async (tmp) => { - // Given - const filePath = joinPath(tmp, 'shopify.app.toml') - const {schema} = await buildVersionedAppSchema() - - // When - await writeAppConfigurationFile( - { - ...FULL_CONFIGURATION, - app_id: '1234', - path: filePath, - } as CurrentAppConfiguration, - schema, - ) - - // Then - const content = await readFile(filePath) - expect(content).not.toContain('app_id') - expect(content).not.toContain('organization_id') - }) - }) }) diff --git a/packages/app/src/cli/services/app/write-app-configuration-file.ts b/packages/app/src/cli/services/app/write-app-configuration-file.ts index 7d5b3f848b0..4dd48d98454 100644 --- a/packages/app/src/cli/services/app/write-app-configuration-file.ts +++ b/packages/app/src/cli/services/app/write-app-configuration-file.ts @@ -28,29 +28,18 @@ export async function writeAppConfigurationFile(configuration: CurrentAppConfigu } export const rewriteConfiguration = (schema: T, config: unknown): unknown => { - // Remove app_id if organization_id is not present. - // This will become unnecessary when we remove app_id from App Management apps. - let configCopy = config - if (typeof config === 'object' && config !== null && config !== undefined) { - if ('app_id' in config && !('organization_id' in config)) { - // eslint-disable-next-line @typescript-eslint/naming-convention - const {app_id, ...rest} = config - configCopy = rest - } - } - if (schema === null || schema === undefined) return null if (schema instanceof zod.ZodNullable || schema instanceof zod.ZodOptional) - return rewriteConfiguration(schema.unwrap(), configCopy) + return rewriteConfiguration(schema.unwrap(), config) if (schema instanceof zod.ZodArray) { - return (configCopy as unknown[]).map((item) => rewriteConfiguration(schema.element, item)) + return (config as unknown[]).map((item) => rewriteConfiguration(schema.element, item)) } if (schema instanceof zod.ZodEffects) { - return rewriteConfiguration(schema._def.schema, configCopy) + return rewriteConfiguration(schema._def.schema, config) } if (schema instanceof zod.ZodObject) { const entries = Object.entries(schema.shape) - const confObj = configCopy as {[key: string]: unknown} + const confObj = config as {[key: string]: unknown} let result: {[key: string]: unknown} = {} entries.forEach(([key, subSchema]) => { if (confObj !== undefined && confObj[key] !== undefined) { diff --git a/packages/app/src/cli/services/context.test.ts b/packages/app/src/cli/services/context.test.ts index f9881da95b9..9cd9a9be202 100644 --- a/packages/app/src/cli/services/context.test.ts +++ b/packages/app/src/cli/services/context.test.ts @@ -11,6 +11,7 @@ import * as patchAppConfigurationFile from './app/patch-app-configuration-file.j import {DeployOptions} from './deploy.js' import { MinimalAppIdentifiers, + AppApiKeyAndOrgId, Organization, OrganizationApp, OrganizationSource, @@ -100,7 +101,7 @@ const deployOptions = (app: AppLinkedInterface, reset = false, force = false): D function buildDeveloperPlatformClient(extras?: Partial): DeveloperPlatformClient { return testDeveloperPlatformClient({ ...extras, - async appFromId({apiKey}: MinimalAppIdentifiers) { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId) { for (const app of [APP1, APP2]) { if (apiKey === app.apiKey) return app } diff --git a/packages/app/src/cli/services/context.ts b/packages/app/src/cli/services/context.ts index 9748d5c1d52..09be435baf3 100644 --- a/packages/app/src/cli/services/context.ts +++ b/packages/app/src/cli/services/context.ts @@ -51,7 +51,7 @@ interface AppFromIdOptions { developerPlatformClient: DeveloperPlatformClient } -export const appFromId = async (options: AppFromIdOptions): Promise => { +export const appFromIdentifiers = async (options: AppFromIdOptions): Promise => { let organizationId = options.organizationId let developerPlatformClient = options.developerPlatformClient if (!organizationId) { @@ -62,8 +62,7 @@ export const appFromId = async (options: AppFromIdOptions): Promise ({...APP1, newApp: true}), - async appFromId({apiKey}: MinimalAppIdentifiers) { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId) { if (apiKey === APP1.apiKey) return APP1 if (apiKey === APP2.apiKey) return APP2 throw new Error(`App with client ID ${apiKey} not found`) diff --git a/packages/app/src/cli/services/dev/select-app.ts b/packages/app/src/cli/services/dev/select-app.ts index 548be40fe7c..41e1aabaea0 100644 --- a/packages/app/src/cli/services/dev/select-app.ts +++ b/packages/app/src/cli/services/dev/select-app.ts @@ -45,7 +45,7 @@ export async function selectOrCreateApp( if (selectedToml) setCachedCommandTomlPreference(selectedToml) - const fullSelectedApp = await developerPlatformClient.appFromId(app) + const fullSelectedApp = await developerPlatformClient.appFromIdentifiers(app) if (!fullSelectedApp) { // This is unlikely, and a bug. But we still want a nice user facing message plus appropriate context logged. diff --git a/packages/app/src/cli/services/generate-schema.test.ts b/packages/app/src/cli/services/generate-schema.test.ts index 2c1aa79dced..0551d827763 100644 --- a/packages/app/src/cli/services/generate-schema.test.ts +++ b/packages/app/src/cli/services/generate-schema.test.ts @@ -122,7 +122,6 @@ describe('generateSchemaService', () => { }, app.configuration.client_id, orgId, - app.configuration.app_id, ) }) }) @@ -179,7 +178,6 @@ describe('generateSchemaService', () => { }, app.configuration.client_id, orgId, - app.configuration.app_id, ) }) }) diff --git a/packages/app/src/cli/services/generate-schema.ts b/packages/app/src/cli/services/generate-schema.ts index a0d544ff8aa..4c81daaa679 100644 --- a/packages/app/src/cli/services/generate-schema.ts +++ b/packages/app/src/cli/services/generate-schema.ts @@ -21,7 +21,6 @@ interface GenerateSchemaOptions { export async function generateSchemaService(options: GenerateSchemaOptions) { const {extension, stdout, developerPlatformClient, app, orgId} = options const apiKey = app.configuration.client_id - const appId = app.configuration.app_id const {api_version: version, type, targeting} = extension.configuration const usingTargets = Boolean(targeting?.length) const definition = await (usingTargets @@ -29,7 +28,6 @@ export async function generateSchemaService(options: GenerateSchemaOptions) { localIdentifier: extension.localIdentifier, developerPlatformClient, apiKey, - appId, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion target: targeting![0]!.target, version, @@ -39,7 +37,6 @@ export async function generateSchemaService(options: GenerateSchemaOptions) { localIdentifier: extension.localIdentifier, developerPlatformClient, apiKey, - appId, type, version, orgId, @@ -58,7 +55,6 @@ interface BaseGenerateSchemaOptions { localIdentifier: string developerPlatformClient: DeveloperPlatformClient apiKey: string - appId?: string version: string orgId: string } @@ -70,7 +66,6 @@ interface GenerateSchemaFromTargetOptions extends BaseGenerateSchemaOptions { async function generateSchemaFromTarget({ localIdentifier, developerPlatformClient, - appId, apiKey, target, version, @@ -81,7 +76,7 @@ async function generateSchemaFromTarget({ version, } // Api key required for partners reqs, can be removed once fully migrated to AMF - const definition = await developerPlatformClient.targetSchemaDefinition(variables, apiKey, orgId, appId) + const definition = await developerPlatformClient.targetSchemaDefinition(variables, apiKey, orgId) if (!definition) { throw new AbortError( @@ -101,7 +96,6 @@ async function generateSchemaFromApiType({ localIdentifier, developerPlatformClient, apiKey, - appId, version, type, orgId, @@ -111,7 +105,7 @@ async function generateSchemaFromApiType({ type, } - const definition = await developerPlatformClient.apiSchemaDefinition(variables, apiKey, orgId, appId) + const definition = await developerPlatformClient.apiSchemaDefinition(variables, apiKey, orgId) if (!definition) { throw new AbortError( diff --git a/packages/app/src/cli/services/info.test.ts b/packages/app/src/cli/services/info.test.ts index ce2f958712e..15e021e008d 100644 --- a/packages/app/src/cli/services/info.test.ts +++ b/packages/app/src/cli/services/info.test.ts @@ -1,6 +1,6 @@ import {InfoOptions, info} from './info.js' import {AppInterface, AppLinkedInterface} from '../models/app/app.js' -import {MinimalAppIdentifiers, OrganizationApp} from '../models/organization.js' +import {AppApiKeyAndOrgId, OrganizationApp} from '../models/organization.js' import {selectOrganizationPrompt} from '../prompts/dev.js' import { testDeveloperPlatformClient, @@ -34,7 +34,7 @@ const ORG1 = { function buildDeveloperPlatformClient(): DeveloperPlatformClient { return testDeveloperPlatformClient({ - async appFromId({apiKey}: MinimalAppIdentifiers): Promise { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId): Promise { switch (apiKey) { case '123': return APP1 diff --git a/packages/app/src/cli/utilities/developer-platform-client.ts b/packages/app/src/cli/utilities/developer-platform-client.ts index e1eb8f1c973..7a8673be6c4 100644 --- a/packages/app/src/cli/utilities/developer-platform-client.ts +++ b/packages/app/src/cli/utilities/developer-platform-client.ts @@ -3,6 +3,7 @@ import {AppManagementClient} from './developer-platform-client/app-management-cl import {PartnersSession} from '../../cli/services/context/partner-account-info.js' import { MinimalAppIdentifiers, + AppApiKeyAndOrgId, MinimalOrganizationApp, Organization, OrganizationApp, @@ -213,7 +214,7 @@ export interface DeveloperPlatformClient { session: () => Promise refreshToken: () => Promise accountInfo: () => Promise - appFromId: (app: MinimalAppIdentifiers) => Promise + appFromIdentifiers: (app: AppApiKeyAndOrgId) => Promise organizations: () => Promise orgFromId: (orgId: string) => Promise orgAndApps: (orgId: string) => Promise> @@ -252,13 +253,11 @@ export interface DeveloperPlatformClient { input: SchemaDefinitionByTargetQueryVariables, apiKey: string, organizationId: string, - appId?: string, ) => Promise apiSchemaDefinition: ( input: SchemaDefinitionByApiTypeQueryVariables, apiKey: string, organizationId: string, - appId?: string, ) => Promise migrateToUiExtension: (input: MigrateToUiExtensionVariables) => Promise toExtensionGraphQLType: (input: string) => string 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 03b1efaca3b..a4c0d52fa54 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 @@ -21,6 +21,7 @@ import { import {PartnersSession} from '../../services/context/partner-account-info.js' import { MinimalAppIdentifiers, + AppApiKeyAndOrgId, MinimalOrganizationApp, Organization, OrganizationApp, @@ -88,10 +89,10 @@ import { ListAppDevStoresQuery, } from '../../api/graphql/business-platform-organizations/generated/list_app_dev_stores.js' import { - ActiveAppRelease, ActiveAppReleaseQuery, ReleasedAppModuleFragment, } from '../../api/graphql/app-management/generated/active-app-release.js' +import {ActiveAppReleaseFromApiKey} from '../../api/graphql/app-management/generated/active-app-release-from-api-key.js' import {ReleaseVersion} from '../../api/graphql/app-management/generated/release-version.js' import {CreateAppVersion} from '../../api/graphql/app-management/generated/create-app-version.js' import {CreateAssetUrl} from '../../api/graphql/app-management/generated/create-asset-url.js' @@ -217,7 +218,7 @@ export class AppManagementClient implements DeveloperPlatformClient { return (await this.session()).accountInfo } - async appFromId(appIdentifiers: MinimalAppIdentifiers): Promise { + async appFromIdentifiers(appIdentifiers: AppApiKeyAndOrgId): Promise { const {app} = await this.activeAppVersionRawResult(appIdentifiers) const {name, appModules} = app.activeRelease.version const appAccessModule = appModules.find((mod) => mod.specification.externalIdentifier === 'app_access') @@ -789,12 +790,12 @@ export class AppManagementClient implements DeveloperPlatformClient { async targetSchemaDefinition( input: SchemaDefinitionByTargetQueryVariables, - _apiKey: string, + apiKey: string, organizationId: string, - appId?: string, ): Promise { try { - const appIdNumber = String(numberFromGid(appId!)) + const {app} = await this.activeAppVersionRawResult({apiKey, organizationId}) + const appIdNumber = String(numberFromGid(app.id)) const token = await this.token() const result = await functionsRequestDoc( organizationId, @@ -815,12 +816,12 @@ export class AppManagementClient implements DeveloperPlatformClient { async apiSchemaDefinition( input: SchemaDefinitionByApiTypeQueryVariables, - _apiKey: string, + apiKey: string, organizationId: string, - appId?: string, ): Promise { try { - const appIdNumber = String(numberFromGid(appId!)) + const {app} = await this.activeAppVersionRawResult({apiKey, organizationId}) + const appIdNumber = String(numberFromGid(app.id)) const token = await this.token() const result = await functionsRequestDoc( organizationId, @@ -871,8 +872,8 @@ export class AppManagementClient implements DeveloperPlatformClient { ) } - private async activeAppVersionRawResult({id, organizationId}: MinimalAppIdentifiers): Promise { - return appManagementRequestDoc(organizationId, ActiveAppRelease, await this.token(), {appId: id}) + private async activeAppVersionRawResult({organizationId, apiKey}: AppApiKeyAndOrgId): Promise { + return appManagementRequestDoc(organizationId, ActiveAppReleaseFromApiKey, await this.token(), {apiKey}) } private async organizationBetaFlags( 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 72230b2e295..4255903a0d7 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 @@ -15,6 +15,7 @@ import { import {fetchCurrentAccountInformation, PartnersSession} from '../../../cli/services/context/partner-account-info.js' import { MinimalAppIdentifiers, + AppApiKeyAndOrgId, MinimalOrganizationApp, Organization, OrganizationApp, @@ -263,7 +264,7 @@ export class PartnersClient implements DeveloperPlatformClient { return (await this.session()).accountInfo } - async appFromId({apiKey}: MinimalAppIdentifiers): Promise { + async appFromIdentifiers({apiKey}: AppApiKeyAndOrgId): Promise { const variables: FindAppQueryVariables = {apiKey} const res: FindAppQuerySchema = await this.request(FindAppQuery, variables) const app = res.app @@ -509,7 +510,6 @@ export class PartnersClient implements DeveloperPlatformClient { input: SchemaDefinitionByTargetQueryVariables, apiKey: string, _organizationId: string, - _appId?: string, ): Promise { // Ensures compatibility with existing partners requests // Can remove once migrated to AMF