From 7b0cce5ea3706b0fcc91cd36d11f846c21d0db0b Mon Sep 17 00:00:00 2001 From: Ariel Caplan Date: Thu, 3 Sep 2026 21:06:04 +0300 Subject: [PATCH 1/2] Explain why store delete prompts for an organization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When only a store domain is given, `store delete` infers the owning organization from the Destinations API and silently drops into an organization picker whenever that inference comes up empty. The picker gives no hint about why it appeared, so a typo'd domain looks identical to a store the CLI legitimately can't see. Render an info banner ahead of the picker that names the domain the developer typed and points at `--organization-id`. Echoing the domain back surfaces typos, while the picker still serves the real cases — org owners deleting a store a teammate created, inactive stores that the destinations search filters out, and transient BP failures. Co-Authored-By: Claude Opus 5 (1M context) Assisted-By: devx/24c9b352-4ee9-4e6b-93da-ffee608999b1 --- ...store-delete-organization-prompt-notice.md | 5 ++++ .../store-lookup/organization.test.ts | 28 +++++++++++++++++++ .../utilities/store-lookup/organization.ts | 8 ++++++ 3 files changed, 41 insertions(+) create mode 100644 .changeset/store-delete-organization-prompt-notice.md diff --git a/.changeset/store-delete-organization-prompt-notice.md b/.changeset/store-delete-organization-prompt-notice.md new file mode 100644 index 00000000000..f6726906a4a --- /dev/null +++ b/.changeset/store-delete-organization-prompt-notice.md @@ -0,0 +1,5 @@ +--- +'@shopify/store': minor +--- + +Explain why `store delete` prompts for an organization, naming the store you provided diff --git a/packages/store/src/cli/utilities/store-lookup/organization.test.ts b/packages/store/src/cli/utilities/store-lookup/organization.test.ts index 717e9c1a0fd..caa5e981314 100644 --- a/packages/store/src/cli/utilities/store-lookup/organization.test.ts +++ b/packages/store/src/cli/utilities/store-lookup/organization.test.ts @@ -3,6 +3,7 @@ import {fetchDestinationsContext} from './destinations.js' import {selectOrg} from '@shopify/organizations' import {AbortError} from '@shopify/cli-kit/node/error' import {terminalSupportsPrompting} from '@shopify/cli-kit/node/system' +import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' import {describe, expect, test, vi, beforeEach} from 'vitest' vi.mock('./destinations.js') @@ -45,6 +46,7 @@ describe('resolveOrganizationForStore', () => { vi.mocked(selectOrg).mockResolvedValue(selectedOrg) vi.mocked(fetchDestinationsContext).mockResolvedValue({owningOrg: {id: '67890', name: 'Inferred Org'}}) vi.mocked(terminalSupportsPrompting).mockReturnValue(true) + mockAndCaptureOutput().clear() }) test('selects the organization by ID when an organization ID is provided', async () => { @@ -72,6 +74,32 @@ describe('resolveOrganizationForStore', () => { expect(organization).toEqual(selectedOrg) }) + test('explains why the organization prompt is appearing, naming the store the developer provided', async () => { + vi.mocked(fetchDestinationsContext).mockResolvedValue({owningOrg: undefined}) + const output = mockAndCaptureOutput() + + await resolveOrganizationForStore(STORE) + + expect(output.info()).toMatchInlineSnapshot(` + "╭─ info ───────────────────────────────────────────────────────────────────────╮ + │ │ + │ Could not determine which organization owns shop.myshopify.com. │ + │ │ + │ Select one below, or specify it with \`--organization-id\`. │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────╯ + " + `) + }) + + test('stays quiet when the owning organization is inferred', async () => { + const output = mockAndCaptureOutput() + + await resolveOrganizationForStore(STORE) + + expect(output.info()).toBe('') + }) + test('does not prompt non-interactively when ownership can be inferred', async () => { vi.mocked(terminalSupportsPrompting).mockReturnValue(false) diff --git a/packages/store/src/cli/utilities/store-lookup/organization.ts b/packages/store/src/cli/utilities/store-lookup/organization.ts index 362376d178e..752e7c1fcd1 100644 --- a/packages/store/src/cli/utilities/store-lookup/organization.ts +++ b/packages/store/src/cli/utilities/store-lookup/organization.ts @@ -3,6 +3,7 @@ import {selectOrg, type Organization} from '@shopify/organizations' import {AbortError} from '@shopify/cli-kit/node/error' import {outputDebug} from '@shopify/cli-kit/node/output' import {terminalSupportsPrompting} from '@shopify/cli-kit/node/system' +import {renderInfo} from '@shopify/cli-kit/node/ui' interface FindStoreOwningOrganizationOptions { store: string @@ -55,5 +56,12 @@ export async function resolveOrganizationForStore(store: string, organizationId? ) } + // The developer only gave a store domain, so explain why they're suddenly being asked to + // pick an organization. Echoing the domain back also makes a typo in it easy to spot. + renderInfo({ + headline: `Could not determine which organization owns ${store}.`, + body: ['Select one below, or specify it with', {command: '--organization-id'}, {char: '.'}], + }) + return selectOrg() } From 4e38e7ddbb4eae104322c5ef2e031085a4956bd3 Mon Sep 17 00:00:00 2001 From: Ariel Caplan Date: Thu, 3 Sep 2026 21:22:38 +0300 Subject: [PATCH 2/2] Remove changeset It's going to go out along with the command being shipped, no need for a separate changeset --- .changeset/store-delete-organization-prompt-notice.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/store-delete-organization-prompt-notice.md diff --git a/.changeset/store-delete-organization-prompt-notice.md b/.changeset/store-delete-organization-prompt-notice.md deleted file mode 100644 index f6726906a4a..00000000000 --- a/.changeset/store-delete-organization-prompt-notice.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@shopify/store': minor ---- - -Explain why `store delete` prompts for an organization, naming the store you provided