Skip to content

Add shopify store info --store <domain> command#7660

Open
amcaplan wants to merge 4 commits into
ariel/store-graphql-layerfrom
ariel/store-info-command
Open

Add shopify store info --store <domain> command#7660
amcaplan wants to merge 4 commits into
ariel/store-graphql-layerfrom
ariel/store-info-command

Conversation

@amcaplan

@amcaplan amcaplan commented May 28, 2026

Copy link
Copy Markdown
Contributor

📚 Part of the store info stack — review/merge bottom-up:

  1. Add a shared GID codec to cli-kit and adopt it in app and organizations #7753 — shared GID codec in cli-kit (adopted by app + organizations)
  2. Add extractHost and extractMyshopifyHandle to cli-kit/common/url #7754extractHost / extractMyshopifyHandle in cli-kit/common/url
  3. Extract the shared --store flag out of the store auth and execute commands #7755 — shared --store flag extracted from store auth / store execute
  4. Add the Business Platform GraphQL data-access layer for store info #7756 — Business Platform GraphQL data-access layer (codegen wiring + queries + generated types)
  5. Add shopify store info --store <domain> command #7660 (this PR)shopify store info, the services + command that consume all of the above

The lower-level pieces this command builds on — the GID codec, URL host/handle helpers, the shared --store flag, and the typed GraphQL client layer — were extracted into the base PRs above. This PR's diff is the store info service modules, the command, and its tests/docs only.

Summary

Adds shopify store info --store <domain>, which surfaces metadata about a store you have access to. Output is aligned to the store-management project brief's dev-store contract and every field is sourced from the Business Platform (BP Destinations + BP Organizations), so the command works without store auth — no Admin API access required.

Fields (camelCase in --json, labelled in text):

