Skip to content

Commit 8a9a672

Browse files
committed
Use shopId to route Organization API requests
1 parent 58cc22a commit 8a9a672

28 files changed

+259
-593
lines changed

packages/store/src/apis/admin/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import {Shop} from './types.js'
12
import {StagedUploadsCreate} from '../../cli/api/graphql/admin/generated/staged_uploads_create.js'
3+
import {ShopDetails} from '../../cli/api/graphql/admin/generated/shop_details.js'
24
import {adminRequestDoc} from '@shopify/cli-kit/node/api/admin'
35
import {ensureAuthenticatedAdmin} from '@shopify/cli-kit/node/session'
46
import type {
@@ -7,6 +9,8 @@ import type {
79
} from '../../cli/api/graphql/admin/generated/staged_uploads_create.js'
810
import type {StagedUploadInput} from '../../cli/api/graphql/admin/generated/types.js'
911

12+
import type {ShopDetailsQuery, ShopDetailsQueryVariables} from '../../cli/api/graphql/admin/generated/shop_details.js'
13+
1014
export async function createStagedUploadAdmin(
1115
storeFqdn: string,
1216
input: StagedUploadInput[],
@@ -23,3 +27,12 @@ export async function createStagedUploadAdmin(
2327
}
2428

2529
export type {StagedUploadInput} from '../../cli/api/graphql/admin/generated/types.js'
30+
31+
export async function getShopDetails(storeDomain: string): Promise<Shop> {
32+
const adminSession = await ensureAuthenticatedAdmin(`https://${storeDomain}`)
33+
const response = await adminRequestDoc<ShopDetailsQuery, ShopDetailsQueryVariables>({
34+
query: ShopDetails,
35+
session: adminSession,
36+
})
37+
return response.shop
38+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface Shop {
2+
id: string
3+
name: string
4+
}

packages/store/src/apis/organizations/index.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {GraphQLVariables, graphqlRequest, CacheOptions, UnauthorizedHandler} fro
1818
import {businessPlatformFqdn} from '@shopify/cli-kit/node/context/fqdn'
1919

2020
export async function organizationsRequest<T>(
21-
organizationId: string,
21+
shopId: string,
2222
query: string,
2323
token: string,
2424
variables?: GraphQLVariables,
@@ -27,9 +27,8 @@ export async function organizationsRequest<T>(
2727
): Promise<T> {
2828
const api = 'BusinessPlatform'
2929
const fqdn = await businessPlatformFqdn()
30-
const decodedOrganizationGid = Buffer.from(organizationId, 'base64').toString('utf-8')
31-
const numericOrganizationId = decodedOrganizationGid.split('/').pop()
32-
const url = `https://${fqdn}/organizations/api/unstable/organization/${numericOrganizationId}/graphql`
30+
const numericShopId = shopId.split('/').pop()
31+
const url = `https://${fqdn}/organizations/api/unstable/shop/${numericShopId}/graphql`
3332

3433
return graphqlRequest<T>({
3534
token,
@@ -43,7 +42,7 @@ export async function organizationsRequest<T>(
4342
}
4443

4544
export async function startBulkDataStoreCopy(
46-
organizationId: string,
45+
shopId: string,
4746
sourceShopDomain: string,
4847
targetShopDomain: string,
4948
resourceConfigs: ResourceConfigs,
@@ -71,7 +70,7 @@ export async function startBulkDataStoreCopy(
7170
}
7271

7372
return organizationsRequest<BulkDataStoreCopyStartResponse>(
74-
organizationId,
73+
shopId,
7574
bulkDataStoreCopyStartMutation,
7675
token,
7776
{
@@ -83,7 +82,7 @@ export async function startBulkDataStoreCopy(
8382
}
8483

8584
export async function startBulkDataStoreExport(
86-
organizationId: string,
85+
shopId: string,
8786
sourceShopDomain: string,
8887
token: string,
8988
unauthorizedHandler?: UnauthorizedHandler,
@@ -95,7 +94,7 @@ export async function startBulkDataStoreExport(
9594
}
9695

9796
return organizationsRequest<BulkDataStoreExportStartResponse>(
98-
organizationId,
97+
shopId,
9998
bulkDataStoreExportStartMutation,
10099
token,
101100
{
@@ -107,7 +106,7 @@ export async function startBulkDataStoreExport(
107106
}
108107

109108
export async function startBulkDataStoreImport(
110-
organizationId: string,
109+
shopId: string,
111110
targetShopDomain: string,
112111
importUrl: string,
113112
resourceConfigs: ResourceConfigs,
@@ -133,7 +132,7 @@ export async function startBulkDataStoreImport(
133132
}
134133

135134
return organizationsRequest<BulkDataStoreImportStartResponse>(
136-
organizationId,
135+
shopId,
137136
bulkDataStoreImportStartMutation,
138137
token,
139138
{
@@ -145,13 +144,13 @@ export async function startBulkDataStoreImport(
145144
}
146145

147146
export async function pollBulkDataOperation(
148-
organizationId: string,
147+
shopId: string,
149148
operationId: string,
150149
token: string,
151150
unauthorizedHandler?: UnauthorizedHandler,
152151
): Promise<BulkDataOperationByIdResponse> {
153152
return organizationsRequest<BulkDataOperationByIdResponse>(
154-
organizationId,
153+
shopId,
155154
bulkDataOperationByIdQuery,
156155
token,
157156
{
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention, @typescript-eslint/ban-types, @typescript-eslint/no-duplicate-type-constituents, @typescript-eslint/no-redundant-type-constituents, @nx/enforce-module-boundaries */
2+
import * as Types from './types.js'
3+
4+
import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'
5+
6+
export type ShopDetailsQueryVariables = Types.Exact<{[key: string]: never}>
7+
8+
export type ShopDetailsQuery = {shop: {id: string; name: string}}
9+
10+
export const ShopDetails = {
11+
kind: 'Document',
12+
definitions: [
13+
{
14+
kind: 'OperationDefinition',
15+
operation: 'query',
16+
name: {kind: 'Name', value: 'ShopDetails'},
17+
selectionSet: {
18+
kind: 'SelectionSet',
19+
selections: [
20+
{
21+
kind: 'Field',
22+
name: {kind: 'Name', value: 'shop'},
23+
selectionSet: {
24+
kind: 'SelectionSet',
25+
selections: [
26+
{kind: 'Field', name: {kind: 'Name', value: 'id'}},
27+
{kind: 'Field', name: {kind: 'Name', value: 'name'}},
28+
{kind: 'Field', name: {kind: 'Name', value: '__typename'}},
29+
],
30+
},
31+
},
32+
],
33+
},
34+
},
35+
],
36+
} as unknown as DocumentNode<ShopDetailsQuery, ShopDetailsQueryVariables>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
query ShopDetails {
2+
shop {
3+
id
4+
name
5+
}
6+
}

packages/store/src/commands/store/copy.test.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {StoreExportOperation} from '../../services/store/operations/store-export
44
import {StoreImportOperation} from '../../services/store/operations/store-import.js'
55
import {ApiClient} from '../../services/store/api/api-client.js'
66
import {MockApiClient} from '../../services/store/mock/mock-api-client.js'
7-
import {ensureOrgHasBulkDataAccess} from '../../services/store/utils/store-utils.js'
87
import {describe, vi, expect, test, beforeEach} from 'vitest'
98
import {Config, loadHelpClass} from '@oclif/core'
109

@@ -14,9 +13,6 @@ vi.mock('../../services/store/operations/store-export.js')
1413
vi.mock('../../services/store/operations/store-import.js')
1514
vi.mock('../../services/store/api/api-client.js')
1615
vi.mock('../../services/store/mock/mock-api-client.js')
17-
vi.mock('../../services/store/utils/store-utils.js', () => ({
18-
ensureOrgHasBulkDataAccess: vi.fn().mockResolvedValue(true),
19-
}))
2016
vi.mock('@oclif/core', async () => {
2117
const actual = await vi.importActual('@oclif/core')
2218
return {
@@ -58,21 +54,16 @@ describe('Copy', () => {
5854
() =>
5955
({
6056
ensureAuthenticatedBusinessPlatform: vi.fn().mockResolvedValue('mock-session'),
61-
fetchOrganizations: vi.fn().mockResolvedValue(mockOrganizations),
6257
} as any),
6358
)
6459

6560
vi.mocked(MockApiClient).mockImplementation(
6661
() =>
6762
({
6863
ensureAuthenticatedBusinessPlatform: vi.fn().mockResolvedValue('mock-session'),
69-
fetchOrganizations: vi.fn().mockResolvedValue(mockOrganizations),
7064
} as any),
7165
)
7266

73-
// Reset the mock for ensureOrgHasBulkDataAccess to default to true
74-
vi.mocked(ensureOrgHasBulkDataAccess).mockResolvedValue(true)
75-
7667
vi.mocked(StoreCopyOperation).mockImplementation(
7768
() =>
7869
({

packages/store/src/commands/store/copy.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {StoreExportOperation} from '../../services/store/operations/store-export
88
import {StoreImportOperation} from '../../services/store/operations/store-import.js'
99
import {ApiClient} from '../../services/store/api/api-client.js'
1010
import {MockApiClient} from '../../services/store/mock/mock-api-client.js'
11-
import {Organization} from '../../apis/destinations/index.js'
1211
import {globalFlags} from '@shopify/cli-kit/node/cli'
1312
import {joinPath, cwd} from '@shopify/cli-kit/node/path'
1413
import {loadHelpClass} from '@oclif/core'
@@ -35,7 +34,6 @@ export default class Copy extends BaseBDCommand {
3534
// Check access for all organizations first
3635
const apiClient = this.flags.mock ? new MockApiClient() : new ApiClient()
3736
const bpSession = await apiClient.ensureAuthenticatedBusinessPlatform()
38-
const allOrgs = await apiClient.fetchOrganizations(bpSession)
3937

4038
const {'from-store': fromStore, 'to-store': toStore, 'from-file': fromFile} = this.flags
4139
let {'to-file': toFile} = this.flags
@@ -51,25 +49,20 @@ export default class Copy extends BaseBDCommand {
5149
toFile = joinPath(cwd(), `${storeDomain}-export-${Date.now()}.sqlite`)
5250
}
5351

54-
const operation = this.getOperation(operationMode, bpSession, apiClient, allOrgs)
52+
const operation = this.getOperation(operationMode, bpSession, apiClient)
5553
const source = fromStore ?? fromFile
5654
const destination = toStore ?? toFile
5755
await operation.execute(source as string, destination as string, this.flags)
5856
}
5957

60-
private getOperation(
61-
mode: OperationMode,
62-
bpSession: string,
63-
apiClient: ApiClient | MockApiClient,
64-
orgs: Organization[],
65-
) {
58+
private getOperation(mode: OperationMode, bpSession: string, apiClient: ApiClient | MockApiClient) {
6659
switch (mode) {
6760
case OperationMode.StoreCopy:
68-
return new StoreCopyOperation(bpSession, apiClient, orgs)
61+
return new StoreCopyOperation(bpSession, apiClient)
6962
case OperationMode.StoreExport:
70-
return new StoreExportOperation(bpSession, apiClient, orgs)
63+
return new StoreExportOperation(bpSession, apiClient)
7164
case OperationMode.StoreImport:
72-
return new StoreImportOperation(bpSession, apiClient, orgs)
65+
return new StoreImportOperation(bpSession, apiClient)
7366
default:
7467
throw new Error(`Unknown operation mode: ${mode}`)
7568
}

packages/store/src/prompts/copy_result.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ describe('renderCopyResult', () => {
5454
}
5555

5656
test('calls renderOperationResult with correct base message', () => {
57-
renderCopyResult(sourceShop, targetShop, mockOperation)
57+
renderCopyResult(sourceShop.domain, targetShop.domain, mockOperation)
5858

5959
expect(renderOperationResult).toHaveBeenCalledWith(
6060
[{subdued: 'From:'}, 'source-shop.myshopify.com', {subdued: '\nTo: '}, 'target-shop.myshopify.com'],
6161
mockOperation,
62-
targetShop,
62+
targetShop.domain,
6363
)
6464
})
6565
})
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import {renderOperationResult} from './operation_result.js'
2-
import {Shop} from '../apis/destinations/index.js'
32
import {BulkDataOperationByIdResponse} from '../apis/organizations/types.js'
43
import {Token} from '@shopify/cli-kit/node/ui'
54

65
export function renderCopyResult(
7-
sourceShop: Shop,
8-
targetShop: Shop,
6+
sourceShopDomain: string,
7+
targetShopDomain: string,
98
copyOperation: BulkDataOperationByIdResponse,
109
): void {
11-
const msg: Token[] = [{subdued: 'From:'}, sourceShop.domain, {subdued: '\nTo: '}, targetShop.domain]
12-
renderOperationResult(msg, copyOperation, targetShop)
10+
const msg: Token[] = [{subdued: 'From:'}, sourceShopDomain, {subdued: '\nTo: '}, targetShopDomain]
11+
renderOperationResult(msg, copyOperation, targetShopDomain)
1312
}

packages/store/src/prompts/export_results.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ describe('renderExportResult', () => {
5555
},
5656
}
5757

58-
renderExportResult(sourceShop, exportOperation)
58+
renderExportResult(sourceShop.domain, exportOperation)
5959

6060
expect(renderSuccess).toHaveBeenCalledWith({
6161
body: [
@@ -104,7 +104,7 @@ describe('renderExportResult', () => {
104104
},
105105
}
106106

107-
renderExportResult(sourceShop, exportOperation)
107+
renderExportResult(sourceShop.domain, exportOperation)
108108

109109
expect(renderWarning).toHaveBeenCalledWith({
110110
body: ['Export operation from', {info: 'source-shop.myshopify.com'}, 'completed with', {error: 'errors'}],
@@ -160,7 +160,7 @@ describe('renderExportResult', () => {
160160
},
161161
}
162162

163-
renderExportResult(sourceShop, exportOperation)
163+
renderExportResult(sourceShop.domain, exportOperation)
164164

165165
expect(renderWarning).toHaveBeenCalledWith({
166166
body: ['Export operation from', {info: 'source-shop.myshopify.com'}, 'completed with', {error: 'errors'}],

0 commit comments

Comments
 (0)