Skip to content

Commit 06e19d7

Browse files
committed
remove STDIN support on execute commands
1 parent 8d398cd commit 06e19d7

File tree

6 files changed

+16
-74
lines changed

6 files changed

+16
-74
lines changed

packages/app/src/cli/commands/app/bulk/execute.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default class BulkExecute extends AppLinkedCommand {
2121
async run(): Promise<AppLinkedCommandOutput> {
2222
const {flags} = await this.parse(BulkExecute)
2323

24-
const {query, appContextResult, store} = await prepareExecuteContext(flags, 'bulk execute')
24+
const {query, appContextResult, store} = await prepareExecuteContext(flags)
2525

2626
await executeBulkOperation({
2727
organization: appContextResult.organization,

packages/app/src/cli/commands/app/execute.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default class Execute extends AppLinkedCommand {
2020
async run(): Promise<AppLinkedCommandOutput> {
2121
const {flags} = await this.parse(Execute)
2222

23-
const {query, appContextResult, store} = await prepareExecuteContext(flags, 'execute')
23+
const {query, appContextResult, store} = await prepareExecuteContext(flags)
2424

2525
await executeOperation({
2626
organization: appContextResult.organization,

packages/app/src/cli/flags.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@ export const appFlags = {
3838
export const bulkOperationFlags = {
3939
query: Flags.string({
4040
char: 'q',
41-
description: 'The GraphQL query or mutation to run as a bulk operation. If omitted, reads from standard input.',
41+
description: 'The GraphQL query or mutation to run as a bulk operation.',
4242
env: 'SHOPIFY_FLAG_QUERY',
4343
required: false,
44-
exclusive: ['query-file'],
44+
exactlyOne: ['query', 'query-file'],
4545
}),
4646
'query-file': Flags.string({
4747
description: "Path to a file containing the GraphQL query or mutation. Can't be used with --query.",
4848
env: 'SHOPIFY_FLAG_QUERY_FILE',
4949
parse: async (input) => resolvePath(input),
50-
exclusive: ['query'],
50+
exactlyOne: ['query', 'query-file'],
5151
}),
5252
variables: Flags.string({
5353
char: 'v',
@@ -92,13 +92,13 @@ export const operationFlags = {
9292
description: 'The GraphQL query or mutation, as a string.',
9393
env: 'SHOPIFY_FLAG_QUERY',
9494
required: false,
95-
exclusive: ['query-file'],
95+
exactlyOne: ['query', 'query-file'],
9696
}),
9797
'query-file': Flags.string({
9898
description: "Path to a file containing the GraphQL query or mutation. Can't be used with --query.",
9999
env: 'SHOPIFY_FLAG_QUERY_FILE',
100100
parse: async (input) => resolvePath(input),
101-
exclusive: ['query'],
101+
exactlyOne: ['query', 'query-file'],
102102
}),
103103
variables: Flags.string({
104104
char: 'v',

packages/app/src/cli/utilities/execute-command-helpers.test.ts

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import {prepareAppStoreContext, prepareExecuteContext} from './execute-command-helpers.js'
22
import {linkedAppContext} from '../services/app-context.js'
33
import {storeContext} from '../services/store-context.js'
4-
import {readStdinString} from '@shopify/cli-kit/node/system'
54
import {readFile, fileExists} from '@shopify/cli-kit/node/fs'
65
import {describe, test, expect, vi, beforeEach} from 'vitest'
76

87
vi.mock('../services/app-context.js')
98
vi.mock('../services/store-context.js')
10-
vi.mock('@shopify/cli-kit/node/system')
119
vi.mock('@shopify/cli-kit/node/fs')
1210

1311
describe('prepareAppStoreContext', () => {
@@ -112,48 +110,18 @@ describe('prepareExecuteContext', () => {
112110
beforeEach(() => {
113111
vi.mocked(linkedAppContext).mockResolvedValue(mockAppContextResult as any)
114112
vi.mocked(storeContext).mockResolvedValue(mockStore as any)
115-
vi.mocked(readStdinString).mockResolvedValue('')
116113
})
117114

118115
test('uses query from flags when provided', async () => {
119116
const result = await prepareExecuteContext(mockFlags)
120117

121118
expect(result.query).toBe(mockFlags.query)
122-
expect(readStdinString).not.toHaveBeenCalled()
123119
})
124120

125-
test('reads query from stdin when flag not provided', async () => {
126-
const stdinQuery = 'query { products { edges { node { id } } } }'
127-
vi.mocked(readStdinString).mockResolvedValue(stdinQuery)
128-
129-
const flagsWithoutQuery = {...mockFlags, query: undefined}
130-
const result = await prepareExecuteContext(flagsWithoutQuery)
131-
132-
expect(readStdinString).toHaveBeenCalled()
133-
expect(result.query).toBe(stdinQuery)
134-
})
135-
136-
test('throws AbortError when no query provided via flag or stdin', async () => {
137-
vi.mocked(readStdinString).mockResolvedValue('')
138-
139-
const flagsWithoutQuery = {...mockFlags, query: undefined}
140-
141-
await expect(prepareExecuteContext(flagsWithoutQuery)).rejects.toThrow('No query provided')
142-
})
143-
144-
test('includes command name in error message', async () => {
145-
vi.mocked(readStdinString).mockResolvedValue('')
146-
121+
test('throws BugError when no query provided', async () => {
147122
const flagsWithoutQuery = {...mockFlags, query: undefined}
148123

149-
try {
150-
await prepareExecuteContext(flagsWithoutQuery, 'bulk execute')
151-
expect.fail('Should have thrown an error')
152-
// eslint-disable-next-line no-catch-all/no-catch-all
153-
} catch (error: any) {
154-
expect(error.message).toContain('No query provided')
155-
expect(error.tryMessage).toMatch(/shopify app bulk execute/)
156-
}
124+
await expect(prepareExecuteContext(flagsWithoutQuery)).rejects.toThrow('exactlyOne constraint')
157125
})
158126

159127
test('returns query, app context, and store', async () => {
@@ -184,7 +152,6 @@ describe('prepareExecuteContext', () => {
184152
expect(fileExists).toHaveBeenCalledWith('/path/to/query.graphql')
185153
expect(readFile).toHaveBeenCalledWith('/path/to/query.graphql', {encoding: 'utf8'})
186154
expect(result.query).toBe(queryFileContent)
187-
expect(readStdinString).not.toHaveBeenCalled()
188155
})
189156

190157
test('throws AbortError when query file does not exist', async () => {
@@ -195,15 +162,4 @@ describe('prepareExecuteContext', () => {
195162
await expect(prepareExecuteContext(flagsWithQueryFile)).rejects.toThrow('Query file not found')
196163
expect(readFile).not.toHaveBeenCalled()
197164
})
198-
199-
test('falls back to stdin when neither query nor query-file provided', async () => {
200-
const stdinQuery = 'query { shop { name } }'
201-
vi.mocked(readStdinString).mockResolvedValue(stdinQuery)
202-
203-
const flagsWithoutQueryOrFile = {...mockFlags, query: undefined}
204-
const result = await prepareExecuteContext(flagsWithoutQueryOrFile)
205-
206-
expect(readStdinString).toHaveBeenCalled()
207-
expect(result.query).toBe(stdinQuery)
208-
})
209165
})

packages/app/src/cli/utilities/execute-command-helpers.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import {linkedAppContext, LoadedAppContextOutput} from '../services/app-context.js'
22
import {storeContext} from '../services/store-context.js'
33
import {OrganizationStore} from '../models/organization.js'
4-
import {readStdinString} from '@shopify/cli-kit/node/system'
5-
import {AbortError} from '@shopify/cli-kit/node/error'
4+
import {AbortError, BugError} from '@shopify/cli-kit/node/error'
65
import {readFile, fileExists} from '@shopify/cli-kit/node/fs'
76
import {outputContent, outputToken} from '@shopify/cli-kit/node/output'
87

@@ -54,16 +53,12 @@ export async function prepareAppStoreContext(flags: AppStoreContextFlags): Promi
5453

5554
/**
5655
* Prepares the execution context for GraphQL operations.
57-
* Handles query input from flag, file, or stdin, and sets up app and store contexts.
56+
* Handles query input from flag or file, and sets up app and store contexts.
5857
*
5958
* @param flags - Command flags containing configuration options.
60-
* @param commandName - Name of the command for error messages (e.g., 'execute', 'bulk execute').
6159
* @returns Context object containing query, app context, and store information.
6260
*/
63-
export async function prepareExecuteContext(
64-
flags: ExecuteCommandFlags,
65-
commandName = 'execute',
66-
): Promise<ExecuteContext> {
61+
export async function prepareExecuteContext(flags: ExecuteCommandFlags): Promise<ExecuteContext> {
6762
let query: string | undefined
6863

6964
if (flags.query) {
@@ -76,14 +71,11 @@ export async function prepareExecuteContext(
7671
)
7772
}
7873
query = await readFile(queryFile, {encoding: 'utf8'})
79-
} else {
80-
query = await readStdinString()
8174
}
8275

8376
if (!query) {
84-
throw new AbortError(
85-
'No query provided. Use the --query flag, --query-file flag, or pipe input via stdin.',
86-
`Example: shopify app ${commandName} --query-file query.graphql`,
77+
throw new BugError(
78+
'Query should have been provided via --query or --query-file flags due to exactlyOne constraint. This indicates the oclif flag validation failed.',
8779
)
8880
}
8981

packages/cli/oclif.manifest.json

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
},
147147
"query": {
148148
"char": "q",
149-
"description": "The GraphQL query or mutation to run as a bulk operation. If omitted, reads from standard input.",
149+
"description": "The GraphQL query or mutation to run as a bulk operation.",
150150
"env": "SHOPIFY_FLAG_QUERY",
151151
"exclusive": [
152152
"query-file"
@@ -160,9 +160,6 @@
160160
"query-file": {
161161
"description": "Path to a file containing the GraphQL query or mutation. Can't be used with --query.",
162162
"env": "SHOPIFY_FLAG_QUERY_FILE",
163-
"exclusive": [
164-
"query"
165-
],
166163
"hasDynamicHelp": false,
167164
"multiple": false,
168165
"name": "query-file",
@@ -1212,9 +1209,6 @@
12121209
"query-file": {
12131210
"description": "Path to a file containing the GraphQL query or mutation. Can't be used with --query.",
12141211
"env": "SHOPIFY_FLAG_QUERY_FILE",
1215-
"exclusive": [
1216-
"query"
1217-
],
12181212
"hasDynamicHelp": false,
12191213
"multiple": false,
12201214
"name": "query-file",
@@ -7602,4 +7596,4 @@
76027596
}
76037597
},
76047598
"version": "3.88.0"
7605-
}
7599+
}

0 commit comments

Comments
 (0)