From d3478fec57d1bbf7cd7c09c265f1c8fc67ad3a06 Mon Sep 17 00:00:00 2001 From: Alfonso Noriega Date: Tue, 19 May 2026 15:20:54 +0200 Subject: [PATCH] feat(store): add shopify store list command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lists every locally stored store-auth session — both standard PKCE-authenticated (shopify store auth) and preview-store (shopify store create preview) — with a 3-column table (Store, Kind, User), --kind filter, and --json output for agent consumption. Adds a LocalStorage#entries() enumerator in cli-kit and a listStoredStoreAppSessions() helper in @shopify/store so the command can resolve sessions across every stored shop without knowing the keys in advance. Stacked on store-create-preview-command (#7558) → preview-store-session-discriminator (#7557). --- .changeset/store-list-command.md | 9 ++ .../src/public/node/local-storage.test.ts | 24 ++++ .../cli-kit/src/public/node/local-storage.ts | 21 +++ packages/cli/README.md | 32 +++++ packages/cli/oclif.manifest.json | 63 +++++++++ packages/store/src/cli/commands/store/list.ts | 44 ++++++ .../services/store/auth/session-store.test.ts | 125 ++++++++++++++++++ .../cli/services/store/auth/session-store.ts | 57 +++++++- .../src/cli/services/store/list/index.test.ts | 105 +++++++++++++++ .../src/cli/services/store/list/index.ts | 56 ++++++++ .../cli/services/store/list/result.test.ts | 83 ++++++++++++ .../src/cli/services/store/list/result.ts | 57 ++++++++ packages/store/src/index.ts | 2 + 13 files changed, 677 insertions(+), 1 deletion(-) create mode 100644 .changeset/store-list-command.md create mode 100644 packages/store/src/cli/commands/store/list.ts create mode 100644 packages/store/src/cli/services/store/list/index.test.ts create mode 100644 packages/store/src/cli/services/store/list/index.ts create mode 100644 packages/store/src/cli/services/store/list/result.test.ts create mode 100644 packages/store/src/cli/services/store/list/result.ts diff --git a/.changeset/store-list-command.md b/.changeset/store-list-command.md new file mode 100644 index 00000000000..94ce763ad33 --- /dev/null +++ b/.changeset/store-list-command.md @@ -0,0 +1,9 @@ +--- +'@shopify/store': minor +'@shopify/cli-kit': patch +'@shopify/cli': minor +--- + +Add `shopify store list`, which prints every locally stored store-auth session — both standard PKCE-authenticated sessions (`shopify store auth`) and preview-store sessions (`shopify store create preview`) — as a table with `Store`, `Kind`, and `User` columns. Supports `--kind standard|preview` for filtering and `--json` for machine-readable output (intended for AI agent consumption alongside the M1 [Preview Store for AI Agent Surfaces](https://vault.shopify.io/gsd/proposals/60T12R) work). + +Internally adds a `LocalStorage#entries()` enumerator to `@shopify/cli-kit` and a `listStoredStoreAppSessions()` helper to `@shopify/store` so the new command can resolve sessions across every stored shop without knowing the keys in advance. diff --git a/packages/cli-kit/src/public/node/local-storage.test.ts b/packages/cli-kit/src/public/node/local-storage.test.ts index cc1ab842326..d12f2151078 100644 --- a/packages/cli-kit/src/public/node/local-storage.test.ts +++ b/packages/cli-kit/src/public/node/local-storage.test.ts @@ -62,6 +62,30 @@ describe('storage', () => { expect(got2).toEqual(undefined) }) }) + + test('entries returns every stored key/value pair', async () => { + await inTemporaryDirectory((cwd) => { + const storage = new LocalStorage({cwd}) + + storage.set('testValue', 'first') + storage.set('anotherKey' as keyof TestSchema, 'second' as TestSchema[keyof TestSchema]) + + const entries = storage.entries() + + expect(entries).toHaveLength(2) + expect(Object.fromEntries(entries)).toEqual({ + testValue: 'first', + anotherKey: 'second', + }) + }) + }) + + test('entries returns an empty array when nothing has been stored', async () => { + await inTemporaryDirectory((cwd) => { + const storage = new LocalStorage({cwd}) + expect(storage.entries()).toEqual([]) + }) + }) }) describe('error handling', () => { diff --git a/packages/cli-kit/src/public/node/local-storage.ts b/packages/cli-kit/src/public/node/local-storage.ts index 9759267aab9..aec9a58b5c0 100644 --- a/packages/cli-kit/src/public/node/local-storage.ts +++ b/packages/cli-kit/src/public/node/local-storage.ts @@ -66,6 +66,27 @@ export class LocalStorage> { } } + /** + * Get every `[key, value]` pair currently held in the local storage. + * + * Useful for callers that need to enumerate all stored values without knowing the + * full set of keys in advance (for example, a `list` command iterating over every + * stored session). The `conf` package stores its entire state as a single JSON + * object, so this is just a typed wrapper around that object. + * + * @returns An array of `[key, value]` tuples. + * @throws AbortError if a permission error occurs. + * @throws BugError if an unexpected error occurs. + */ + entries(): [keyof T, T[keyof T]][] { + try { + return Object.entries(this.config.store) as [keyof T, T[keyof T]][] + // eslint-disable-next-line no-catch-all/no-catch-all + } catch (error) { + this.handleError(error, 'entries') + } + } + /** * Clear the local storage (delete all values). * diff --git a/packages/cli/README.md b/packages/cli/README.md index 72159c47124..02c1f635d03 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -79,6 +79,7 @@ * [`shopify store auth`](#shopify-store-auth) * [`shopify store create preview`](#shopify-store-create-preview) * [`shopify store execute`](#shopify-store-execute) +* [`shopify store list`](#shopify-store-list) * [`shopify theme check`](#shopify-theme-check) * [`shopify theme console`](#shopify-theme-console) * [`shopify theme delete`](#shopify-theme-delete) @@ -2224,6 +2225,37 @@ EXAMPLES $ shopify store execute --store shop.myshopify.com --query "query { shop { name } }" --json ``` +## `shopify store list` + +List stored store-auth sessions. + +``` +USAGE + $ shopify store list [-j] [--kind standard|preview] [--no-color] [--verbose] + +FLAGS + -j, --json [env: SHOPIFY_FLAG_JSON] Output the result as JSON. Automatically disables color output. + --kind=