Field Source
id (gid://shopify/Shop/<id>) BP Organizations shopifyShopId (GID built locally)
displayName BP Organizations
subdomain --store
organizationId, organizationName BP Destinations → organizationForDestination
storeOwner { name, email } BP Organizations ownerDetails
type (dev / production / …) BP Store enum
plan (basic / grow / advanced / plus) BP Shop.planName, mapped to a public handle
featurePreview BP Organizations developerPreviewHandle
adminUrl derived from the --store domain
  • Supports --json for machine-readable output; text output renders a single Store details section.
  • Fields that can't be resolved are simply omitted — when the BP Organizations lookup fails, the destination-resolved fields (organizationId / organizationName) plus subdomain and adminUrl are still returned.
  • plan maps BP's raw internal plan names (which differ from marketing names, e.g. professional → Grow, unlimited → Advanced) to a public handle via a hardcoded 1:1 table; unrecognized plans are omitted.

Implementation notes

What this PR contains

With the GID codec (#7753), URL helpers (#7754), shared --store flag (#7755), and GraphQL layer (#7756) factored out below, this PR is the store info feature itself:

  • Service modules (services/store/info/*) — orchestrate the three BP calls, match the store, map plan/type, and assemble the result.
  • Command (commands/store/info.ts) — wires storeFlags.store (from Extract the shared --store flag out of the store auth and execute commands #7755) and --json to the service and renderer.
  • Rendering (result.ts) — the doc-shaped JSON payload and the text Store details section.
  • Tests and the changeset (minor @shopify/cli bump for the new command).

Quality gates

  • pnpm vitest run (packages/store) — 168 tests passing
  • pnpm type-check
  • pnpm lint
  • pnpm refresh-manifests — manifest + README regenerated and committed
  • pnpm build-dev-docsstore-info.interface.ts + the store info entries in generated_docs_data_v2.json regenerated and committed

Test plan

  • shopify store info --store <store>.myshopify.com returns the contract fields without store auth
  • --json output matches the camelCase contract
  • Missing --store surfaces a clear AbortError
  • Non-existent / inaccessible shop domain surfaces a clear AbortError
  • When the BP Organizations lookup fails, the org / admin-URL / subdomain baseline still renders

Out of scope / follow-ups

  • Preview stores — only BP-fetched store types are in scope here.
  • --store accepting a GID or integer — should be a separate CLI-wide change to storeFlags.store / normalizeStoreFqdn rather than localized to info. Interactive org/store prompting (which would make --store optional) is likewise deferred.

Closes shop/issues-develop#22724

🤖 Generated with Claude Code

amcaplan commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

Comment thread packages/store/src/cli/commands/store/info.ts Outdated
Comment thread packages/cli/README.md
-j, --json [env: SHOPIFY_FLAG_JSON] Output the result as JSON. Automatically disables color output.
-s, --store=<value> (required) [env: SHOPIFY_FLAG_STORE] The myshopify.com domain of the store to authenticate
against.
-s, --store=<value> (required) [env: SHOPIFY_FLAG_STORE] The myshopify.com domain of the store.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are losing some info here + below. I am debating whether it's better to have a shared flag entirely, or there's value in overriding the description.

@amcaplan amcaplan changed the title Add shopify store info <store> command Add shopify store info --store <domain> command May 28, 2026
@amcaplan amcaplan force-pushed the ariel/extract-organizations-package branch from d67e8d3 to c9531e3 Compare May 28, 2026 22:02
@amcaplan amcaplan force-pushed the ariel/store-info-command branch from 38490df to 979bd9a Compare May 28, 2026 22:02
Base automatically changed from ariel/extract-organizations-package to main May 28, 2026 22:14
@amcaplan amcaplan force-pushed the ariel/store-info-command branch from 979bd9a to c1e7a69 Compare May 31, 2026 18:17
@amcaplan amcaplan changed the base branch from main to graphite-base/7660 June 8, 2026 14:39
@amcaplan amcaplan force-pushed the ariel/store-info-command branch from 55cad39 to 77cbde9 Compare June 8, 2026 14:39
@amcaplan amcaplan changed the base branch from graphite-base/7660 to ariel/cli-kit-url-helpers June 8, 2026 14:39
@amcaplan amcaplan changed the base branch from ariel/cli-kit-url-helpers to graphite-base/7660 June 8, 2026 15:33
@amcaplan amcaplan force-pushed the ariel/store-info-command branch from 77cbde9 to 44ef0bd Compare June 8, 2026 15:33
@amcaplan amcaplan changed the base branch from graphite-base/7660 to ariel/store-graphql-layer June 8, 2026 15:33
@amcaplan amcaplan force-pushed the ariel/store-info-command branch from 44ef0bd to fb6858d Compare June 8, 2026 16:03
@amcaplan amcaplan force-pushed the ariel/store-graphql-layer branch from f60666b to f36a34f Compare June 8, 2026 16:03
@amcaplan amcaplan force-pushed the ariel/store-info-command branch 2 times, most recently from 4619df4 to 53681cc Compare June 9, 2026 15:40
@amcaplan amcaplan marked this pull request as ready for review June 9, 2026 15:44
@amcaplan amcaplan requested review from a team as code owners June 9, 2026 15:44
@dmerand

dmerand commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

/snapit

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🫰✨ Thanks @dmerand! Your snapshot has been published to npm.

Test the snapshot by installing your package globally:

pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20260609162508

Caution

After installing, validate the version by running shopify version in your terminal.
If the versions don't match, you might have multiple global instances installed.
Use which shopify to find out which one you are running and uninstall it.

@amcaplan amcaplan force-pushed the ariel/store-info-command branch from 53681cc to 27250a0 Compare June 9, 2026 18:26
@amcaplan amcaplan force-pushed the ariel/store-graphql-layer branch from f36a34f to 73fbe9b Compare June 9, 2026 18:26
@amcaplan

amcaplan commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Addressing two earlier review threads (couldn't post as threaded replies — there's a pending review on this PR, so the API blocks reply creation):

1. Command description "reads like harness session language" — Resolved. The description was since rewritten and no longer uses the tiered store auth phrasing; it now reads as plain prose listing the returned fields (id, display name, subdomain, organization, owner, type, plan, feature preview, admin URL) plus a --json note.

2. Losing info on the shared --store flag description — Decision: keeping the shared flag with the generic description (The myshopify.com domain of the store.) across all store commands, favouring one source of truth and cross-command consistency over per-command phrasing. Not overriding the description per command.

— 🤖 AI-generated (Claude Code), posted on @amcaplan's behalf.

@amcaplan amcaplan force-pushed the ariel/store-info-command branch from 27250a0 to ceeb9cc Compare June 9, 2026 19:08
amcaplan and others added 4 commits June 9, 2026 23:18
Introduce the data-access and composition layer behind `shopify store
info`: the Business Platform destinations lookup (with owning-org
resolution), the Organizations shop fetch, plan-handle mapping, shared
types, and the getStoreInfo orchestrator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire up the StoreInfo command on the shared `--store` flag and render
the composed result as human-readable text or `--json`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cover the service layer, command wiring, and result rendering.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the changeset and regenerate the command reference: README, oclif
manifest, and shopify.dev docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@amcaplan amcaplan force-pushed the ariel/store-graphql-layer branch from 73fbe9b to 6b71f98 Compare June 9, 2026 20:19
@amcaplan amcaplan force-pushed the ariel/store-info-command branch from ceeb9cc to 43520bc Compare June 9, 2026 20:19
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Differences in type declarations

We detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

packages/cli-kit/dist/public/common/gid.d.ts
/**
 * Extracts the trailing numeric id from a plain GraphQL global id like
 * `gid://shopify/Product/123`.
 *
 * @param gid - A plain GraphQL global id string.
 * @returns The trailing numeric id, or undefined when the string does not end with `/<digits>`.
 */
export declare function numericIdFromGid(gid: string): string | undefined;
/**
 * Decodes a base64-encoded GraphQL global id (for example, the form
 * Business Platform APIs return) and returns the trailing numeric id.
 *
 * @param gid - A base64-encoded GraphQL global id.
 * @returns The trailing numeric id, or undefined when the decoded string does not end with `/<digits>`.
 */
export declare function numericIdFromEncodedGid(gid: string): string | undefined;
/**
 * Encodes a plain GraphQL global id (`gid://...`) as base64, which is the
 * form some Business Platform endpoints require.
 *
 * @param gid - A plain GraphQL global id string to encode.
 * @returns The base64-encoded gid.
 */
export declare function encodeGid(gid: string): string;

Existing type declarations

packages/cli-kit/dist/public/common/url.d.ts
@@ -12,4 +12,20 @@ export declare function isValidURL(url: string): boolean;
  * @param url - The string to parse into a URL.
  * @returns A URL object if the parsing is successful, undefined otherwise.
  */
-export declare function safeParseURL(url: string): URL | undefined;
\ No newline at end of file
+export declare function safeParseURL(url: string): URL | undefined;
+/**
+ * Extracts the lowercased hostname from a URL-shaped string. Tolerates
+ * bare hosts (without a scheme) and inputs that come back from APIs as
+ * either  or .
+ *
+ * @param value - A URL or bare host string, possibly null/undefined.
+ * @returns The lowercased hostname, or undefined when the input is empty.
+ */
+export declare function extractHost(value: string | null | undefined): string | undefined;
+/**
+ * Extracts the subdomain handle from a  URL or host.
+ *
+ * @param value - A URL or host string, possibly null/undefined.
+ * @returns The myshopify subdomain handle, or undefined when the input isn't a  URL.
+ */
+export declare function extractMyshopifyHandle(value: string | null | undefined): string | undefined;
\ No newline at end of file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: @shopify/cli @shopify/cli package issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants