Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,16 @@ export type Scalars = {
URL: { input: string; output: string; }
};

/** Operators for user filter queries. */
/** Operators for filter queries. */
export type Operator =
/** Between operator. */
| 'BETWEEN'
/** Equals operator. */
| 'EQUALS'
/** In operator. */
/**
* In operator. Accepts a comma-separated string of values (e.g.
* "value1,value2,value3"). Not supported for all filter fields.
*/
| 'IN';

export type OrganizationUserProvisionShopAccessInput = {
Expand All @@ -113,17 +116,23 @@ export type ShopFilterField =
* `inactive`, `cancelled`, `client_transfer`, `plus_client_transfer`,
* `development_legacy`, `custom`, `fraudulent`, `staff`, `trial`,
* `plus_development`, `retail`, `shop_pay_commerce_components`, `non_profit`.
* With the `In` operator, use raw plan names (e.g. "professional,shopify_plus").
*/
| 'SHOP_PLAN'
/** The active/inactive status of the shop. Values: `active`, `inactive`. */
| 'STORE_STATUS'
/**
* The type of the shop. Values: `development`, `production`, `app_development`,
* `development_superset`, `client_transfer`, `collaborator`.
* The type of the shop. Does not support the `In` operator. Values:
* `development`, `production`, `app_development`, `development_superset`,
* `client_transfer`, `collaborator`.
*/
| 'STORE_TYPE';

/** Represents a single filter option for shop queries. */
/**
* Represents a single filter option for shop queries. When using the `In`
* operator, pass a comma-separated string of values (e.g. "value1,value2").
* Maximum 20 values.
*/
export type ShopFilterInput = {
field: ShopFilterField;
operator: Operator;
Expand Down
36 changes: 36 additions & 0 deletions packages/cli/src/cli/services/store/auth/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,42 @@ describe('store auth service', () => {
expect(setStoredStoreAppSession).not.toHaveBeenCalled()
})

test('authenticateStoreWithApp succeeds when scopes input is space-separated', async () => {
const waitForStoreAuthCodeMock = vi.fn().mockImplementation(async (options) => {
await options.onListening?.()
return 'abc123'
})

const result = await authenticateStoreWithApp(
{
store: 'shop.myshopify.com',
scopes: 'read_products read_inventory',
},
{
openURL: vi.fn().mockResolvedValue(true),
waitForStoreAuthCode: waitForStoreAuthCodeMock,
exchangeStoreAuthCodeForToken: vi.fn().mockResolvedValue({
access_token: 'token',
scope: 'read_products,read_inventory',
expires_in: 86400,
associated_user: {id: 42, email: 'test@example.com'},
}),
presenter: {
openingBrowser: vi.fn(),
manualAuthUrl: vi.fn(),
success: vi.fn(),
},
},
)

expect(result.scopes).toEqual(['read_products', 'read_inventory'])
expect(setStoredStoreAppSession).toHaveBeenCalledWith(
expect.objectContaining({
scopes: ['read_products', 'read_inventory'],
}),
)
})

test('authenticateStoreWithApp accepts compressed write scopes that imply requested read scopes', async () => {
const waitForStoreAuthCodeMock = vi.fn().mockImplementation(async (options) => {
await options.onListening?.()
Expand Down
24 changes: 24 additions & 0 deletions packages/cli/src/cli/services/store/auth/scopes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,30 @@ describe('store auth scope helpers', () => {
expect(mergeRequestedAndStoredScopes(['read_products'], ['read_orders'])).toEqual(['read_orders', 'read_products'])
})

test('parseStoreAuthScopes splits space-separated scopes', () => {
expect(parseStoreAuthScopes('read_products read_inventory')).toEqual(['read_products', 'read_inventory'])
})

test('parseStoreAuthScopes splits mixed comma-and-space delimiters', () => {
expect(parseStoreAuthScopes('read_products, read_inventory,write_orders')).toEqual([
'read_products',
'read_inventory',
'write_orders',
])
})

test('resolveGrantedScopes succeeds when granted scopes are space-separated', () => {
expect(
resolveGrantedScopes(
{
access_token: 'token',
scope: 'read_products read_inventory',
},
['read_products', 'read_inventory'],
Comment thread
RyanDJLee marked this conversation as resolved.
),
).toEqual(['read_products', 'read_inventory'])
})

test('resolveGrantedScopes accepts compressed write scopes that imply requested reads', () => {
expect(
resolveGrantedScopes(
Expand Down
5 changes: 1 addition & 4 deletions packages/cli/src/cli/services/store/auth/scopes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import {outputContent, outputDebug} from '@shopify/cli-kit/node/output'
import type {StoreTokenResponse} from './token-client.js'

export function parseStoreAuthScopes(input: string): string[] {
const scopes = input
.split(',')
.map((scope) => scope.trim())
.filter(Boolean)
const scopes = input.split(/[ ,]+/).filter(Boolean)

if (scopes.length === 0) {
throw new AbortError('At least one scope is required.', 'Pass --scopes as a comma-separated list.')
Expand Down
Loading