Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/silver-clouds-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/cli': patch
---

fix missing json output for theme info when no theme or dev flag is present
5 changes: 4 additions & 1 deletion packages/theme/src/cli/commands/theme/info.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {themeFlags} from '../../flags.js'
import {fetchThemeInfo, fetchDevInfo, formatThemeInfo} from '../../services/info.js'
import {fetchThemeInfo, fetchDevInfo, formatThemeInfo, devInfoJSON} from '../../services/info.js'
import ThemeCommand from '../../utilities/theme-command.js'
import {Flags} from '@oclif/core'
import {AdminSession} from '@shopify/cli-kit/node/session'
Expand Down Expand Up @@ -50,6 +50,9 @@ export default class Info extends ThemeCommand {
renderInfo(formattedInfo)
} else {
const infoMessage = await fetchDevInfo({cliVersion: this.config.version})
if (flags.json) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we're calling flags.json twice now. Can you look into merging that logic?

return outputResult(JSON.stringify(devInfoJSON({cliVersion: this.config.version}), null, 2))
}
renderInfo({customSections: infoMessage})
}
recordTiming('theme-command:info')
Expand Down
21 changes: 20 additions & 1 deletion packages/theme/src/cli/services/info.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {themeInfoJSON, fetchThemeInfo} from './info.js'
import {themeInfoJSON, fetchThemeInfo, devInfoJSON} from './info.js'
import {getDevelopmentTheme, getThemeStore} from './local-storage.js'
import {findOrSelectTheme} from '../utilities/theme-selector.js'
import {DevelopmentThemeManager} from '../utilities/development-theme-manager.js'
import {themePreviewUrl, themeEditorUrl} from '@shopify/cli-kit/node/themes/urls'
import {Theme} from '@shopify/cli-kit/node/themes/types'
import {describe, vi, test, expect} from 'vitest'

vi.mock('./local-storage.js')
vi.mock('../utilities/development-theme-manager.js')
vi.mock('../utilities/theme-selector.js', () => {
return {findOrSelectTheme: vi.fn()}
Expand Down Expand Up @@ -47,6 +49,23 @@ describe('info', () => {
expect(output).toHaveProperty('theme.editor_url', expect.stringContaining(session.storeFqdn))
})

test('generate dev info JSON when no theme or dev flag provided', () => {
// Given
vi.mocked(getThemeStore).mockReturnValue('my-shop.myshopify.com')
vi.mocked(getDevelopmentTheme).mockReturnValue(undefined)

// When
const output = devInfoJSON({cliVersion: '3.91.0'})

// Then
expect(output).toHaveProperty('store', 'my-shop.myshopify.com')
expect(output).toHaveProperty('development_theme_id', null)
expect(output).toHaveProperty('cli_version', '3.91.0')
expect(output).toHaveProperty('os', expect.stringContaining('-'))
expect(output).toHaveProperty('shell', process.env.SHELL ?? 'unknown')
expect(output).toHaveProperty('node_version', process.version)
})

test('fetch theme info by id', async () => {
// Given
vi.mocked(findOrSelectTheme).mockResolvedValue(theme)
Expand Down
22 changes: 22 additions & 0 deletions packages/theme/src/cli/services/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ interface ThemeInfoOptions {
json?: boolean
}

interface DevInfo {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we rename this to ThemeEnvironmentInfo?

store: string
development_theme_id: string | null
cli_version: string
os: string
shell: string
node_version: string
}

export function themeInfoJSON(theme: Theme, adminSession: AdminSession): ThemeInfo {
return {
theme: {
Expand All @@ -41,6 +50,19 @@ export function themeInfoJSON(theme: Theme, adminSession: AdminSession): ThemeIn
}
}

export function devInfoJSON(config: {cliVersion: string}): DevInfo {
const {platform, arch} = platformAndArch()
const store = getThemeStore()
return {
store: store ?? 'Not configured',
development_theme_id: store ? getDevelopmentTheme() ?? null : null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This took me a minute to understand. If you don't want to make it more verbose can we wrap the first part in () so like development_theme_id: store ? (getDevelopmentTheme() ?? null) : null, ? That way you can more easily ready that it's getDevelopmentTheme that may return null OR that if store isn't found we don't want to run that method and skip right to null as well.

cli_version: config.cliVersion,
os: `${platform}-${arch}`,
shell: process.env.SHELL ?? 'unknown',
node_version: process.version,
}
}

export async function fetchThemeInfo(
adminSession: AdminSession,
options: ThemeInfoOptions,
Expand Down