diff --git a/packages/app/src/cli/prompts/config.ts b/packages/app/src/cli/prompts/config.ts index 25f9f003a99..a605dac8934 100644 --- a/packages/app/src/cli/prompts/config.ts +++ b/packages/app/src/cli/prompts/config.ts @@ -1,11 +1,8 @@ /* eslint-disable no-await-in-loop */ -import {AppSchema, CurrentAppConfiguration} from '../models/app/app.js' -import {rewriteConfiguration} from '../services/app/write-app-configuration-file.js' import {AppConfigurationFileName} from '../models/app/loader.js' import { RenderTextPromptOptions, renderConfirmationPrompt, - renderInfo, renderSelectPrompt, renderTextPrompt, } from '@shopify/cli-kit/node/ui' @@ -13,10 +10,7 @@ import {fileExists, glob} from '@shopify/cli-kit/node/fs' import {basename, joinPath} from '@shopify/cli-kit/node/path' import {slugify} from '@shopify/cli-kit/common/string' import {err, ok, Result} from '@shopify/cli-kit/node/result' -import {encodeToml} from '@shopify/cli-kit/node/toml' -import {deepCompare, deepDifference} from '@shopify/cli-kit/common/object' import colors from '@shopify/cli-kit/node/colors' -import {zod} from '@shopify/cli-kit/node/schema' export async function selectConfigName(directory: string, defaultName = ''): Promise { const namePromptOptions = buildTextPromptOptions(defaultName) @@ -82,25 +76,3 @@ export function validate(value: string): string | undefined { // Max filename size for Windows/Mac including the prefix/postfix if (result.length > 238) return 'The file name is too long.' } - -export function buildDiffConfigContent( - localConfig: CurrentAppConfiguration, - remoteConfig: unknown, - schema: zod.ZodTypeAny = AppSchema, - renderNoChanges = true, -) { - const [updated, baseline] = deepDifference( - {...(rewriteConfiguration(schema, localConfig) as object), build: undefined}, - {...(rewriteConfiguration(schema, remoteConfig) as object), build: undefined}, - ) - - if (deepCompare(updated, baseline)) { - if (renderNoChanges) renderInfo({headline: 'No changes to update.'}) - return undefined - } - - return { - baselineContent: encodeToml(baseline), - updatedContent: encodeToml(updated), - } -} diff --git a/packages/app/src/cli/prompts/dev.test.ts b/packages/app/src/cli/prompts/dev.test.ts index 2e30c71d809..ebc26905124 100644 --- a/packages/app/src/cli/prompts/dev.test.ts +++ b/packages/app/src/cli/prompts/dev.test.ts @@ -10,6 +10,7 @@ import { import {Organization, OrganizationStore} from '../models/organization.js' import {testDeveloperPlatformClient, testOrganizationApp} from '../models/app/app.test-data.js' import {getTomls} from '../utilities/app/config/getTomls.js' +import {searchForAppsByNameFactory} from '../services/dev/prompt-helpers.js' import {describe, expect, vi, test, beforeEach} from 'vitest' import {renderAutocompletePrompt, renderConfirmationPrompt, renderTextPrompt} from '@shopify/cli-kit/node/ui' import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' @@ -92,7 +93,7 @@ describe('selectApp', () => { vi.mocked(renderAutocompletePrompt).mockResolvedValue(APP2.apiKey) // When - const got = await selectAppPrompt(testDeveloperPlatformClient(), apps, true, ORG1.id) + const got = await selectAppPrompt(searchForAppsByNameFactory(testDeveloperPlatformClient(), ORG1.id), apps, true) // Then expect(got).toEqual(APP2) @@ -116,7 +117,7 @@ describe('selectApp', () => { const apps = [APP1, APP2] vi.mocked(renderAutocompletePrompt).mockResolvedValue(APP2.apiKey) - const got = await selectAppPrompt(testDeveloperPlatformClient(), apps, true, ORG1.id, { + const got = await selectAppPrompt(searchForAppsByNameFactory(testDeveloperPlatformClient(), ORG1.id), apps, true, { directory: '/', }) diff --git a/packages/app/src/cli/prompts/dev.ts b/packages/app/src/cli/prompts/dev.ts index 9b749e45490..1a086f87838 100644 --- a/packages/app/src/cli/prompts/dev.ts +++ b/packages/app/src/cli/prompts/dev.ts @@ -1,7 +1,6 @@ import {Organization, MinimalOrganizationApp, OrganizationStore, MinimalAppIdentifiers} from '../models/organization.js' import {getTomls} from '../utilities/app/config/getTomls.js' import {setCachedCommandTomlMap} from '../services/local-storage.js' -import {DeveloperPlatformClient} from '../utilities/developer-platform-client.js' import {renderAutocompletePrompt, renderConfirmationPrompt, renderTextPrompt} from '@shopify/cli-kit/node/ui' import {outputCompleted} from '@shopify/cli-kit/node/output' @@ -18,10 +17,9 @@ export async function selectOrganizationPrompt(organizations: Organization[]): P } export async function selectAppPrompt( - developerPlatformClient: DeveloperPlatformClient, + onSearchForAppsByName: (term: string) => Promise<{apps: MinimalOrganizationApp[]; hasMorePages: boolean}>, apps: MinimalOrganizationApp[], hasMorePages: boolean, - orgId: string, options?: { directory?: string }, @@ -45,7 +43,7 @@ export async function selectAppPrompt( choices: currentAppChoices.map(toAnswer), hasMorePages, search: async (term) => { - const result = await developerPlatformClient.appsForOrg(orgId, term) + const result = await onSearchForAppsByName(term) currentAppChoices = result.apps return { diff --git a/packages/app/src/cli/services/app/select-app.ts b/packages/app/src/cli/services/app/select-app.ts index a1bdfe1c1e3..f57f4403296 100644 --- a/packages/app/src/cli/services/app/select-app.ts +++ b/packages/app/src/cli/services/app/select-app.ts @@ -9,13 +9,18 @@ import { selectDeveloperPlatformClient, } from '../../utilities/developer-platform-client.js' import {selectOrg} from '../context.js' +import {searchForAppsByNameFactory} from '../dev/prompt-helpers.js' import {deepMergeObjects} from '@shopify/cli-kit/common/object' export async function selectApp(): Promise { const org = await selectOrg() const developerPlatformClient = selectDeveloperPlatformClient({organization: org}) const {apps, hasMorePages} = await developerPlatformClient.appsForOrg(org.id) - const selectedApp = await selectAppPrompt(developerPlatformClient, apps, hasMorePages, org.id) + const selectedApp = await selectAppPrompt( + searchForAppsByNameFactory(developerPlatformClient, org.id), + apps, + hasMorePages, + ) const fullSelectedApp = await developerPlatformClient.appFromId(selectedApp) return fullSelectedApp! } diff --git a/packages/app/src/cli/services/context/breakdown-extensions.ts b/packages/app/src/cli/services/context/breakdown-extensions.ts index bf0cfb851b1..76c26bb5704 100644 --- a/packages/app/src/cli/services/context/breakdown-extensions.ts +++ b/packages/app/src/cli/services/context/breakdown-extensions.ts @@ -4,7 +4,6 @@ import {versionDiffByVersion} from '../release/version-diff.js' import {AppVersionsDiffExtensionSchema} from '../../api/graphql/app_versions_diff.js' import {AppInterface, CurrentAppConfiguration, filterNonVersionedAppFields} from '../../models/app/app.js' import {MinimalOrganizationApp} from '../../models/organization.js' -import {buildDiffConfigContent} from '../../prompts/config.js' import {IdentifiersExtensions} from '../../models/app/identifiers.js' import { extensionTypeStrategy, @@ -17,6 +16,11 @@ import { RemoteExtensionRegistrations, } from '../../api/graphql/all_app_extension_registrations.js' import {ExtensionSpecification} from '../../models/extensions/specification.js' +import {rewriteConfiguration} from '../app/write-app-configuration-file.js' +import {SpecsAppConfiguration} from '../../models/extensions/specifications/types/app_config.js' +import {deepCompare, deepDifference} from '@shopify/cli-kit/common/object' +import {encodeToml} from '@shopify/cli-kit/node/toml' +import {zod} from '@shopify/cli-kit/node/schema' export interface ConfigExtensionIdentifiersBreakdown { existingFieldNames: string[] @@ -154,7 +158,7 @@ async function resolveRemoteConfigExtensionIdentifiersBreakdown( app: AppInterface, versionAppModules?: AppModuleVersion[], ) { - const remoteConfig = + const remoteConfig: Partial = (await fetchAppRemoteConfiguration( remoteApp, developerPlatformClient, @@ -168,7 +172,6 @@ async function resolveRemoteConfigExtensionIdentifiersBreakdown( baselineConfig as CurrentAppConfiguration, remoteConfig, app.configSchema, - false, ) // List of field included in the config except the ones that only affect the CLI and are not pushed to the server @@ -208,6 +211,26 @@ async function resolveRemoteConfigExtensionIdentifiersBreakdown( } } +function buildDiffConfigContent( + localConfig: CurrentAppConfiguration, + remoteConfig: Partial, + schema: zod.ZodTypeAny, +) { + const [updated, baseline] = deepDifference( + {...(rewriteConfiguration(schema, localConfig) as object), build: undefined}, + {...(rewriteConfiguration(schema, remoteConfig) as object), build: undefined}, + ) + + if (deepCompare(updated, baseline)) { + return undefined + } + + return { + baselineContent: encodeToml(baseline), + updatedContent: encodeToml(updated), + } +} + /** * This method extracts the list of global fields or global sections from the string that represents a toml section like * this: diff --git a/packages/app/src/cli/services/dev/prompt-helpers.ts b/packages/app/src/cli/services/dev/prompt-helpers.ts new file mode 100644 index 00000000000..5e3d758785f --- /dev/null +++ b/packages/app/src/cli/services/dev/prompt-helpers.ts @@ -0,0 +1,8 @@ +import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js' + +export function searchForAppsByNameFactory(developerPlatformClient: DeveloperPlatformClient, orgId: string) { + return async (term: string) => { + const result = await developerPlatformClient.appsForOrg(orgId, term) + return {apps: result.apps, hasMorePages: result.hasMorePages} + } +} diff --git a/packages/app/src/cli/services/dev/select-app.test.ts b/packages/app/src/cli/services/dev/select-app.test.ts index 9640b5487de..753cd4e0dfb 100644 --- a/packages/app/src/cli/services/dev/select-app.test.ts +++ b/packages/app/src/cli/services/dev/select-app.test.ts @@ -62,7 +62,7 @@ describe('selectOrCreateApp', () => { // Then expect(got).toEqual(APP1) - expect(selectAppPrompt).toHaveBeenCalledWith(developerPlatformClient, APPS, false, ORG1.id, { + expect(selectAppPrompt).toHaveBeenCalledWith(expect.any(Function), APPS, false, { directory: undefined, }) }) diff --git a/packages/app/src/cli/services/dev/select-app.ts b/packages/app/src/cli/services/dev/select-app.ts index a2d6e55e363..ef89d386add 100644 --- a/packages/app/src/cli/services/dev/select-app.ts +++ b/packages/app/src/cli/services/dev/select-app.ts @@ -1,3 +1,4 @@ +import {searchForAppsByNameFactory} from './prompt-helpers.js' import {appNamePrompt, createAsNewAppPrompt, selectAppPrompt} from '../../prompts/dev.js' import {Organization, MinimalOrganizationApp, OrganizationApp} from '../../models/organization.js' import {getCachedCommandInfo, setCachedCommandTomlPreference} from '../local-storage.js' @@ -35,7 +36,7 @@ export async function selectOrCreateApp( const name = await appNamePrompt(localAppName) return developerPlatformClient.createApp(org, name, options) } else { - const app = await selectAppPrompt(developerPlatformClient, apps, hasMorePages, org.id, { + const app = await selectAppPrompt(searchForAppsByNameFactory(developerPlatformClient, org.id), apps, hasMorePages, { directory: options?.directory, })