Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/store-list-bp-auto.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
'@shopify/cli-kit': patch
---

Add `shopify store list` to list stores from Business Platform for the current Shopify CLI account. When some organization-scoped Business Platform lookups fail, the command now returns successful organizations with a warning and failure details for the skipped organizations.
Add `shopify store list` with `--source auto|bp|local`. By default the command prefers Business Platform and falls back to locally stored store auth when Business Platform cannot represent or serve the current CLI session. When some organization-scoped Business Platform lookups fail, the command still returns successful organizations with a warning and failure details for the skipped organizations.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ export interface storelist {
*/
'--no-color'?: ''

/**
* Data source for the listing. `auto` prefers Business Platform and falls back to locally stored store auth when necessary.
* @environment SHOPIFY_FLAG_STORE_LIST_SOURCE
*/
'--source <value>'?: string

/**
* Increase the verbosity of the output.
* @environment SHOPIFY_FLAG_VERBOSE
Expand Down
11 changes: 10 additions & 1 deletion docs-shopify.dev/generated/generated_docs_data_v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -4309,6 +4309,15 @@
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_NO_COLOR"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/store-list.interface.ts",
"syntaxKind": "PropertySignature",
"name": "--source <value>",
"value": "string",
"description": "Data source for the listing. `auto` prefers Business Platform and falls back to locally stored store auth when necessary.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_STORE_LIST_SOURCE"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/store-list.interface.ts",
"syntaxKind": "PropertySignature",
Expand All @@ -4328,7 +4337,7 @@
"environmentValue": "SHOPIFY_FLAG_JSON"
}
],
"value": "export interface storelist {\n /**\n * Output the result as JSON. Automatically disables color output.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}"
"value": "export interface storelist {\n /**\n * Output the result as JSON. Automatically disables color output.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Data source for the listing. `auto` prefers Business Platform and falls back to locally stored store auth when necessary.\n * @environment SHOPIFY_FLAG_STORE_LIST_SOURCE\n */\n '--source <value>'?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}"
}
},
"themecheck": {
Expand Down
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,19 @@
]
}
},
"packages/store": {
"entry": [
"**/{commands,hooks}/**/*.ts!",
"**/index.ts!"
],
"project": "**/*.ts!",
"ignore": [
"**/graphql/**/generated/*.ts"
],
"ignoreDependencies": [
"@graphql-typed-document-node/core"
]
},
"packages/theme": {
"project": "**/*.ts!",
"entry": [
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/cli/api/graphql/admin/generated/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ export type MetafieldOwnerType =
| 'SELLING_PLAN'
/** The Shop metafield owner type. */
| 'SHOP'
/** The Transfer metafield owner type. */
| 'TRANSFER'
/** The Validation metafield owner type. */
| 'VALIDATION';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ export type MetafieldOwnerType =
| 'SELLING_PLAN'
/** The Shop metafield owner type. */
| 'SHOP'
/** The Transfer metafield owner type. */
| 'TRANSFER'
/** The Validation metafield owner type. */
| 'VALIDATION';

Expand Down
3 changes: 2 additions & 1 deletion packages/cli-kit/src/private/node/session/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export async function fetch(): Promise<Sessions | undefined> {
let contentJson: unknown
try {
contentJson = JSON.parse(content)
} catch {
} catch (error) {
if (!(error instanceof SyntaxError)) throw error
await remove()
return undefined
}
Expand Down
15 changes: 15 additions & 0 deletions packages/cli-kit/src/public/node/session.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,21 @@ describe('ensureAuthenticatedBusinessPlatform', () => {
expect(got).toEqual('business_platform')
})

test('passes auth options through to the private auth helper', async () => {
// Given
vi.mocked(ensureAuthenticated).mockResolvedValueOnce({businessPlatform: 'business_platform', userId: '1234-5678'})

// When
await ensureAuthenticatedBusinessPlatform([], {noPrompt: true})

// Then
expect(ensureAuthenticated).toHaveBeenCalledWith(
{businessPlatformApi: {scopes: []}},
process.env,
expect.objectContaining({noPrompt: true}),
)
})

test('throws error if there is no business_platform token', async () => {
// Given
vi.mocked(ensureAuthenticated).mockResolvedValueOnce({partners: 'partners_token', userId: '1234-5678'})
Expand Down
8 changes: 6 additions & 2 deletions packages/cli-kit/src/public/node/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,17 @@ ${outputToken.json(scopes)}
* Ensure that we have a valid session to access the Business Platform API.
*
* @param scopes - Optional array of extra scopes to authenticate with.
* @param options - Optional auth behavior overrides such as `noPrompt`.
* @returns The access token for the Business Platform API.
*/
export async function ensureAuthenticatedBusinessPlatform(scopes: BusinessPlatformScope[] = []): Promise<string> {
export async function ensureAuthenticatedBusinessPlatform(
scopes: BusinessPlatformScope[] = [],
options: EnsureAuthenticatedAdditionalOptions = {},
): Promise<string> {
outputDebug(outputContent`Ensuring that the user is authenticated with the Business Platform API with the following scopes:
${outputToken.json(scopes)}
`)
const tokens = await ensureAuthenticated({businessPlatformApi: {scopes}}, process.env)
const tokens = await ensureAuthenticated({businessPlatformApi: {scopes}}, process.env, options)
if (!tokens.businessPlatform) {
throw new BugError('No business-platform token found after ensuring authenticated')
}
Expand Down
25 changes: 19 additions & 6 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2182,25 +2182,38 @@ EXAMPLES

## `shopify store list`

List stores accessible through Business Platform.
List stores available to the current CLI session.

```
USAGE
$ shopify store list [-j] [--no-color] [--verbose]
$ shopify store list [-j] [--no-color] [--source auto|bp|local] [--verbose]

FLAGS
-j, --json [env: SHOPIFY_FLAG_JSON] Output the result as JSON. Automatically disables color output.
--no-color [env: SHOPIFY_FLAG_NO_COLOR] Disable color output.
--verbose [env: SHOPIFY_FLAG_VERBOSE] Increase the verbosity of the output.
-j, --json [env: SHOPIFY_FLAG_JSON] Output the result as JSON. Automatically disables color output.
--no-color [env: SHOPIFY_FLAG_NO_COLOR] Disable color output.
--source=<option> [default: auto, env: SHOPIFY_FLAG_STORE_LIST_SOURCE] Data source for the listing. `auto`
prefers Business Platform and falls back to locally stored store auth when necessary.
<options: auto|bp|local>
--verbose [env: SHOPIFY_FLAG_VERBOSE] Increase the verbosity of the output.

DESCRIPTION
List stores accessible through Business Platform.
List stores available to the current CLI session.

Lists stores from Business Platform for the current Shopify CLI account.

By default, the command uses `--source auto`:
- Business Platform when the current CLI session can be used without reauthentication and BP can resolve it
- the local store-auth cache when BP is unavailable for the current session

Use `--source bp` to force Business Platform, or `--source local` to inspect only locally stored store auth.

EXAMPLES
$ shopify store list

$ shopify store list --source bp

$ shopify store list --source local

$ shopify store list --json
```

Expand Down
23 changes: 20 additions & 3 deletions packages/cli/oclif.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5868,10 +5868,12 @@
"args": {
},
"customPluginName": "@shopify/store",
"description": "Lists stores from Business Platform for the current Shopify CLI account.",
"descriptionWithMarkdown": "Lists stores from Business Platform for the current Shopify CLI account.",
"description": "Lists stores from Business Platform for the current Shopify CLI account.\n\nBy default, the command uses `--source auto`:\n- Business Platform when the current CLI session can be used without reauthentication and BP can resolve it\n- the local store-auth cache when BP is unavailable for the current session\n\nUse `--source bp` to force Business Platform, or `--source local` to inspect only locally stored store auth.",
"descriptionWithMarkdown": "Lists stores from Business Platform for the current Shopify CLI account.\n\nBy default, the command uses `--source auto`:\n- Business Platform when the current CLI session can be used without reauthentication and BP can resolve it\n- the local store-auth cache when BP is unavailable for the current session\n\nUse `--source bp` to force Business Platform, or `--source local` to inspect only locally stored store auth.",
"examples": [
"<%= config.bin %> <%= command.id %>",
"<%= config.bin %> <%= command.id %> --source bp",
"<%= config.bin %> <%= command.id %> --source local",
"<%= config.bin %> <%= command.id %> --json"
],
"flags": {
Expand All @@ -5892,6 +5894,21 @@
"name": "no-color",
"type": "boolean"
},
"source": {
"default": "auto",
"description": "Data source for the listing. `auto` prefers Business Platform and falls back to locally stored store auth when necessary.",
"env": "SHOPIFY_FLAG_STORE_LIST_SOURCE",
"hasDynamicHelp": false,
"multiple": false,
"name": "source",
"options": [
"auto",
"bp",
"local"
],
"required": false,
"type": "option"
},
"verbose": {
"allowNo": false,
"description": "Increase the verbosity of the output.",
Expand All @@ -5909,7 +5926,7 @@
"pluginName": "@shopify/cli",
"pluginType": "core",
"strict": true,
"summary": "List stores accessible through Business Platform."
"summary": "List stores available to the current CLI session."
},
"theme:check": {
"aliases": [
Expand Down
3 changes: 2 additions & 1 deletion packages/e2e/data/snapshots/commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@
├─ search
├─ store
│ ├─ auth
│ └─ execute
│ ├─ execute
│ └─ list
├─ theme
│ ├─ check
│ ├─ console
Expand Down
2 changes: 1 addition & 1 deletion packages/organizations/src/cli/services/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {businessPlatformRequestDoc} from '@shopify/cli-kit/node/api/business-pla
import {ensureAuthenticatedBusinessPlatform} from '@shopify/cli-kit/node/session'
import {AbortError} from '@shopify/cli-kit/node/error'

export interface FetchOrganizationsWithAccessInfoResult {
interface FetchOrganizationsWithAccessInfoResult {
organizations: Organization[]
currentUserResolved: boolean
currentUserEmail?: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,11 @@ enum AttestationTypeHandle {
Confirms that the listed beneficial owners (UBOs) are accurate and complete.
"""
OWNERSHIP_DECLARATION

"""
Records merchant acceptance of the Shopify Payments Terms of Service.
"""
SHOPIFY_PAYMENTS_TOS_ACCEPTED
}

type AuthorizedApplication {
Expand Down Expand Up @@ -6347,6 +6352,11 @@ enum Document {
"""
GI_CERTIFICATE_OF_INCORPORATION

"""
Certificate of Incumbency
"""
GI_CERTIFICATE_OF_INCUMBENCY

"""
Companies House Document
"""
Expand All @@ -6367,11 +6377,26 @@ enum Document {
"""
GI_IDENTITY_CARD

"""
Partnership Agreement
"""
GI_PARTNERSHIP_AGREEMENT

"""
Passport
"""
GI_PASSPORT

"""
Recent Annual Return
"""
GI_RECENT_ANNUAL_RETURN

"""
Shareholder Register
"""
GI_SHAREHOLDER_REGISTER

"""
UBO Attestation
"""
Expand Down Expand Up @@ -7652,11 +7677,26 @@ enum Document {
"""
NO_BANK_STATEMENT

"""
Beneficial Owner Report
"""
NO_BENEFICIAL_OWNER_REPORT

"""
Certificate of Incorporation
"""
NO_CERTIFICATE_OF_INCORPORATION

"""
Certificate of Registration
"""
NO_CERTIFICATE_OF_REGISTRATION

"""
Commercial Register Extract
"""
NO_COMMERCIAL_REGISTER_EXTRACT

"""
Director Attestation
"""
Expand All @@ -7682,6 +7722,11 @@ enum Document {
"""
NO_IDENTITY_CARD

"""
Partnership Agreement
"""
NO_PARTNERSHIP_AGREEMENT

"""
Passport
"""
Expand All @@ -7697,6 +7742,11 @@ enum Document {
"""
NO_RESIDENT_PERMIT

"""
Shareholder Register
"""
NO_SHAREHOLDER_REGISTER

"""
UBO Attestation
"""
Expand Down Expand Up @@ -15210,10 +15260,10 @@ type Query {

"""
Returns entity supporting document types for the given country code and
category. Optionally filter by purpose. When purpose is not provided, all
document types for the given country and category are returned.
category. Optionally filter by purpose and/or legal entity type. When neither
filter is provided, all document types for the given country and category are returned.
"""
entitySupportingDocumentTypes(category: Category!, countryCode: CountryCodeWithDefault!, purpose: DocumentPurpose): [SupportingDocumentType!]!
entitySupportingDocumentTypes(category: Category!, countryCode: CountryCodeWithDefault!, legalEntityType: LegalEntityTypeInput, purpose: DocumentPurpose): [SupportingDocumentType!]!

"""
Returns the government identifier type with the given handle.
Expand Down Expand Up @@ -15326,6 +15376,11 @@ type Query {
Indicates whether a subdomain is available for a new shop.
"""
shopSubdomainAvailable(subdomain: String!): Boolean

"""
Validate whether a shop is ready for a Vibe transfer.
"""
validateVibeTransferReadiness(shopId: PropertyPublicID!): ValidateVibeTransferReadinessResult!
}

input RemoveOrganizationUserRoleInput {
Expand Down Expand Up @@ -19040,3 +19095,15 @@ enum ValidLegalEntityCategoryInput {
INDIVIDUAL
UNSPECIFIED
}

type ValidateVibeTransferReadinessResult {
"""
Whether the shop is ready for a Vibe transfer.
"""
readyToTransfer: Boolean!

"""
The collection of errors.
"""
userErrors: [UserError!]
}
Loading
Loading