Skip to content

Commit 6d8cd8a

Browse files
committed
Return version result as an object
Assisted-By: devx/c4197d39-027e-4413-9b97-5c38707a9864
1 parent 11456a6 commit 6d8cd8a

10 files changed

Lines changed: 114 additions & 50 deletions

File tree

‎packages/cli/README.md‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5859,7 +5859,16 @@ DESCRIPTION
58595859
58605860
```json
58615861
{
5862-
"type": "string",
5862+
"type": "object",
5863+
"properties": {
5864+
"version": {
5865+
"type": "string"
5866+
}
5867+
},
5868+
"required": [
5869+
"version"
5870+
],
5871+
"additionalProperties": false,
58635872
"title": "VersionResult",
58645873
"$schema": "http://json-schema.org/draft-07/schema#"
58655874
}

‎packages/cli/oclif.manifest.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11492,7 +11492,7 @@
1149211492
],
1149311493
"args": {
1149411494
},
11495-
"description": "Shopify CLI version currently installed.\n\nOutput from `--json` conforms to the `VersionResult` schema.\n\nUse `--json-schema` to print the result, error, and event schemas.\n\n```json\n{\n \"type\": \"string\",\n \"title\": \"VersionResult\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```",
11495+
"description": "Shopify CLI version currently installed.\n\nOutput from `--json` conforms to the `VersionResult` schema.\n\nUse `--json-schema` to print the result, error, and event schemas.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"version\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"version\"\n ],\n \"additionalProperties\": false,\n \"title\": \"VersionResult\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```",
1149611496
"descriptionWithMarkdown": "Shopify CLI version currently installed.",
1149711497
"enableJsonFlag": false,
1149811498
"flags": {

‎packages/cli/src/cli/commands/version.test.ts‎

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import Version from './version.js'
2-
import {versionJsonOutputSchema, versionService} from '../services/commands/version.js'
2+
import {versionService} from '../services/commands/version/index.js'
3+
import {versionJsonOutputSchema} from '../services/commands/version/types.js'
34
import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version'
45
import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output'
56
import {execa} from 'execa'
67
import {afterEach, describe, expect, test, vi} from 'vitest'
78

8-
vi.mock('../services/commands/version.js', async (importOriginal) => ({
9-
...(await importOriginal<typeof import('../services/commands/version.js')>()),
9+
vi.mock('../services/commands/version/index.js', async (importOriginal) => ({
10+
...(await importOriginal<typeof import('../services/commands/version/index.js')>()),
1011
versionService: vi.fn(),
1112
}))
1213

@@ -44,7 +45,7 @@ const runVersion = async (arguments_: string[]) => {
4445
describe('version command', () => {
4546
test('writes the raw version text by default', async () => {
4647
const outputMock = mockAndCaptureOutput()
47-
vi.mocked(versionService).mockResolvedValue('2.2.2')
48+
vi.mocked(versionService).mockResolvedValue({version: '2.2.2'})
4849

4950
await Version.run([], import.meta.url)
5051

@@ -53,22 +54,22 @@ describe('version command', () => {
5354
expect(outputMock.warn()).toBe('')
5455
})
5556

56-
test('writes one scalar JSON document when requested', async () => {
57+
test('writes one JSON document when requested', async () => {
5758
const outputMock = mockAndCaptureOutput()
58-
vi.mocked(versionService).mockResolvedValue('2.2.2')
59+
vi.mocked(versionService).mockResolvedValue({version: '2.2.2'})
5960

6061
await Version.run(['--json'], import.meta.url)
6162

62-
expect(outputMock.output()).toBe('"2.2.2"')
63-
expect(JSON.parse(outputMock.output())).toBe('2.2.2')
63+
expect(outputMock.output()).toBe(JSON.stringify({version: '2.2.2'}, null, 2))
64+
expect(JSON.parse(outputMock.output())).toEqual({version: '2.2.2'})
6465
expect(outputMock.warn()).toBe('')
6566
})
6667

67-
test('exposes the scalar schema and JSON flags in help', () => {
68+
test('exposes the object schema and JSON flags in help', () => {
6869
expect(Version.jsonOutputSchema).toBe(versionJsonOutputSchema)
6970
expect(Version.flags.json).toBeDefined()
7071
expect(Version.description).toContain('Output from `--json` conforms to the `VersionResult` schema.')
71-
expect(Version.description).toContain('"type": "string"')
72+
expect(Version.description).toContain('"type": "object"')
7273
})
7374

7475
test('writes the installed version without stderr output', {timeout: 20000}, async () => {
@@ -84,15 +85,19 @@ describe('version command', () => {
8485

8586
expect(result.exitCode).toBe(0)
8687
expect(result.stderr).toBe('')
87-
expect(result.stdout).toBe(`${JSON.stringify(CLI_KIT_VERSION)}\n`)
88-
expect(JSON.parse(result.stdout)).toBe(CLI_KIT_VERSION)
88+
expect(result.stdout).toBe(`${JSON.stringify({version: CLI_KIT_VERSION}, null, 2)}\n`)
89+
expect(JSON.parse(result.stdout)).toEqual({version: CLI_KIT_VERSION})
8990
})
9091

91-
test('writes a schema with a string result without stderr output', {timeout: 20000}, async () => {
92+
test('writes a schema with an object result without stderr output', {timeout: 20000}, async () => {
9293
const result = await runVersion(['--json-schema'])
9394

9495
expect(result.exitCode).toBe(0)
9596
expect(result.stderr).toBe('')
96-
expect(JSON.parse(result.stdout).definitions.Result.type).toBe('string')
97+
const definition = JSON.parse(result.stdout).definitions.Result
98+
expect(definition.type).toBe('object')
99+
expect(definition.properties.version).toEqual({type: 'string'})
100+
expect(definition.required).toEqual(['version'])
101+
expect(definition.additionalProperties).toBe(false)
97102
})
98103
})

‎packages/cli/src/cli/commands/version.ts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import {versionJsonOutputSchema, versionService} from '../services/commands/version.js'
1+
import {versionService} from '../services/commands/version/index.js'
2+
import {presentVersionResult} from '../services/commands/version/result.js'
3+
import {versionJsonOutputSchema} from '../services/commands/version/types.js'
24
import Command from '@shopify/cli-kit/node/base-command'
35
import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli'
4-
import {outputResult} from '@shopify/cli-kit/node/output'
56

67
export default class Version extends Command {
78
static descriptionWithMarkdown = 'Shopify CLI version currently installed.'
@@ -19,8 +20,8 @@ export default class Version extends Command {
1920

2021
async run(): Promise<void> {
2122
const {flags} = await this.parse(Version)
22-
const version = await versionService()
23+
const result = await versionService()
2324

24-
outputResult(flags.json ? versionJsonOutputSchema.encode(version) : version)
25+
presentVersionResult(result, flags.json ? 'json' : 'text')
2526
}
2627
}

‎packages/cli/src/cli/services/commands/version.test.ts‎

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {versionService} from './index.js'
2+
import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output'
3+
import {afterEach, describe, expect, test, vi} from 'vitest'
4+
5+
vi.mock('@shopify/cli-kit/common/version', () => ({CLI_KIT_VERSION: '2.2.2'}))
6+
7+
afterEach(() => {
8+
mockAndCaptureOutput().clear()
9+
})
10+
11+
describe('version service', () => {
12+
test('returns the installed version as an object without writing output', async () => {
13+
const outputMock = mockAndCaptureOutput()
14+
15+
await expect(versionService()).resolves.toEqual({version: '2.2.2'})
16+
17+
expect(outputMock.output()).toBe('')
18+
})
19+
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version'
2+
import type {VersionResult} from './types.js'
3+
4+
export async function versionService(): Promise<VersionResult> {
5+
return {version: CLI_KIT_VERSION}
6+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {presentVersionResult} from './result.js'
2+
import {versionJsonOutputSchema} from './types.js'
3+
import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output'
4+
import {afterEach, describe, expect, test} from 'vitest'
5+
6+
afterEach(() => {
7+
mockAndCaptureOutput().clear()
8+
})
9+
10+
describe('presentVersionResult', () => {
11+
test('writes the raw version text by default', () => {
12+
const outputMock = mockAndCaptureOutput()
13+
14+
presentVersionResult({version: '2.2.2'}, 'text')
15+
16+
expect(outputMock.output()).toBe('2.2.2')
17+
expect(outputMock.warn()).toBe('')
18+
})
19+
20+
test('writes one JSON document when requested', () => {
21+
const outputMock = mockAndCaptureOutput()
22+
23+
presentVersionResult({version: '2.2.2'}, 'json')
24+
25+
expect(outputMock.output()).toBe(JSON.stringify({version: '2.2.2'}, null, 2))
26+
expect(JSON.parse(outputMock.output())).toEqual({version: '2.2.2'})
27+
})
28+
})
29+
30+
describe('version JSON result contract', () => {
31+
test('encodes an object with a version string', () => {
32+
expect(versionJsonOutputSchema.encode({version: '2.2.2'})).toBe(JSON.stringify({version: '2.2.2'}, null, 2))
33+
})
34+
35+
test.each([['2.2.2'], [{}], [{version: 1}]])('rejects %j', (value) => {
36+
expect(() => versionJsonOutputSchema.validate(value)).toThrow()
37+
})
38+
39+
test('declares a closed object schema with a required version string', () => {
40+
expect(versionJsonOutputSchema.jsonSchema).toMatchObject({
41+
type: 'object',
42+
properties: {version: {type: 'string'}},
43+
required: ['version'],
44+
additionalProperties: false,
45+
})
46+
})
47+
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import {versionJsonOutputSchema, type VersionResult} from './types.js'
2+
import {outputResult} from '@shopify/cli-kit/node/output'
3+
4+
export function presentVersionResult(result: VersionResult, format: 'json' | 'text'): void {
5+
outputResult(format === 'json' ? versionJsonOutputSchema.encode(result) : result.version)
6+
}
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version'
21
import {defineJsonOutputSchema, type InferJsonOutputSchema} from '@shopify/cli-kit/node/json-output-schema'
32
import {zod} from '@shopify/cli-kit/node/schema'
43

54
export const versionJsonOutputSchema = defineJsonOutputSchema({
65
name: 'VersionResult',
7-
schema: zod.string(),
6+
schema: zod.object({version: zod.string()}),
87
})
98

109
export type VersionResult = InferJsonOutputSchema<typeof versionJsonOutputSchema>
11-
12-
export async function versionService(): Promise<VersionResult> {
13-
return CLI_KIT_VERSION
14-
}

0 commit comments

Comments
 (0)