From 23133250b520800386761a26792a12bcc8776149 Mon Sep 17 00:00:00 2001 From: Gonzalo Riestra Date: Mon, 25 May 2026 14:21:54 +0200 Subject: [PATCH] Allow app config link to target config by client ID --- .../src/cli/commands/app/config/link.test.ts | 37 +++++++++++++++++++ .../app/src/cli/commands/app/config/link.ts | 6 +++ packages/cli/README.md | 2 +- packages/cli/oclif.manifest.json | 3 -- 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 packages/app/src/cli/commands/app/config/link.test.ts diff --git a/packages/app/src/cli/commands/app/config/link.test.ts b/packages/app/src/cli/commands/app/config/link.test.ts new file mode 100644 index 00000000000..0e0a731ae4c --- /dev/null +++ b/packages/app/src/cli/commands/app/config/link.test.ts @@ -0,0 +1,37 @@ +import ConfigLink from './link.js' +import link from '../../../services/app/config/link.js' +import {linkedAppContext} from '../../../services/app-context.js' +import {testAppLinked, testOrganizationApp} from '../../../models/app/app.test-data.js' +import {inTemporaryDirectory} from '@shopify/cli-kit/node/fs' +import {describe, expect, test, vi} from 'vitest' + +vi.mock('../../../services/app/config/link.js') +vi.mock('../../../services/app-context.js') + +describe('app config link command', () => { + test('accepts --client-id with --config to link a specific app to a specific config file', async () => { + await inTemporaryDirectory(async (tmp) => { + const app = testAppLinked() + vi.mocked(link).mockResolvedValue({ + remoteApp: testOrganizationApp(), + configFileName: 'shopify.app.staging.toml', + configuration: app.configuration, + }) + vi.mocked(linkedAppContext).mockResolvedValue({app} as Awaited>) + + await ConfigLink.run(['--path', tmp, '--client-id', 'api-key', '--config', 'staging'], import.meta.url) + + expect(link).toHaveBeenCalledWith({ + directory: tmp, + apiKey: 'api-key', + configName: 'staging', + }) + expect(linkedAppContext).toHaveBeenCalledWith({ + directory: tmp, + clientId: undefined, + forceRelink: false, + userProvidedConfigName: 'shopify.app.staging.toml', + }) + }) + }) +}) diff --git a/packages/app/src/cli/commands/app/config/link.ts b/packages/app/src/cli/commands/app/config/link.ts index 1783c844eba..363c357f2fa 100644 --- a/packages/app/src/cli/commands/app/config/link.ts +++ b/packages/app/src/cli/commands/app/config/link.ts @@ -3,6 +3,7 @@ import {linkedAppContext} from '../../../services/app-context.js' import link, {LinkOptions} from '../../../services/app/config/link.js' import AppLinkedCommand, {AppLinkedCommandOutput} from '../../../utilities/app-linked-command.js' import {globalFlags} from '@shopify/cli-kit/node/cli' +import {Flags} from '@oclif/core' export default class ConfigLink extends AppLinkedCommand { static summary = 'Fetch your app configuration from the Developer Dashboard.' @@ -17,6 +18,11 @@ export default class ConfigLink extends AppLinkedCommand { static flags = { ...globalFlags, ...appFlags, + 'client-id': Flags.string({ + hidden: false, + description: 'The Client ID of your app.', + env: 'SHOPIFY_FLAG_CLIENT_ID', + }), } public async run(): Promise { diff --git a/packages/cli/README.md b/packages/cli/README.md index d96a305ea8a..e903c4e7b79 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -241,7 +241,7 @@ Fetch your app configuration from the Developer Dashboard. ``` USAGE - $ shopify app config link [--client-id | -c ] [--no-color] [--path ] [--reset | ] [--verbose] + $ shopify app config link [--client-id ] [--no-color] [--path ] [--reset | -c ] [--verbose] FLAGS -c, --config= [env: SHOPIFY_FLAG_APP_CONFIG] The name of the app configuration. diff --git a/packages/cli/oclif.manifest.json b/packages/cli/oclif.manifest.json index 046ac204728..deade50bdac 100644 --- a/packages/cli/oclif.manifest.json +++ b/packages/cli/oclif.manifest.json @@ -442,9 +442,6 @@ "client-id": { "description": "The Client ID of your app.", "env": "SHOPIFY_FLAG_CLIENT_ID", - "exclusive": [ - "config" - ], "hasDynamicHelp": false, "hidden": false, "multiple": false,