Skip to content

Commit

Permalink
Merge pull request #3590 from Shopify/introduce-import-payments-exten…
Browse files Browse the repository at this point in the history
…sion

Make the fetching of dashboard extensions generic
  • Loading branch information
yigitozkavci committed Mar 25, 2024
2 parents f8ed8f9 + 15f2703 commit b30df5e
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {buildTomlObject} from '../../services/flow/extension-to-toml.js'
import {appFlags} from '../../flags.js'
import {loadApp} from '../../models/app/loader.js'
import {AppInterface} from '../../models/app/app.js'
import {importFlowExtensions} from '../../services/import-flow-legacy-extensions.js'
import {importDashboardExtensions} from '../../services/import-dashboard-extensions.js'
import Command from '../../utilities/app-command.js'
import {loadLocalExtensionsSpecifications} from '../../models/extensions/load-specifications.js'
import {Flags} from '@oclif/core'
Expand All @@ -26,6 +27,12 @@ export default class AppImportFlowExtension extends Command {
const specifications = await loadLocalExtensionsSpecifications()
const app: AppInterface = await loadApp({specifications, directory: flags.path, configName: flags.config})

await importFlowExtensions({app, apiKey: flags['client-id']})
const flowExtensionTypes = ['flow_action_definition', 'flow_trigger_definition']
await importDashboardExtensions({
app,
apiKey: flags['client-id'],
extensionTypes: flowExtensionTypes,
buildTomlObject,
})
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {getActiveDashboardExtensions} from './fetch-flow-dashboard-extensions.js'
import {testDeveloperPlatformClient} from '../../models/app/app.test-data.js'
import {AllAppExtensionRegistrationsQuerySchema} from '../../api/graphql/all_app_extension_registrations.js'
import {MinimalAppIdentifiers} from '../../models/organization.js'
import {getActiveDashboardExtensions} from './fetch-dashboard-extensions.js'
import {testDeveloperPlatformClient} from '../models/app/app.test-data.js'
import {AllAppExtensionRegistrationsQuerySchema} from '../api/graphql/all_app_extension_registrations.js'
import {MinimalAppIdentifiers} from '../models/organization.js'
import {describe, expect, vi} from 'vitest'

vi.mock('../dev/fetch')
Expand Down Expand Up @@ -55,7 +55,12 @@ describe('getActiveDashboardExtensions', (it) => {
})

// When
const got = await getActiveDashboardExtensions({developerPlatformClient, apiKey: 'apiKey', organizationId: '1'})
const got = await getActiveDashboardExtensions({
developerPlatformClient,
apiKey: 'apiKey',
organizationId: '1',
extensionTypes: ['flow_action_definition', 'flow_trigger_definition'],
})

// Then
expect(got).toEqual([
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js'
import {DeveloperPlatformClient} from '../utilities/developer-platform-client.js'

export async function getActiveDashboardExtensions({
developerPlatformClient,
apiKey,
organizationId,
extensionTypes,
}: {
developerPlatformClient: DeveloperPlatformClient
apiKey: string
organizationId: string
extensionTypes: string[]
}) {
const initialRemoteExtensions = await developerPlatformClient.appExtensionRegistrations({
id: apiKey,
Expand All @@ -16,9 +18,9 @@ export async function getActiveDashboardExtensions({
})
const {dashboardManagedExtensionRegistrations} = initialRemoteExtensions.app
return dashboardManagedExtensionRegistrations.filter((ext) => {
const isFlow = ext.type === 'flow_action_definition' || ext.type === 'flow_trigger_definition'
const isNeededExtensionType = extensionTypes.includes(ext.type)
const hasActiveVersion = ext.activeVersion && ext.activeVersion.config
const hasDraftVersion = ext.draftVersion && ext.draftVersion.config
return isFlow && (hasActiveVersion || hasDraftVersion)
return isNeededExtensionType && (hasActiveVersion || hasDraftVersion)
})
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {importFlowExtensions} from './import-flow-legacy-extensions.js'
import {importDashboardExtensions} from './import-dashboard-extensions.js'
import {fetchAppAndIdentifiers} from './context.js'
import {getActiveDashboardExtensions} from './flow/fetch-flow-dashboard-extensions.js'
import {getActiveDashboardExtensions} from './fetch-dashboard-extensions.js'
import {buildTomlObject} from './flow/extension-to-toml.js'
import {testApp, testDeveloperPlatformClient} from '../models/app/app.test-data.js'
import {OrganizationApp} from '../models/organization.js'
import {ExtensionRegistration} from '../api/graphql/all_app_extension_registrations.js'
Expand All @@ -11,7 +12,7 @@ import {joinPath} from '@shopify/cli-kit/node/path'

vi.mock('@shopify/cli-kit/node/ui')
vi.mock('./context.js')
vi.mock('./flow/fetch-flow-dashboard-extensions.js')
vi.mock('./fetch-dashboard-extensions.js')
vi.mock('./context/partner-account-info.js')

const organizationApp: OrganizationApp = {
Expand Down Expand Up @@ -44,7 +45,7 @@ const flowExtensionB: ExtensionRegistration = {
},
}

describe('import-flow-legacy-extensions', () => {
describe('import-dashboard-extensions', () => {
test('importing an extension creates a folder and toml file', async () => {
// Given
vi.mocked(fetchAppAndIdentifiers).mockResolvedValue([organizationApp, {}])
Expand All @@ -55,7 +56,12 @@ describe('import-flow-legacy-extensions', () => {
await inTemporaryDirectory(async (tmpDir) => {
const app = testApp({directory: tmpDir})

await importFlowExtensions({app, developerPlatformClient: testDeveloperPlatformClient()})
await importDashboardExtensions({
app,
developerPlatformClient: testDeveloperPlatformClient(),
extensionTypes: ['flow_action_definition', 'flow_trigger_definition'],
buildTomlObject,
})

expect(renderSuccess).toHaveBeenCalledWith({
headline: ['Imported the following extensions from the dashboard:'],
Expand All @@ -81,7 +87,12 @@ describe('import-flow-legacy-extensions', () => {
await inTemporaryDirectory(async (tmpDir) => {
const app = testApp({directory: tmpDir})

await importFlowExtensions({app, developerPlatformClient: testDeveloperPlatformClient()})
await importDashboardExtensions({
app,
developerPlatformClient: testDeveloperPlatformClient(),
extensionTypes: ['flow_action_definition', 'flow_trigger_definition'],
buildTomlObject,
})

expect(renderSuccess).toHaveBeenCalledWith({
headline: ['Imported the following extensions from the dashboard:'],
Expand All @@ -105,10 +116,11 @@ describe('import-flow-legacy-extensions', () => {
// When
await inTemporaryDirectory(async (tmpDir) => {
const app = testApp({directory: tmpDir})

await importFlowExtensions({
await importDashboardExtensions({
app,
developerPlatformClient: testDeveloperPlatformClient(),
extensionTypes: ['flow_action_definition', 'flow_trigger_definition'],
buildTomlObject,
})

// Then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {fetchAppAndIdentifiers, logMetadataForLoadedContext} from './context.js'
import {ensureExtensionDirectoryExists} from './extensions/common.js'
import {buildTomlObject} from './flow/extension-to-toml.js'
import {getActiveDashboardExtensions} from './flow/fetch-flow-dashboard-extensions.js'
import {getActiveDashboardExtensions} from './fetch-dashboard-extensions.js'
import {AppInterface} from '../models/app/app.js'
import {updateAppIdentifiers, IdentifiersExtensions} from '../models/app/identifiers.js'
import {ExtensionRegistration} from '../api/graphql/all_app_extension_registrations.js'
Expand All @@ -11,42 +10,45 @@ import {basename, joinPath} from '@shopify/cli-kit/node/path'
import {writeFile} from '@shopify/cli-kit/node/fs'
import {outputContent} from '@shopify/cli-kit/node/output'

interface ImportFlowOptions {
interface ImportOptions {
app: AppInterface
apiKey?: string
developerPlatformClient?: DeveloperPlatformClient
extensionTypes: string[]
buildTomlObject: (ext: ExtensionRegistration) => string
}

export async function importFlowExtensions(options: ImportFlowOptions) {
export async function importDashboardExtensions(options: ImportOptions) {
const developerPlatformClient = options.developerPlatformClient ?? selectDeveloperPlatformClient()
const [remoteApp, _] = await fetchAppAndIdentifiers({...options, reset: false}, developerPlatformClient, false)

await logMetadataForLoadedContext(remoteApp)

const flowExtensions = await getActiveDashboardExtensions({
const extensions = await getActiveDashboardExtensions({
developerPlatformClient,
apiKey: remoteApp.apiKey,
organizationId: remoteApp.organizationId,
extensionTypes: options.extensionTypes,
})

if (flowExtensions.length === 0) {
if (extensions.length === 0) {
renderSuccess({headline: ['No extensions to migrate.']})
return
}

const choices = flowExtensions.map((ext) => {
const choices = extensions.map((ext) => {
return {label: ext.title, value: ext.uuid}
})
choices.push({label: 'All', value: 'All'})
const promptAnswer = await renderSelectPrompt({message: 'Extensions to migrate', choices})

const extensionsToMigrate =
promptAnswer === 'All' ? flowExtensions : [flowExtensions.find((ext) => ext?.uuid === promptAnswer)!]
promptAnswer === 'All' ? extensions : [extensions.find((ext) => ext?.uuid === promptAnswer)!]

const extensionUuids: IdentifiersExtensions = {}
const importPromises = extensionsToMigrate.map(async (ext) => {
const directory = await ensureExtensionDirectoryExists({app: options.app, name: ext.title})
const tomlObject = buildTomlObject(ext)
const tomlObject = options.buildTomlObject(ext)
const path = joinPath(directory, 'shopify.extension.toml')
await writeFile(path, tomlObject)
extensionUuids[ext.title] = ext.uuid
Expand Down

0 comments on commit b30df5e

Please sign in to comment.