Skip to content

Commit f696432

Browse files
committed
shopify app bulk cancel command to cancel bulkops through CLI
1 parent 06d8de3 commit f696432

File tree

12 files changed

+730
-28
lines changed

12 files changed

+730
-28
lines changed

packages/app/src/cli/api/graphql/app-dev/generated/types.d.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any, tsdoc/syntax */
1+
/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention, tsdoc/syntax */
22
import {JsonMapType} from '@shopify/cli-kit/node/toml'
33

44
export type Maybe<T> = T | null
@@ -15,12 +15,6 @@ export type Scalars = {
1515
Boolean: {input: boolean; output: boolean}
1616
Int: {input: number; output: number}
1717
Float: {input: number; output: number}
18-
/**
19-
* Represents an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)-encoded date and time string.
20-
* For example, 3:50 pm on September 7, 2019 in the time zone of UTC (Coordinated Universal Time) is
21-
* represented as `"2019-09-07T15:50:00Z`".
22-
*/
23-
DateTime: {input: any; output: any}
2418
/**
2519
* A [JSON](https://www.json.org/json-en.html) object.
2620
*
@@ -37,12 +31,4 @@ export type Scalars = {
3731
* }`
3832
*/
3933
JSON: {input: JsonMapType | string; output: JsonMapType}
40-
/**
41-
* Represents an [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and
42-
* [RFC 3987](https://datatracker.ietf.org/doc/html/rfc3987)-compliant URI string.
43-
*
44-
* For example, `"https://example.myshopify.com"` is a valid URL. It includes a scheme (`https`) and a host
45-
* (`example.myshopify.com`).
46-
*/
47-
URL: {input: string; output: string}
4834
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/no-redundant-type-constituents */
2+
import * as Types from './types.js'
3+
4+
import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'
5+
6+
export type BulkOperationCancelMutationVariables = Types.Exact<{
7+
id: Types.Scalars['ID']['input']
8+
}>
9+
10+
export type BulkOperationCancelMutation = {
11+
bulkOperationCancel?: {
12+
bulkOperation?: {
13+
completedAt?: unknown | null
14+
createdAt: unknown
15+
errorCode?: Types.BulkOperationErrorCode | null
16+
fileSize?: unknown | null
17+
id: string
18+
objectCount: unknown
19+
partialDataUrl?: string | null
20+
query: string
21+
rootObjectCount: unknown
22+
status: Types.BulkOperationStatus
23+
type: Types.BulkOperationType
24+
url?: string | null
25+
} | null
26+
userErrors: {field?: string[] | null; message: string}[]
27+
} | null
28+
}
29+
30+
export const BulkOperationCancel = {
31+
kind: 'Document',
32+
definitions: [
33+
{
34+
kind: 'OperationDefinition',
35+
operation: 'mutation',
36+
name: {kind: 'Name', value: 'BulkOperationCancel'},
37+
variableDefinitions: [
38+
{
39+
kind: 'VariableDefinition',
40+
variable: {kind: 'Variable', name: {kind: 'Name', value: 'id'}},
41+
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'ID'}}},
42+
},
43+
],
44+
selectionSet: {
45+
kind: 'SelectionSet',
46+
selections: [
47+
{
48+
kind: 'Field',
49+
name: {kind: 'Name', value: 'bulkOperationCancel'},
50+
arguments: [
51+
{
52+
kind: 'Argument',
53+
name: {kind: 'Name', value: 'id'},
54+
value: {kind: 'Variable', name: {kind: 'Name', value: 'id'}},
55+
},
56+
],
57+
selectionSet: {
58+
kind: 'SelectionSet',
59+
selections: [
60+
{
61+
kind: 'Field',
62+
name: {kind: 'Name', value: 'bulkOperation'},
63+
selectionSet: {
64+
kind: 'SelectionSet',
65+
selections: [
66+
{kind: 'Field', name: {kind: 'Name', value: 'completedAt'}},
67+
{kind: 'Field', name: {kind: 'Name', value: 'createdAt'}},
68+
{kind: 'Field', name: {kind: 'Name', value: 'errorCode'}},
69+
{kind: 'Field', name: {kind: 'Name', value: 'fileSize'}},
70+
{kind: 'Field', name: {kind: 'Name', value: 'id'}},
71+
{kind: 'Field', name: {kind: 'Name', value: 'objectCount'}},
72+
{kind: 'Field', name: {kind: 'Name', value: 'partialDataUrl'}},
73+
{kind: 'Field', name: {kind: 'Name', value: 'query'}},
74+
{kind: 'Field', name: {kind: 'Name', value: 'rootObjectCount'}},
75+
{kind: 'Field', name: {kind: 'Name', value: 'status'}},
76+
{kind: 'Field', name: {kind: 'Name', value: 'type'}},
77+
{kind: 'Field', name: {kind: 'Name', value: 'url'}},
78+
{kind: 'Field', name: {kind: 'Name', value: '__typename'}},
79+
],
80+
},
81+
},
82+
{
83+
kind: 'Field',
84+
name: {kind: 'Name', value: 'userErrors'},
85+
selectionSet: {
86+
kind: 'SelectionSet',
87+
selections: [
88+
{kind: 'Field', name: {kind: 'Name', value: 'field'}},
89+
{kind: 'Field', name: {kind: 'Name', value: 'message'}},
90+
{kind: 'Field', name: {kind: 'Name', value: '__typename'}},
91+
],
92+
},
93+
},
94+
{kind: 'Field', name: {kind: 'Name', value: '__typename'}},
95+
],
96+
},
97+
},
98+
],
99+
},
100+
},
101+
],
102+
} as unknown as DocumentNode<BulkOperationCancelMutation, BulkOperationCancelMutationVariables>

