Skip to content

Commit

Permalink
Merge pull request #4628 from Shopify/use-app-context-in-basic-commands
Browse files Browse the repository at this point in the history
Use app context in some basic commands
  • Loading branch information
isaacroldan authored Oct 15, 2024
2 parents 3970350 + 11ab66d commit 71d9acb
Show file tree
Hide file tree
Showing 14 changed files with 124 additions and 240 deletions.
12 changes: 5 additions & 7 deletions packages/app/src/cli/commands/app/app-logs/sources.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {appFlags} from '../../../flags.js'
import {AppInterface} from '../../../models/app/app.js'
import {loadApp} from '../../../models/app/loader.js'
import {loadLocalExtensionsSpecifications} from '../../../models/extensions/load-specifications.js'
import {linkedAppContext} from '../../../services/app-context.js'
import {sources} from '../../../services/app-logs/sources.js'
import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js'
import {globalFlags} from '@shopify/cli-kit/node/cli'
Expand All @@ -20,12 +18,12 @@ export default class Sources extends AppCommand {

public async run(): Promise<AppCommandOutput> {
const {flags} = await this.parse(Sources)
const specifications = await loadLocalExtensionsSpecifications()
const app: AppInterface = await loadApp({
specifications,

const {app} = await linkedAppContext({
directory: flags.path,
clientId: undefined,
forceRelink: false,
userProvidedConfigName: flags.config,
mode: 'report',
})

if (app.errors) {
Expand Down
14 changes: 6 additions & 8 deletions packages/app/src/cli/commands/app/config/link.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {appFlags} from '../../../flags.js'
import {loadApp} from '../../../models/app/loader.js'
import {loadLocalExtensionsSpecifications} from '../../../models/extensions/load-specifications.js'
import {linkedAppContext} from '../../../services/app-context.js'
import link, {LinkOptions} from '../../../services/app/config/link.js'
import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js'
import {Flags} from '@oclif/core'
Expand Down Expand Up @@ -35,14 +34,13 @@ export default class ConfigLink extends AppCommand {
configName: flags.config,
}

await link(options)
const result = await link(options)

const specifications = await loadLocalExtensionsSpecifications()

const app = await loadApp({
specifications,
const {app} = await linkedAppContext({
directory: flags.path,
userProvidedConfigName: undefined,
clientId: undefined,
forceRelink: false,
userProvidedConfigName: result.state.configurationFileName,
})

return {app}
Expand Down
13 changes: 6 additions & 7 deletions packages/app/src/cli/commands/app/config/use.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {appFlags} from '../../../flags.js'
import {checkFolderIsValidApp, loadApp} from '../../../models/app/loader.js'
import {loadLocalExtensionsSpecifications} from '../../../models/extensions/load-specifications.js'
import {checkFolderIsValidApp} from '../../../models/app/loader.js'
import {linkedAppContext} from '../../../services/app-context.js'
import use from '../../../services/app/config/use.js'
import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js'
import {Args, Flags} from '@oclif/core'
Expand Down Expand Up @@ -42,12 +42,11 @@ export default class ConfigUse extends AppCommand {
await checkFolderIsValidApp(flags.path)
await use({directory: flags.path, configName: args.config, reset: flags.reset})

const specifications = await loadLocalExtensionsSpecifications()

const app = await loadApp({
specifications,
const {app} = await linkedAppContext({
directory: flags.path,
userProvidedConfigName: undefined,
clientId: undefined,
forceRelink: false,
userProvidedConfigName: args.config,
})

return {app}
Expand Down
12 changes: 5 additions & 7 deletions packages/app/src/cli/commands/app/demo/watcher.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {appFlags} from '../../../flags.js'
import {AppInterface} from '../../../models/app/app.js'
import {loadApp} from '../../../models/app/loader.js'
import {loadLocalExtensionsSpecifications} from '../../../models/extensions/load-specifications.js'
import {AppEventWatcher, EventType} from '../../../services/dev/app-events/app-event-watcher.js'
import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js'
import {linkedAppContext} from '../../../services/app-context.js'
import colors from '@shopify/cli-kit/node/colors'
import {globalFlags} from '@shopify/cli-kit/node/cli'
import {outputInfo} from '@shopify/cli-kit/node/output'
Expand All @@ -20,12 +18,12 @@ export default class DemoWatcher extends AppCommand {

public async run(): Promise<AppCommandOutput> {
const {flags} = await this.parse(DemoWatcher)
const specifications = await loadLocalExtensionsSpecifications()
const app: AppInterface = await loadApp({
specifications,

const {app} = await linkedAppContext({
directory: flags.path,
clientId: undefined,
forceRelink: false,
userProvidedConfigName: flags.config,
mode: 'report',
})

const watcher = new AppEventWatcher(app)
Expand Down
15 changes: 7 additions & 8 deletions packages/app/src/cli/commands/app/env/pull.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {appFlags} from '../../../flags.js'
import {AppInterface} from '../../../models/app/app.js'
import {getDotEnvFileName, loadApp} from '../../../models/app/loader.js'
import {getDotEnvFileName} from '../../../models/app/loader.js'
import {pullEnv} from '../../../services/app/env/pull.js'
import {loadLocalExtensionsSpecifications} from '../../../models/extensions/load-specifications.js'
import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js'
import {linkedAppContext} from '../../../services/app-context.js'
import {Flags} from '@oclif/core'
import {globalFlags} from '@shopify/cli-kit/node/cli'
import {outputInfo} from '@shopify/cli-kit/node/output'
Expand All @@ -30,15 +29,15 @@ export default class EnvPull extends AppCommand {

public async run(): Promise<AppCommandOutput> {
const {flags} = await this.parse(EnvPull)
const specifications = await loadLocalExtensionsSpecifications()
const app: AppInterface = await loadApp({
specifications,

const {app, remoteApp} = await linkedAppContext({
directory: flags.path,
clientId: undefined,
forceRelink: false,
userProvidedConfigName: flags.config,
mode: 'report',
})
const envFile = joinPath(app.directory, flags['env-file'] ?? getDotEnvFileName(app.configuration.path))
outputInfo(await pullEnv(app, {envFile}))
outputInfo(await pullEnv({app, remoteApp, envFile}))
return {app}
}
}
13 changes: 5 additions & 8 deletions packages/app/src/cli/commands/app/env/show.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {appFlags} from '../../../flags.js'
import {AppInterface} from '../../../models/app/app.js'
import {loadApp} from '../../../models/app/loader.js'
import {loadLocalExtensionsSpecifications} from '../../../models/extensions/load-specifications.js'
import {linkedAppContext} from '../../../services/app-context.js'
import {showEnv} from '../../../services/app/env/show.js'
import AppCommand, {AppCommandOutput} from '../../../utilities/app-command.js'
import {globalFlags} from '@shopify/cli-kit/node/cli'
Expand All @@ -21,14 +19,13 @@ export default class EnvShow extends AppCommand {

public async run(): Promise<AppCommandOutput> {
const {flags} = await this.parse(EnvShow)
const specifications = await loadLocalExtensionsSpecifications()
const app: AppInterface = await loadApp({
specifications,
const {app, remoteApp} = await linkedAppContext({
directory: flags.path,
clientId: undefined,
forceRelink: false,
userProvidedConfigName: flags.config,
mode: 'report',
})
outputInfo(await showEnv(app))
outputInfo(await showEnv(app, remoteApp))
return {app}
}
}
17 changes: 9 additions & 8 deletions packages/app/src/cli/commands/app/info.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {appFlags} from '../../flags.js'
import {AppInterface} from '../../models/app/app.js'
import {Format, info} from '../../services/info.js'
import {loadApp} from '../../models/app/loader.js'
import {loadLocalExtensionsSpecifications} from '../../models/extensions/load-specifications.js'
import AppCommand, {AppCommandOutput} from '../../utilities/app-command.js'
import {linkedAppContext} from '../../services/app-context.js'
import {Flags} from '@oclif/core'
import {globalFlags} from '@shopify/cli-kit/node/cli'
import {outputInfo} from '@shopify/cli-kit/node/output'
Expand Down Expand Up @@ -38,21 +36,24 @@ export default class AppInfo extends AppCommand {

public async run(): Promise<AppCommandOutput> {
const {flags} = await this.parse(AppInfo)
const specifications = await loadLocalExtensionsSpecifications()
const app: AppInterface = await loadApp({
specifications,

const {app, remoteApp, developerPlatformClient} = await linkedAppContext({
directory: flags.path,
clientId: undefined,
forceRelink: false,
userProvidedConfigName: flags.config,
mode: 'report',
unsafeReportMode: true,
})
outputInfo(
await info(app, {
await info(app, remoteApp, {
format: (flags.json ? 'json' : 'text') as Format,
webEnv: flags['web-env'],
configName: flags.config,
developerPlatformClient,
}),
)
if (app.errors) process.exit(2)

return {app}
}
}
15 changes: 9 additions & 6 deletions packages/app/src/cli/services/app/env/pull.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {pullEnv} from './pull.js'
import {AppInterface} from '../../../models/app/app.js'
import {AppInterface, AppLinkedInterface} from '../../../models/app/app.js'
import {testApp, testOrganizationApp} from '../../../models/app/app.test-data.js'
import {fetchAppFromConfigOrSelect} from '../fetch-app-from-config-or-select.js'
import {OrganizationApp} from '../../../models/organization.js'
import {describe, expect, vi, beforeEach, test} from 'vitest'
import * as file from '@shopify/cli-kit/node/fs'
import {resolvePath, joinPath} from '@shopify/cli-kit/node/path'
Expand All @@ -10,10 +11,12 @@ import {unstyled, stringifyMessage} from '@shopify/cli-kit/node/output'
vi.mock('../fetch-app-from-config-or-select')

describe('env pull', () => {
let app: AppInterface
let app: AppLinkedInterface
let remoteApp: OrganizationApp

beforeEach(async () => {
app = mockApp()
app = mockApp() as AppLinkedInterface
remoteApp = testOrganizationApp()
vi.mocked(fetchAppFromConfigOrSelect).mockResolvedValue(testOrganizationApp())
})

Expand All @@ -24,7 +27,7 @@ describe('env pull', () => {

// When
const filePath = resolvePath(tmpDir, '.env')
const result = await pullEnv(app, {envFile: filePath})
const result = await pullEnv({app, remoteApp, envFile: filePath})

// Then
expect(file.writeFile).toHaveBeenCalledWith(
Expand All @@ -50,7 +53,7 @@ describe('env pull', () => {
vi.spyOn(file, 'writeFile')

// When
const result = await pullEnv(app, {envFile: filePath})
const result = await pullEnv({app, remoteApp, envFile: filePath})

// Then
expect(file.writeFile).toHaveBeenCalledWith(
Expand Down Expand Up @@ -84,7 +87,7 @@ describe('env pull', () => {
vi.spyOn(file, 'writeFile')

// When
const result = await pullEnv(app, {envFile: filePath})
const result = await pullEnv({app, remoteApp, envFile: filePath})

// Then
expect(file.writeFile).not.toHaveBeenCalled()
Expand Down
20 changes: 8 additions & 12 deletions packages/app/src/cli/services/app/env/pull.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
import {AppInterface, getAppScopes} from '../../../models/app/app.js'
import {fetchAppFromConfigOrSelect} from '../fetch-app-from-config-or-select.js'
import {AppLinkedInterface, getAppScopes} from '../../../models/app/app.js'

import {logMetadataForLoadedContext} from '../../context.js'

import {OrganizationApp} from '../../../models/organization.js'
import {patchEnvFile} from '@shopify/cli-kit/node/dot-env'
import {diffLines} from 'diff'
import {fileExists, readFile, writeFile} from '@shopify/cli-kit/node/fs'
import {OutputMessage, outputContent, outputToken} from '@shopify/cli-kit/node/output'

interface PullEnvOptions {
app: AppLinkedInterface
remoteApp: OrganizationApp
envFile: string
}

export async function pullEnv(app: AppInterface, {envFile}: PullEnvOptions): Promise<OutputMessage> {
return updateEnvFile(app, envFile)
}

async function updateEnvFile(app: AppInterface, envFile: PullEnvOptions['envFile']): Promise<OutputMessage> {
const orgApp = await fetchAppFromConfigOrSelect(app)

await logMetadataForLoadedContext(orgApp)
export async function pullEnv({app, remoteApp, envFile}: PullEnvOptions): Promise<OutputMessage> {
await logMetadataForLoadedContext(remoteApp)

const updatedValues = {
SHOPIFY_API_KEY: orgApp.apiKey,
SHOPIFY_API_SECRET: orgApp.apiSecretKeys[0]?.secret,
SHOPIFY_API_KEY: remoteApp.apiKey,
SHOPIFY_API_SECRET: remoteApp.apiSecretKeys[0]?.secret,
SCOPES: getAppScopes(app.configuration),
}

Expand Down
10 changes: 3 additions & 7 deletions packages/app/src/cli/services/app/env/show.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {fetchOrganizations} from '../../dev/fetch.js'
import {fetchAppFromConfigOrSelect} from '../fetch-app-from-config-or-select.js'
import {AppInterface} from '../../../models/app/app.js'
import {selectOrganizationPrompt} from '../../../prompts/dev.js'
import {testDeveloperPlatformClient, testApp, testOrganizationApp} from '../../../models/app/app.test-data.js'
import {testApp, testOrganizationApp} from '../../../models/app/app.test-data.js'
import {describe, expect, vi, test} from 'vitest'
import * as file from '@shopify/cli-kit/node/fs'
import {stringifyMessage, unstyled} from '@shopify/cli-kit/node/output'
Expand All @@ -20,6 +20,7 @@ describe('env show', () => {
vi.spyOn(file, 'writeFile')

const app = mockApp()
const remoteApp = testOrganizationApp()
const organization = {
id: '123',
flags: {},
Expand All @@ -33,12 +34,7 @@ describe('env show', () => {
vi.mocked(fetchAppFromConfigOrSelect).mockResolvedValue(organizationApp)

// When
const result = await showEnv(
app,
testDeveloperPlatformClient({
orgAndApps: () => Promise.resolve({organization, apps: [organizationApp], hasMorePages: false}),
}),
)
const result = await showEnv(app, remoteApp)

// Then
expect(file.writeFile).not.toHaveBeenCalled()
Expand Down
28 changes: 9 additions & 19 deletions packages/app/src/cli/services/app/env/show.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,27 @@
import {AppInterface, getAppScopes} from '../../../models/app/app.js'
import {DeveloperPlatformClient, selectDeveloperPlatformClient} from '../../../utilities/developer-platform-client.js'
import {OrganizationApp} from '../../../models/organization.js'
import {logMetadataForLoadedContext} from '../../context.js'
import {fetchAppFromConfigOrSelect} from '../fetch-app-from-config-or-select.js'
import {OutputMessage, outputContent, outputToken} from '@shopify/cli-kit/node/output'

type Format = 'json' | 'text'

export async function showEnv(
app: AppInterface,
developerPlatformClient: DeveloperPlatformClient = selectDeveloperPlatformClient({configuration: app.configuration}),
): Promise<OutputMessage> {
return outputEnv(app, 'text', developerPlatformClient)
export async function showEnv(app: AppInterface, remoteApp: OrganizationApp): Promise<OutputMessage> {
return outputEnv(app, remoteApp, 'text')
}

export async function outputEnv(
app: AppInterface,
format: Format,
developerPlatformClient: DeveloperPlatformClient = selectDeveloperPlatformClient({configuration: app.configuration}),
): Promise<OutputMessage> {
const orgApp = await fetchAppFromConfigOrSelect(app, developerPlatformClient)

await logMetadataForLoadedContext(orgApp)
export async function outputEnv(app: AppInterface, remoteApp: OrganizationApp, format: Format): Promise<OutputMessage> {
await logMetadataForLoadedContext(remoteApp)

if (format === 'json') {
return outputContent`${outputToken.json({
SHOPIFY_API_KEY: orgApp.apiKey,
SHOPIFY_API_SECRET: orgApp.apiSecretKeys[0]?.secret,
SHOPIFY_API_KEY: remoteApp.apiKey,
SHOPIFY_API_SECRET: remoteApp.apiSecretKeys[0]?.secret,
SCOPES: getAppScopes(app.configuration),
})}`
} else {
return outputContent`
${outputToken.green('SHOPIFY_API_KEY')}=${orgApp.apiKey}
${outputToken.green('SHOPIFY_API_SECRET')}=${orgApp.apiSecretKeys[0]?.secret ?? ''}
${outputToken.green('SHOPIFY_API_KEY')}=${remoteApp.apiKey}
${outputToken.green('SHOPIFY_API_SECRET')}=${remoteApp.apiSecretKeys[0]?.secret ?? ''}
${outputToken.green('SCOPES')}=${getAppScopes(app.configuration)}
`
}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/cli/services/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ interface AppContext {
* @param directory - The directory containing the app.
* @param developerPlatformClient - The client to access the platform API
*/
export async function getAppContext({
async function getAppContext({
reset,
directory,
configName,
Expand Down
Loading

0 comments on commit 71d9acb

Please sign in to comment.