packages/app/src/cli/api/graphql/bulk-operations/generated/types.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ export type BulkOperationsSortKeys =
210210
| 'COMPLETED_AT'
211211
/** Sort by the `created_at` value. */
212212
| 'CREATED_AT'
213+
/** Sort by the `status` value. */
214+
| 'STATUS'
213215

214216
/**
215217
* The possible HTTP methods that can be used when sending a request to upload a file using information from a
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
mutation BulkOperationCancel($id: ID!) {
2+
bulkOperationCancel(id: $id) {
3+
bulkOperation {
4+
completedAt
5+
createdAt
6+
errorCode
7+
fileSize
8+
id
9+
objectCount
10+
partialDataUrl
11+
query
12+
rootObjectCount
13+
status
14+
type
15+
url
16+
}
17+
userErrors {
18+
field
19+
message
20+
}
21+
}
22+
}
23+
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {appFlags} from '../../../flags.js'
2+
import AppLinkedCommand, {AppLinkedCommandOutput} from '../../../utilities/app-linked-command.js'
3+
import {prepareAppStoreContext} from '../../../utilities/execute-command-helpers.js'
4+
import {cancelBulkOperation} from '../../../services/bulk-operations/cancel-bulk-operation.js'
5+
import {Args, Flags} from '@oclif/core'
6+
import {globalFlags} from '@shopify/cli-kit/node/cli'
7+
import {normalizeStoreFqdn} from '@shopify/cli-kit/node/context/fqdn'
8+
9+
export default class BulkCancel extends AppLinkedCommand {
10+
static summary = 'Cancel a bulk operation.'
11+
12+
static description = 'Cancels a running bulk operation by ID.'
13+
14+
static hidden = true
15+
16+
static flags = {
17+
...globalFlags,
18+
...appFlags,
19+
id: Flags.string({
20+
description: 'The bulk operation ID to cancel (format: gid://shopify/BulkOperation/XXX).',
21+
env: 'SHOPIFY_FLAG_ID',
22+
}),
23+
store: Flags.string({
24+
char: 's',
25+
description: 'The store domain. Must be an existing dev store.',
26+
env: 'SHOPIFY_FLAG_STORE',
27+
parse: async (input) => normalizeStoreFqdn(input),
28+
}),
29+
}
30+
31+
static args = {
32+
id: Args.string({
33+
description: 'The bulk operation ID to cancel (format: gid://shopify/BulkOperation/XXX).',
34+
required: false,
35+
}),
36+
}
37+
38+
async run(): Promise<AppLinkedCommandOutput> {
39+
const {flags, args} = await this.parse(BulkCancel)
40+
41+
const operationId = flags.id ?? args.id
42+
if (!operationId) {
43+
this.error('Bulk operation ID is required. Provide it via --id flag or as a positional argument.')
44+
}
45+
46+
const {appContextResult, store} = await prepareAppStoreContext(flags)
47+
48+
await cancelBulkOperation({
49+
organization: appContextResult.organization,
50+
storeFqdn: store.shopDomain,
51+
operationId,
52+
remoteApp: appContextResult.remoteApp,
53+
})
54+
55+
return {app: appContextResult.app}
56+
}
57+
}
58+

packages/app/src/cli/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Build from './commands/app/build.js'
2+
import BulkCancel from './commands/app/bulk/cancel.js'
23
import BulkStatus from './commands/app/bulk/status.js'
34
import ConfigLink from './commands/app/config/link.js'
45
import ConfigUse from './commands/app/config/use.js'
@@ -39,6 +40,7 @@ import FunctionInfo from './commands/app/function/info.js'
3940
*/
4041
export const commands: {[key: string]: typeof AppLinkedCommand | typeof AppUnlinkedCommand} = {
4142
'app:build': Build,
43+
'app:bulk:cancel': BulkCancel,
4244
'app:bulk:status': BulkStatus,
4345
'app:deploy': Deploy,
4446
'app:dev': Dev,

0 commit comments

Comments
 (0)