@shopify/cli-kit 4.3.0 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.d.ts +28 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.js +74 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.d.ts +28 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.js +92 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.d.ts +26 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.js +72 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.d.ts +19 -0
- package/dist/cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js +49 -0
- package/dist/cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.d.ts +22 -0
- package/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.js +78 -0
- package/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.d.ts +22 -0
- package/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.js +82 -0
- package/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.js.map +1 -0
- package/dist/private/node/api/headers.js +1 -1
- package/dist/private/node/api/headers.js.map +1 -1
- package/dist/private/node/ui/components/Alert.test.js +5 -5
- package/dist/private/node/ui/components/Alert.test.js.map +1 -1
- package/dist/private/node/ui/components/Banner.js +9 -1
- package/dist/private/node/ui/components/Banner.js.map +1 -1
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/api/admin.d.ts +2 -1
- package/dist/public/node/api/admin.js +4 -3
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/bulk-operations/cancel.d.ts +15 -0
- package/dist/public/node/api/bulk-operations/cancel.js +20 -0
- package/dist/public/node/api/bulk-operations/cancel.js.map +1 -0
- package/dist/public/node/api/bulk-operations/constants.d.ts +5 -0
- package/dist/public/node/api/bulk-operations/constants.js +6 -0
- package/dist/public/node/api/bulk-operations/constants.js.map +1 -0
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.d.ts +17 -0
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js +48 -0
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js.map +1 -0
- package/dist/public/node/api/bulk-operations/fetch.d.ts +31 -0
- package/dist/public/node/api/bulk-operations/fetch.js +42 -0
- package/dist/public/node/api/bulk-operations/fetch.js.map +1 -0
- package/dist/public/node/api/bulk-operations/format-bulk-operation-status.d.ts +45 -0
- package/dist/public/node/api/bulk-operations/format-bulk-operation-status.js +91 -0
- package/dist/public/node/api/bulk-operations/format-bulk-operation-status.js.map +1 -0
- package/dist/public/node/api/bulk-operations/helpers.d.ts +51 -0
- package/dist/public/node/api/bulk-operations/helpers.js +110 -0
- package/dist/public/node/api/bulk-operations/helpers.js.map +1 -0
- package/dist/public/node/api/bulk-operations/query.d.ts +22 -0
- package/dist/public/node/api/bulk-operations/query.js +40 -0
- package/dist/public/node/api/bulk-operations/query.js.map +1 -0
- package/dist/public/node/api/bulk-operations/run-mutation.d.ts +16 -0
- package/dist/public/node/api/bulk-operations/run-mutation.js +27 -0
- package/dist/public/node/api/bulk-operations/run-mutation.js.map +1 -0
- package/dist/public/node/api/bulk-operations/run-query.d.ts +15 -0
- package/dist/public/node/api/bulk-operations/run-query.js +19 -0
- package/dist/public/node/api/bulk-operations/run-query.js.map +1 -0
- package/dist/public/node/api/bulk-operations/stage-file.d.ts +13 -0
- package/dist/public/node/api/bulk-operations/stage-file.js +89 -0
- package/dist/public/node/api/bulk-operations/stage-file.js.map +1 -0
- package/dist/public/node/api/bulk-operations/watch-bulk-operation.d.ts +26 -0
- package/dist/public/node/api/bulk-operations/watch-bulk-operation.js +131 -0
- package/dist/public/node/api/bulk-operations/watch-bulk-operation.js.map +1 -0
- package/dist/public/node/api/bulk-operations.d.ts +18 -0
- package/dist/public/node/api/bulk-operations.js +19 -0
- package/dist/public/node/api/bulk-operations.js.map +1 -0
- package/dist/public/node/constants.d.ts +1 -0
- package/dist/public/node/constants.js +2 -0
- package/dist/public/node/constants.js.map +1 -0
- package/dist/public/node/context/fqdn.js +45 -4
- package/dist/public/node/context/fqdn.js.map +1 -1
- package/dist/public/node/graphiql/session.d.ts +50 -0
- package/dist/public/node/graphiql/session.js +92 -0
- package/dist/public/node/graphiql/session.js.map +1 -0
- package/dist/public/node/graphiql/templates/graphiql.js +1 -4
- package/dist/public/node/graphiql/templates/graphiql.js.map +1 -1
- package/dist/public/node/store-auth-session.d.ts +113 -0
- package/dist/public/node/store-auth-session.js +257 -0
- package/dist/public/node/store-auth-session.js.map +1 -0
- package/dist/public/node/ui.d.ts +2 -6
- package/dist/public/node/ui.js +2 -6
- package/dist/public/node/ui.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BULK_OPERATIONS_MIN_API_VERSION } from './constants.js';
|
|
2
|
+
import { adminRequestDoc } from '../admin.js';
|
|
3
|
+
import { GetBulkOperationById, } from '../../../../cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js';
|
|
4
|
+
import { ListBulkOperations, } from '../../../../cli/api/graphql/bulk-operations/generated/list-bulk-operations.js';
|
|
5
|
+
/**
|
|
6
|
+
* Fetches a single bulk operation by ID.
|
|
7
|
+
*
|
|
8
|
+
* @param options - The admin session, operation ID, and optional API version.
|
|
9
|
+
* @returns The bulk operation, or null if it doesn't exist.
|
|
10
|
+
*/
|
|
11
|
+
export async function fetchBulkOperationById(options) {
|
|
12
|
+
const { adminSession, operationId, version } = options;
|
|
13
|
+
const response = await adminRequestDoc({
|
|
14
|
+
query: GetBulkOperationById,
|
|
15
|
+
session: adminSession,
|
|
16
|
+
variables: { id: operationId },
|
|
17
|
+
version: version ?? BULK_OPERATIONS_MIN_API_VERSION,
|
|
18
|
+
});
|
|
19
|
+
return response.bulkOperation;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Fetches recent bulk operations for the store.
|
|
23
|
+
*
|
|
24
|
+
* @param options - The admin session, optional API version, look-back window, and page size.
|
|
25
|
+
* @returns The list of bulk operation nodes, most recent first.
|
|
26
|
+
*/
|
|
27
|
+
export async function fetchRecentBulkOperations(options) {
|
|
28
|
+
const { adminSession, version, sinceDays = 7, first = 100 } = options;
|
|
29
|
+
const since = new Date(Date.now() - sinceDays * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
|
|
30
|
+
const response = await adminRequestDoc({
|
|
31
|
+
query: ListBulkOperations,
|
|
32
|
+
session: adminSession,
|
|
33
|
+
variables: {
|
|
34
|
+
query: `created_at:>=${since}`,
|
|
35
|
+
first,
|
|
36
|
+
sortKey: 'CREATED_AT',
|
|
37
|
+
},
|
|
38
|
+
version: version ?? BULK_OPERATIONS_MIN_API_VERSION,
|
|
39
|
+
});
|
|
40
|
+
return response.bulkOperations.nodes;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../../../../src/public/node/api/bulk-operations/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,+BAA+B,EAAC,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAE3C,OAAO,EACL,oBAAoB,GAErB,MAAM,mFAAmF,CAAA;AAC1F,OAAO,EACL,kBAAkB,GAGnB,MAAM,+EAA+E,CAAA;AAQtF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAAsC;IAEtC,MAAM,EAAC,YAAY,EAAE,WAAW,EAAE,OAAO,EAAC,GAAG,OAAO,CAAA;IAEpD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAA0C;QAC9E,KAAK,EAAE,oBAAoB;QAC3B,OAAO,EAAE,YAAY;QACrB,SAAS,EAAE,EAAC,EAAE,EAAE,WAAW,EAAC;QAC5B,OAAO,EAAE,OAAO,IAAI,+BAA+B;KACpD,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,aAAa,CAAA;AAC/B,CAAC;AAWD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,OAAyC;IAEzC,MAAM,EAAC,YAAY,EAAE,OAAO,EAAE,SAAS,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,EAAC,GAAG,OAAO,CAAA;IAEnE,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IAEhG,MAAM,QAAQ,GAAG,MAAM,eAAe,CAA4D;QAChG,KAAK,EAAE,kBAAkB;QACzB,OAAO,EAAE,YAAY;QACrB,SAAS,EAAE;YACT,KAAK,EAAE,gBAAgB,KAAK,EAAE;YAC9B,KAAK;YACL,OAAO,EAAE,YAAY;SACtB;QACD,OAAO,EAAE,OAAO,IAAI,+BAA+B;KACpD,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAA;AACtC,CAAC","sourcesContent":["import {BULK_OPERATIONS_MIN_API_VERSION} from './constants.js'\nimport {adminRequestDoc} from '../admin.js'\nimport {AdminSession} from '../../session.js'\nimport {\n GetBulkOperationById,\n GetBulkOperationByIdQuery,\n} from '../../../../cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js'\nimport {\n ListBulkOperations,\n ListBulkOperationsQuery,\n ListBulkOperationsQueryVariables,\n} from '../../../../cli/api/graphql/bulk-operations/generated/list-bulk-operations.js'\n\ninterface FetchBulkOperationByIdOptions {\n adminSession: AdminSession\n operationId: string\n version?: string\n}\n\n/**\n * Fetches a single bulk operation by ID.\n *\n * @param options - The admin session, operation ID, and optional API version.\n * @returns The bulk operation, or null if it doesn't exist.\n */\nexport async function fetchBulkOperationById(\n options: FetchBulkOperationByIdOptions,\n): Promise<GetBulkOperationByIdQuery['bulkOperation']> {\n const {adminSession, operationId, version} = options\n\n const response = await adminRequestDoc<GetBulkOperationByIdQuery, {id: string}>({\n query: GetBulkOperationById,\n session: adminSession,\n variables: {id: operationId},\n version: version ?? BULK_OPERATIONS_MIN_API_VERSION,\n })\n\n return response.bulkOperation\n}\n\ninterface FetchRecentBulkOperationsOptions {\n adminSession: AdminSession\n version?: string\n /** Number of days back to include. Defaults to 7. */\n sinceDays?: number\n /** Maximum number of operations to return. Defaults to 100. */\n first?: number\n}\n\n/**\n * Fetches recent bulk operations for the store.\n *\n * @param options - The admin session, optional API version, look-back window, and page size.\n * @returns The list of bulk operation nodes, most recent first.\n */\nexport async function fetchRecentBulkOperations(\n options: FetchRecentBulkOperationsOptions,\n): Promise<ListBulkOperationsQuery['bulkOperations']['nodes']> {\n const {adminSession, version, sinceDays = 7, first = 100} = options\n\n const since = new Date(Date.now() - sinceDays * 24 * 60 * 60 * 1000).toISOString().split('T')[0]\n\n const response = await adminRequestDoc<ListBulkOperationsQuery, ListBulkOperationsQueryVariables>({\n query: ListBulkOperations,\n session: adminSession,\n variables: {\n query: `created_at:>=${since}`,\n first,\n sortKey: 'CREATED_AT',\n },\n version: version ?? BULK_OPERATIONS_MIN_API_VERSION,\n })\n\n return response.bulkOperations.nodes\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { GetBulkOperationByIdQuery } from '../../../../cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js';
|
|
2
|
+
import { TokenizedString } from '../../output.js';
|
|
3
|
+
import { TokenItem } from '../../ui.js';
|
|
4
|
+
/**
|
|
5
|
+
* Produces a human-readable status line for a bulk operation.
|
|
6
|
+
*
|
|
7
|
+
* @param operation - The bulk operation.
|
|
8
|
+
* @returns A tokenized status string.
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatBulkOperationStatus(operation: NonNullable<GetBulkOperationByIdQuery['bulkOperation']>): TokenizedString;
|
|
11
|
+
interface UserError {
|
|
12
|
+
field?: string[] | null;
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Renders a list of bulk operation user errors.
|
|
17
|
+
*
|
|
18
|
+
* @param userErrors - The user errors to render.
|
|
19
|
+
* @param headline - The headline for the error block.
|
|
20
|
+
*/
|
|
21
|
+
export declare function renderBulkOperationUserErrors(userErrors: UserError[], headline: string): void;
|
|
22
|
+
export interface BulkOperationCancellationResult {
|
|
23
|
+
headline: string;
|
|
24
|
+
body?: TokenItem;
|
|
25
|
+
customSections?: {
|
|
26
|
+
body: {
|
|
27
|
+
list: {
|
|
28
|
+
items: string[];
|
|
29
|
+
};
|
|
30
|
+
}[];
|
|
31
|
+
}[];
|
|
32
|
+
renderType: 'success' | 'warning' | 'info';
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Classifies the outcome of a cancellation request into a renderable payload.
|
|
36
|
+
*
|
|
37
|
+
* The engine intentionally stays command-agnostic: for an in-progress cancellation it returns just
|
|
38
|
+
* the headline and render type, leaving each command to append its own "check status" hint (which
|
|
39
|
+
* references that command's own `bulk status` invocation).
|
|
40
|
+
*
|
|
41
|
+
* @param operation - The bulk operation after the cancel request.
|
|
42
|
+
* @returns The headline, body, sections, and render type to use.
|
|
43
|
+
*/
|
|
44
|
+
export declare function formatBulkOperationCancellationResult(operation: NonNullable<GetBulkOperationByIdQuery['bulkOperation']>): BulkOperationCancellationResult;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { outputContent, outputToken } from '../../output.js';
|
|
2
|
+
import { renderError } from '../../ui.js';
|
|
3
|
+
/**
|
|
4
|
+
* Produces a human-readable status line for a bulk operation.
|
|
5
|
+
*
|
|
6
|
+
* @param operation - The bulk operation.
|
|
7
|
+
* @returns A tokenized status string.
|
|
8
|
+
*/
|
|
9
|
+
export function formatBulkOperationStatus(operation) {
|
|
10
|
+
switch (operation.status) {
|
|
11
|
+
case 'RUNNING':
|
|
12
|
+
return outputContent `Bulk operation in progress${operation.objectCount > 0
|
|
13
|
+
? outputToken.gray(` (${String(operation.objectCount)} objects ${operation.type === 'MUTATION' ? 'written' : 'read'})`)
|
|
14
|
+
: ''}`;
|
|
15
|
+
case 'CREATED':
|
|
16
|
+
return outputContent `Starting`;
|
|
17
|
+
case 'COMPLETED':
|
|
18
|
+
return outputContent `Bulk operation succeeded: ${outputToken.gray(`${String(operation.objectCount)} objects`)}`;
|
|
19
|
+
case 'FAILED':
|
|
20
|
+
return outputContent `Bulk operation failed. ${outputToken.errorText(`Error: ${operation.errorCode ?? 'unknown'}`)}`;
|
|
21
|
+
case 'CANCELING':
|
|
22
|
+
return outputContent `Bulk operation canceling...`;
|
|
23
|
+
case 'CANCELED':
|
|
24
|
+
return outputContent `Bulk operation canceled.`;
|
|
25
|
+
case 'EXPIRED':
|
|
26
|
+
return outputContent `Bulk operation expired.`;
|
|
27
|
+
default:
|
|
28
|
+
return outputContent `Bulk operation status: ${operation.status}`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Renders a list of bulk operation user errors.
|
|
33
|
+
*
|
|
34
|
+
* @param userErrors - The user errors to render.
|
|
35
|
+
* @param headline - The headline for the error block.
|
|
36
|
+
*/
|
|
37
|
+
export function renderBulkOperationUserErrors(userErrors, headline) {
|
|
38
|
+
const errorMessages = userErrors
|
|
39
|
+
.map((error) => outputContent `${error.field?.join('.') ?? 'unknown'}: ${error.message}`.value)
|
|
40
|
+
.join('\n');
|
|
41
|
+
renderError({
|
|
42
|
+
headline,
|
|
43
|
+
body: errorMessages,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Classifies the outcome of a cancellation request into a renderable payload.
|
|
48
|
+
*
|
|
49
|
+
* The engine intentionally stays command-agnostic: for an in-progress cancellation it returns just
|
|
50
|
+
* the headline and render type, leaving each command to append its own "check status" hint (which
|
|
51
|
+
* references that command's own `bulk status` invocation).
|
|
52
|
+
*
|
|
53
|
+
* @param operation - The bulk operation after the cancel request.
|
|
54
|
+
* @returns The headline, body, sections, and render type to use.
|
|
55
|
+
*/
|
|
56
|
+
export function formatBulkOperationCancellationResult(operation) {
|
|
57
|
+
const headline = formatBulkOperationStatus(operation).value;
|
|
58
|
+
switch (operation.status) {
|
|
59
|
+
case 'CANCELING':
|
|
60
|
+
return {
|
|
61
|
+
headline: 'Bulk operation is being cancelled.',
|
|
62
|
+
renderType: 'success',
|
|
63
|
+
};
|
|
64
|
+
case 'CANCELED':
|
|
65
|
+
case 'COMPLETED':
|
|
66
|
+
case 'FAILED': {
|
|
67
|
+
const items = [
|
|
68
|
+
outputContent `ID: ${outputToken.cyan(operation.id)}`.value,
|
|
69
|
+
outputContent `Status: ${outputToken.yellow(operation.status)}`.value,
|
|
70
|
+
outputContent `Created at: ${outputToken.gray(String(operation.createdAt))}`.value,
|
|
71
|
+
...(operation.completedAt
|
|
72
|
+
? [outputContent `Completed at: ${outputToken.gray(String(operation.completedAt))}`.value]
|
|
73
|
+
: []),
|
|
74
|
+
];
|
|
75
|
+
return {
|
|
76
|
+
headline: outputContent `Bulk operation is already ${operation.status.toLowerCase()}.`.value,
|
|
77
|
+
body: outputContent `This operation has already finished and can't be canceled.`.value,
|
|
78
|
+
customSections: [{ body: [{ list: { items } }] }],
|
|
79
|
+
renderType: 'warning',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
case 'CREATED':
|
|
83
|
+
case 'EXPIRED':
|
|
84
|
+
case 'RUNNING':
|
|
85
|
+
return {
|
|
86
|
+
headline,
|
|
87
|
+
renderType: 'info',
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=format-bulk-operation-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-bulk-operation-status.js","sourceRoot":"","sources":["../../../../../src/public/node/api/bulk-operations/format-bulk-operation-status.ts"],"names":[],"mappings":"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","sourcesContent":["import {GetBulkOperationByIdQuery} from '../../../../cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js'\nimport {outputContent, outputToken, TokenizedString} from '../../output.js'\nimport {renderError, TokenItem} from '../../ui.js'\n\n/**\n * Produces a human-readable status line for a bulk operation.\n *\n * @param operation - The bulk operation.\n * @returns A tokenized status string.\n */\nexport function formatBulkOperationStatus(\n operation: NonNullable<GetBulkOperationByIdQuery['bulkOperation']>,\n): TokenizedString {\n switch (operation.status) {\n case 'RUNNING':\n return outputContent`Bulk operation in progress${\n (operation.objectCount as number) > 0\n ? outputToken.gray(\n ` (${String(operation.objectCount)} objects ${operation.type === 'MUTATION' ? 'written' : 'read'})`,\n )\n : ''\n }`\n case 'CREATED':\n return outputContent`Starting`\n case 'COMPLETED':\n return outputContent`Bulk operation succeeded: ${outputToken.gray(`${String(operation.objectCount)} objects`)}`\n case 'FAILED':\n return outputContent`Bulk operation failed. ${outputToken.errorText(\n `Error: ${operation.errorCode ?? 'unknown'}`,\n )}`\n case 'CANCELING':\n return outputContent`Bulk operation canceling...`\n case 'CANCELED':\n return outputContent`Bulk operation canceled.`\n case 'EXPIRED':\n return outputContent`Bulk operation expired.`\n default:\n return outputContent`Bulk operation status: ${operation.status}`\n }\n}\n\ninterface UserError {\n field?: string[] | null\n message: string\n}\n\n/**\n * Renders a list of bulk operation user errors.\n *\n * @param userErrors - The user errors to render.\n * @param headline - The headline for the error block.\n */\nexport function renderBulkOperationUserErrors(userErrors: UserError[], headline: string): void {\n const errorMessages = userErrors\n .map((error) => outputContent`${error.field?.join('.') ?? 'unknown'}: ${error.message}`.value)\n .join('\\n')\n\n renderError({\n headline,\n body: errorMessages,\n })\n}\n\nexport interface BulkOperationCancellationResult {\n headline: string\n body?: TokenItem\n customSections?: {body: {list: {items: string[]}}[]}[]\n renderType: 'success' | 'warning' | 'info'\n}\n\n/**\n * Classifies the outcome of a cancellation request into a renderable payload.\n *\n * The engine intentionally stays command-agnostic: for an in-progress cancellation it returns just\n * the headline and render type, leaving each command to append its own \"check status\" hint (which\n * references that command's own `bulk status` invocation).\n *\n * @param operation - The bulk operation after the cancel request.\n * @returns The headline, body, sections, and render type to use.\n */\nexport function formatBulkOperationCancellationResult(\n operation: NonNullable<GetBulkOperationByIdQuery['bulkOperation']>,\n): BulkOperationCancellationResult {\n const headline = formatBulkOperationStatus(operation).value\n\n switch (operation.status) {\n case 'CANCELING':\n return {\n headline: 'Bulk operation is being cancelled.',\n renderType: 'success',\n }\n case 'CANCELED':\n case 'COMPLETED':\n case 'FAILED': {\n const items = [\n outputContent`ID: ${outputToken.cyan(operation.id)}`.value,\n outputContent`Status: ${outputToken.yellow(operation.status)}`.value,\n outputContent`Created at: ${outputToken.gray(String(operation.createdAt))}`.value,\n ...(operation.completedAt\n ? [outputContent`Completed at: ${outputToken.gray(String(operation.completedAt))}`.value]\n : []),\n ]\n return {\n headline: outputContent`Bulk operation is already ${operation.status.toLowerCase()}.`.value,\n body: outputContent`This operation has already finished and can't be canceled.`.value,\n customSections: [{body: [{list: {items}}]}],\n renderType: 'warning',\n }\n }\n case 'CREATED':\n case 'EXPIRED':\n case 'RUNNING':\n return {\n headline,\n renderType: 'info',\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { AdminSession } from '../../session.js';
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes a bulk operation ID to a GID.
|
|
4
|
+
*
|
|
5
|
+
* @param id - A numeric ID or a full GID.
|
|
6
|
+
* @returns The GID form of the ID.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeBulkOperationId(id: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Extracts the numeric ID from a bulk operation GID.
|
|
11
|
+
*
|
|
12
|
+
* @param gid - A GID like "gid://shopify/BulkOperation/123".
|
|
13
|
+
* @returns The numeric ID, or the original string if it isn't a recognized GID.
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractBulkOperationId(gid: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Validates that a GraphQL document contains exactly one operation definition.
|
|
18
|
+
*
|
|
19
|
+
* @param graphqlOperation - The GraphQL query or mutation string to validate.
|
|
20
|
+
* @throws AbortError if the document doesn't contain exactly one operation or has syntax errors.
|
|
21
|
+
*/
|
|
22
|
+
export declare function validateSingleOperation(graphqlOperation: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Checks if a GraphQL operation is a mutation.
|
|
25
|
+
*
|
|
26
|
+
* @param graphqlOperation - The GraphQL query or mutation string to check.
|
|
27
|
+
* @returns True if the operation is a mutation, false otherwise.
|
|
28
|
+
* @throws AbortError if the operation has invalid GraphQL syntax.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isMutation(graphqlOperation: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Options for resolving an API version.
|
|
33
|
+
*/
|
|
34
|
+
interface ResolveApiVersionOptions {
|
|
35
|
+
/** Admin session containing store credentials. */
|
|
36
|
+
adminSession: AdminSession;
|
|
37
|
+
/** The API version specified by the user. */
|
|
38
|
+
userSpecifiedVersion?: string;
|
|
39
|
+
/** Optional minimum version to use as a fallback when no version is specified. */
|
|
40
|
+
minimumDefaultVersion?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Determines the API version to use based on the user provided version and the available versions.
|
|
44
|
+
* The 'unstable' version is always allowed without validation.
|
|
45
|
+
*
|
|
46
|
+
* @param options - Options for resolving the API version.
|
|
47
|
+
* @returns The resolved API version.
|
|
48
|
+
* @throws AbortError if the provided version is not allowed.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveApiVersion(options: ResolveApiVersionOptions): Promise<string>;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { fetchApiVersions } from '../admin.js';
|
|
2
|
+
import { AbortError } from '../../error.js';
|
|
3
|
+
import { outputContent } from '../../output.js';
|
|
4
|
+
import { parse } from 'graphql';
|
|
5
|
+
/**
|
|
6
|
+
* Normalizes a bulk operation ID to a GID.
|
|
7
|
+
*
|
|
8
|
+
* @param id - A numeric ID or a full GID.
|
|
9
|
+
* @returns The GID form of the ID.
|
|
10
|
+
*/
|
|
11
|
+
export function normalizeBulkOperationId(id) {
|
|
12
|
+
// If already a GID, return as-is
|
|
13
|
+
if (id.startsWith('gid://')) {
|
|
14
|
+
return id;
|
|
15
|
+
}
|
|
16
|
+
// If numeric, convert to GID
|
|
17
|
+
if (/^\d+$/.test(id)) {
|
|
18
|
+
return `gid://shopify/BulkOperation/${id}`;
|
|
19
|
+
}
|
|
20
|
+
// Otherwise return as-is (let API handle any errors)
|
|
21
|
+
return id;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Extracts the numeric ID from a bulk operation GID.
|
|
25
|
+
*
|
|
26
|
+
* @param gid - A GID like "gid://shopify/BulkOperation/123".
|
|
27
|
+
* @returns The numeric ID, or the original string if it isn't a recognized GID.
|
|
28
|
+
*/
|
|
29
|
+
export function extractBulkOperationId(gid) {
|
|
30
|
+
const match = gid.match(/^gid:\/\/shopify\/BulkOperation\/(\d+)$/);
|
|
31
|
+
return match?.[1] ?? gid;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validates that a GraphQL document contains exactly one operation definition.
|
|
35
|
+
*
|
|
36
|
+
* @param graphqlOperation - The GraphQL query or mutation string to validate.
|
|
37
|
+
* @throws AbortError if the document doesn't contain exactly one operation or has syntax errors.
|
|
38
|
+
*/
|
|
39
|
+
export function validateSingleOperation(graphqlOperation) {
|
|
40
|
+
let document;
|
|
41
|
+
try {
|
|
42
|
+
document = parse(graphqlOperation);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error instanceof Error) {
|
|
46
|
+
throw new AbortError(`Invalid GraphQL syntax: ${error.message}`);
|
|
47
|
+
}
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
const operationDefinitions = document.definitions.filter((def) => def.kind === 'OperationDefinition');
|
|
51
|
+
if (operationDefinitions.length !== 1) {
|
|
52
|
+
throw new AbortError('GraphQL document must contain exactly one operation definition. Multiple operations are not supported.');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Checks if a GraphQL operation is a mutation.
|
|
57
|
+
*
|
|
58
|
+
* @param graphqlOperation - The GraphQL query or mutation string to check.
|
|
59
|
+
* @returns True if the operation is a mutation, false otherwise.
|
|
60
|
+
* @throws AbortError if the operation has invalid GraphQL syntax.
|
|
61
|
+
*/
|
|
62
|
+
export function isMutation(graphqlOperation) {
|
|
63
|
+
let document;
|
|
64
|
+
try {
|
|
65
|
+
document = parse(graphqlOperation);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (error instanceof Error) {
|
|
69
|
+
throw new AbortError(`Invalid GraphQL syntax: ${error.message}`);
|
|
70
|
+
}
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
const operationDefinition = document.definitions.find((def) => def.kind === 'OperationDefinition');
|
|
74
|
+
return operationDefinition?.operation === 'mutation';
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Determines the API version to use based on the user provided version and the available versions.
|
|
78
|
+
* The 'unstable' version is always allowed without validation.
|
|
79
|
+
*
|
|
80
|
+
* @param options - Options for resolving the API version.
|
|
81
|
+
* @returns The resolved API version.
|
|
82
|
+
* @throws AbortError if the provided version is not allowed.
|
|
83
|
+
*/
|
|
84
|
+
export async function resolveApiVersion(options) {
|
|
85
|
+
const { adminSession, userSpecifiedVersion, minimumDefaultVersion } = options;
|
|
86
|
+
if (userSpecifiedVersion === 'unstable')
|
|
87
|
+
return userSpecifiedVersion;
|
|
88
|
+
const availableVersions = await fetchApiVersions(adminSession);
|
|
89
|
+
if (!userSpecifiedVersion) {
|
|
90
|
+
// Return the most recent supported version, or minimumDefaultVersion if specified, whichever is newer.
|
|
91
|
+
const supportedVersions = availableVersions.filter((version) => version.supported).map((version) => version.handle);
|
|
92
|
+
if (minimumDefaultVersion) {
|
|
93
|
+
supportedVersions.push(minimumDefaultVersion);
|
|
94
|
+
}
|
|
95
|
+
const latest = supportedVersions.sort().reverse()[0];
|
|
96
|
+
if (!latest) {
|
|
97
|
+
throw new AbortError('No supported API versions available for this store.');
|
|
98
|
+
}
|
|
99
|
+
return latest;
|
|
100
|
+
}
|
|
101
|
+
// Check if the user provided version is allowed. Unsupported versions (RC) are allowed here.
|
|
102
|
+
const versionList = availableVersions.map((version) => version.handle);
|
|
103
|
+
if (versionList.includes(userSpecifiedVersion))
|
|
104
|
+
return userSpecifiedVersion;
|
|
105
|
+
// Invalid user provided version.
|
|
106
|
+
const firstLine = outputContent `Invalid API version: ${userSpecifiedVersion}`.value;
|
|
107
|
+
const secondLine = outputContent `Allowed versions: ${versionList.join(', ')}`.value;
|
|
108
|
+
throw new AbortError(firstLine, secondLine);
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../../../src/public/node/api/bulk-operations/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,aAAa,CAAA;AAE5C,OAAO,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,KAAK,EAAC,MAAM,SAAS,CAAA;AAE7B;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,EAAU;IACjD,iCAAiC;IACjC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAA;IACX,CAAC;IAED,6BAA6B;IAC7B,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,OAAO,+BAA+B,EAAE,EAAE,CAAA;IAC5C,CAAC;IAED,qDAAqD;IACrD,OAAO,EAAE,CAAA;AACX,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAChD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAClE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAA;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,gBAAwB;IAC9D,IAAI,QAAQ,CAAA;IACZ,IAAI,CAAC;QACH,QAAQ,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAA;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,IAAI,UAAU,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAClE,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;IAED,MAAM,oBAAoB,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,qBAAqB,CAAC,CAAA;IAErG,IAAI,oBAAoB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,UAAU,CAClB,wGAAwG,CACzG,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,gBAAwB;IACjD,IAAI,QAAQ,CAAA;IACZ,IAAI,CAAC;QACH,QAAQ,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAA;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,IAAI,UAAU,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAClE,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;IAED,MAAM,mBAAmB,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,qBAAqB,CAAC,CAAA;IAElG,OAAO,mBAAmB,EAAE,SAAS,KAAK,UAAU,CAAA;AACtD,CAAC;AAcD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAiC;IACvE,MAAM,EAAC,YAAY,EAAE,oBAAoB,EAAE,qBAAqB,EAAC,GAAG,OAAO,CAAA;IAE3E,IAAI,oBAAoB,KAAK,UAAU;QAAE,OAAO,oBAAoB,CAAA;IAEpE,MAAM,iBAAiB,GAAG,MAAM,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAE9D,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,uGAAuG;QACvG,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACnH,IAAI,qBAAqB,EAAE,CAAC;YAC1B,iBAAiB,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;QAC/C,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;QACpD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,UAAU,CAAC,qDAAqD,CAAC,CAAA;QAC7E,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED,6FAA6F;IAC7F,MAAM,WAAW,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACtE,IAAI,WAAW,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAAE,OAAO,oBAAoB,CAAA;IAE3E,iCAAiC;IACjC,MAAM,SAAS,GAAG,aAAa,CAAA,wBAAwB,oBAAoB,EAAE,CAAC,KAAK,CAAA;IACnF,MAAM,UAAU,GAAG,aAAa,CAAA,qBAAqB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAA;IACnF,MAAM,IAAI,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;AAC7C,CAAC","sourcesContent":["import {fetchApiVersions} from '../admin.js'\nimport {AdminSession} from '../../session.js'\nimport {AbortError} from '../../error.js'\nimport {outputContent} from '../../output.js'\nimport {parse} from 'graphql'\n\n/**\n * Normalizes a bulk operation ID to a GID.\n *\n * @param id - A numeric ID or a full GID.\n * @returns The GID form of the ID.\n */\nexport function normalizeBulkOperationId(id: string): string {\n // If already a GID, return as-is\n if (id.startsWith('gid://')) {\n return id\n }\n\n // If numeric, convert to GID\n if (/^\\d+$/.test(id)) {\n return `gid://shopify/BulkOperation/${id}`\n }\n\n // Otherwise return as-is (let API handle any errors)\n return id\n}\n\n/**\n * Extracts the numeric ID from a bulk operation GID.\n *\n * @param gid - A GID like \"gid://shopify/BulkOperation/123\".\n * @returns The numeric ID, or the original string if it isn't a recognized GID.\n */\nexport function extractBulkOperationId(gid: string): string {\n const match = gid.match(/^gid:\\/\\/shopify\\/BulkOperation\\/(\\d+)$/)\n return match?.[1] ?? gid\n}\n\n/**\n * Validates that a GraphQL document contains exactly one operation definition.\n *\n * @param graphqlOperation - The GraphQL query or mutation string to validate.\n * @throws AbortError if the document doesn't contain exactly one operation or has syntax errors.\n */\nexport function validateSingleOperation(graphqlOperation: string): void {\n let document\n try {\n document = parse(graphqlOperation)\n } catch (error) {\n if (error instanceof Error) {\n throw new AbortError(`Invalid GraphQL syntax: ${error.message}`)\n }\n throw error\n }\n\n const operationDefinitions = document.definitions.filter((def) => def.kind === 'OperationDefinition')\n\n if (operationDefinitions.length !== 1) {\n throw new AbortError(\n 'GraphQL document must contain exactly one operation definition. Multiple operations are not supported.',\n )\n }\n}\n\n/**\n * Checks if a GraphQL operation is a mutation.\n *\n * @param graphqlOperation - The GraphQL query or mutation string to check.\n * @returns True if the operation is a mutation, false otherwise.\n * @throws AbortError if the operation has invalid GraphQL syntax.\n */\nexport function isMutation(graphqlOperation: string): boolean {\n let document\n try {\n document = parse(graphqlOperation)\n } catch (error) {\n if (error instanceof Error) {\n throw new AbortError(`Invalid GraphQL syntax: ${error.message}`)\n }\n throw error\n }\n\n const operationDefinition = document.definitions.find((def) => def.kind === 'OperationDefinition')\n\n return operationDefinition?.operation === 'mutation'\n}\n\n/**\n * Options for resolving an API version.\n */\ninterface ResolveApiVersionOptions {\n /** Admin session containing store credentials. */\n adminSession: AdminSession\n /** The API version specified by the user. */\n userSpecifiedVersion?: string\n /** Optional minimum version to use as a fallback when no version is specified. */\n minimumDefaultVersion?: string\n}\n\n/**\n * Determines the API version to use based on the user provided version and the available versions.\n * The 'unstable' version is always allowed without validation.\n *\n * @param options - Options for resolving the API version.\n * @returns The resolved API version.\n * @throws AbortError if the provided version is not allowed.\n */\nexport async function resolveApiVersion(options: ResolveApiVersionOptions): Promise<string> {\n const {adminSession, userSpecifiedVersion, minimumDefaultVersion} = options\n\n if (userSpecifiedVersion === 'unstable') return userSpecifiedVersion\n\n const availableVersions = await fetchApiVersions(adminSession)\n\n if (!userSpecifiedVersion) {\n // Return the most recent supported version, or minimumDefaultVersion if specified, whichever is newer.\n const supportedVersions = availableVersions.filter((version) => version.supported).map((version) => version.handle)\n if (minimumDefaultVersion) {\n supportedVersions.push(minimumDefaultVersion)\n }\n\n const latest = supportedVersions.sort().reverse()[0]\n if (!latest) {\n throw new AbortError('No supported API versions available for this store.')\n }\n return latest\n }\n\n // Check if the user provided version is allowed. Unsupported versions (RC) are allowed here.\n const versionList = availableVersions.map((version) => version.handle)\n if (versionList.includes(userSpecifiedVersion)) return userSpecifiedVersion\n\n // Invalid user provided version.\n const firstLine = outputContent`Invalid API version: ${userSpecifiedVersion}`.value\n const secondLine = outputContent`Allowed versions: ${versionList.join(', ')}`.value\n throw new AbortError(firstLine, secondLine)\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inputs for resolving a bulk operation's GraphQL query.
|
|
3
|
+
*/
|
|
4
|
+
interface ResolveBulkOperationQueryInput {
|
|
5
|
+
/** Inline GraphQL operation string. */
|
|
6
|
+
query?: string;
|
|
7
|
+
/** Path to a file containing the GraphQL operation. */
|
|
8
|
+
queryFile?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolves the GraphQL operation for a bulk command from either an inline `--query` value or a
|
|
12
|
+
* `--query-file` path, validating that it's non-empty and contains exactly one operation.
|
|
13
|
+
*
|
|
14
|
+
* Centralizes the read-and-validate logic shared by the app and store bulk execute commands.
|
|
15
|
+
*
|
|
16
|
+
* @param input - The inline query and/or the query file path (exactly one is expected).
|
|
17
|
+
* @returns The validated GraphQL operation string.
|
|
18
|
+
* @throws AbortError if the value/file is empty or missing, or the operation is invalid.
|
|
19
|
+
* @throws BugError if neither input was provided (oclif's exactlyOne constraint should prevent this).
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveBulkOperationQuery(input: ResolveBulkOperationQueryInput): Promise<string>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { validateSingleOperation } from './helpers.js';
|
|
2
|
+
import { AbortError, BugError } from '../../error.js';
|
|
3
|
+
import { fileExists, readFile } from '../../fs.js';
|
|
4
|
+
import { outputContent, outputToken } from '../../output.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the GraphQL operation for a bulk command from either an inline `--query` value or a
|
|
7
|
+
* `--query-file` path, validating that it's non-empty and contains exactly one operation.
|
|
8
|
+
*
|
|
9
|
+
* Centralizes the read-and-validate logic shared by the app and store bulk execute commands.
|
|
10
|
+
*
|
|
11
|
+
* @param input - The inline query and/or the query file path (exactly one is expected).
|
|
12
|
+
* @returns The validated GraphQL operation string.
|
|
13
|
+
* @throws AbortError if the value/file is empty or missing, or the operation is invalid.
|
|
14
|
+
* @throws BugError if neither input was provided (oclif's exactlyOne constraint should prevent this).
|
|
15
|
+
*/
|
|
16
|
+
export async function resolveBulkOperationQuery(input) {
|
|
17
|
+
let query;
|
|
18
|
+
if (input.query !== undefined) {
|
|
19
|
+
if (!input.query.trim()) {
|
|
20
|
+
throw new AbortError('The --query flag value is empty. Please provide a valid GraphQL query or mutation.');
|
|
21
|
+
}
|
|
22
|
+
query = input.query;
|
|
23
|
+
}
|
|
24
|
+
else if (input.queryFile) {
|
|
25
|
+
if (!(await fileExists(input.queryFile))) {
|
|
26
|
+
throw new AbortError(outputContent `Query file not found at ${outputToken.path(input.queryFile)}. Please check the path and try again.`);
|
|
27
|
+
}
|
|
28
|
+
const fileContents = await readFile(input.queryFile, { encoding: 'utf8' });
|
|
29
|
+
if (!fileContents.trim()) {
|
|
30
|
+
throw new AbortError(outputContent `Query file at ${outputToken.path(input.queryFile)} is empty. Please provide a valid GraphQL query or mutation.`);
|
|
31
|
+
}
|
|
32
|
+
query = fileContents;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw new BugError('Query should have been provided via --query or --query-file flags due to exactlyOne constraint. This indicates the oclif flag validation failed.');
|
|
36
|
+
}
|
|
37
|
+
validateSingleOperation(query);
|
|
38
|
+
return query;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../../../../src/public/node/api/bulk-operations/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,uBAAuB,EAAC,MAAM,cAAc,CAAA;AACpD,OAAO,EAAC,UAAU,EAAE,QAAQ,EAAC,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAC,UAAU,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAA;AAChD,OAAO,EAAC,aAAa,EAAE,WAAW,EAAC,MAAM,iBAAiB,CAAA;AAY1D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAAqC;IACnF,IAAI,KAAa,CAAA;IAEjB,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,UAAU,CAAC,oFAAoF,CAAC,CAAA;QAC5G,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;IACrB,CAAC;SAAM,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,UAAU,CAClB,aAAa,CAAA,2BAA2B,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,wCAAwC,CAClH,CAAA;QACH,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,EAAC,QAAQ,EAAE,MAAM,EAAC,CAAC,CAAA;QACxE,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,UAAU,CAClB,aAAa,CAAA,iBAAiB,WAAW,CAAC,IAAI,CAC5C,KAAK,CAAC,SAAS,CAChB,8DAA8D,CAChE,CAAA;QACH,CAAC;QACD,KAAK,GAAG,YAAY,CAAA;IACtB,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,QAAQ,CAChB,kJAAkJ,CACnJ,CAAA;IACH,CAAC;IAED,uBAAuB,CAAC,KAAK,CAAC,CAAA;IAE9B,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["import {validateSingleOperation} from './helpers.js'\nimport {AbortError, BugError} from '../../error.js'\nimport {fileExists, readFile} from '../../fs.js'\nimport {outputContent, outputToken} from '../../output.js'\n\n/**\n * Inputs for resolving a bulk operation's GraphQL query.\n */\ninterface ResolveBulkOperationQueryInput {\n /** Inline GraphQL operation string. */\n query?: string\n /** Path to a file containing the GraphQL operation. */\n queryFile?: string\n}\n\n/**\n * Resolves the GraphQL operation for a bulk command from either an inline `--query` value or a\n * `--query-file` path, validating that it's non-empty and contains exactly one operation.\n *\n * Centralizes the read-and-validate logic shared by the app and store bulk execute commands.\n *\n * @param input - The inline query and/or the query file path (exactly one is expected).\n * @returns The validated GraphQL operation string.\n * @throws AbortError if the value/file is empty or missing, or the operation is invalid.\n * @throws BugError if neither input was provided (oclif's exactlyOne constraint should prevent this).\n */\nexport async function resolveBulkOperationQuery(input: ResolveBulkOperationQueryInput): Promise<string> {\n let query: string\n\n if (input.query !== undefined) {\n if (!input.query.trim()) {\n throw new AbortError('The --query flag value is empty. Please provide a valid GraphQL query or mutation.')\n }\n query = input.query\n } else if (input.queryFile) {\n if (!(await fileExists(input.queryFile))) {\n throw new AbortError(\n outputContent`Query file not found at ${outputToken.path(input.queryFile)}. Please check the path and try again.`,\n )\n }\n const fileContents = await readFile(input.queryFile, {encoding: 'utf8'})\n if (!fileContents.trim()) {\n throw new AbortError(\n outputContent`Query file at ${outputToken.path(\n input.queryFile,\n )} is empty. Please provide a valid GraphQL query or mutation.`,\n )\n }\n query = fileContents\n } else {\n throw new BugError(\n 'Query should have been provided via --query or --query-file flags due to exactlyOne constraint. This indicates the oclif flag validation failed.',\n )\n }\n\n validateSingleOperation(query)\n\n return query\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BulkOperationRunMutationMutation } from '../../../../cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.js';
|
|
2
|
+
import { AdminSession } from '../../session.js';
|
|
3
|
+
interface BulkOperationRunMutationOptions {
|
|
4
|
+
adminSession: AdminSession;
|
|
5
|
+
query: string;
|
|
6
|
+
variablesJsonl?: string;
|
|
7
|
+
version?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Stages a JSONL variables file then starts a bulk mutation operation on the store.
|
|
11
|
+
*
|
|
12
|
+
* @param options - The admin session, mutation, JSONL variables, and optional API version.
|
|
13
|
+
* @returns The bulkOperationRunMutation result, including the created operation and any user errors.
|
|
14
|
+
*/
|
|
15
|
+
export declare function runBulkOperationMutation(options: BulkOperationRunMutationOptions): Promise<BulkOperationRunMutationMutation['bulkOperationRunMutation']>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { stageFile } from './stage-file.js';
|
|
2
|
+
import { BulkOperationRunMutation as BulkOperationRunMutationDoc, } from '../../../../cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.js';
|
|
3
|
+
import { adminRequestDoc } from '../admin.js';
|
|
4
|
+
/**
|
|
5
|
+
* Stages a JSONL variables file then starts a bulk mutation operation on the store.
|
|
6
|
+
*
|
|
7
|
+
* @param options - The admin session, mutation, JSONL variables, and optional API version.
|
|
8
|
+
* @returns The bulkOperationRunMutation result, including the created operation and any user errors.
|
|
9
|
+
*/
|
|
10
|
+
export async function runBulkOperationMutation(options) {
|
|
11
|
+
const { adminSession, query: mutation, variablesJsonl, version } = options;
|
|
12
|
+
const stagedUploadPath = await stageFile({
|
|
13
|
+
adminSession,
|
|
14
|
+
variablesJsonl,
|
|
15
|
+
});
|
|
16
|
+
const response = await adminRequestDoc({
|
|
17
|
+
query: BulkOperationRunMutationDoc,
|
|
18
|
+
session: adminSession,
|
|
19
|
+
variables: {
|
|
20
|
+
mutation,
|
|
21
|
+
stagedUploadPath,
|
|
22
|
+
},
|
|
23
|
+
...(version && { version }),
|
|
24
|
+
});
|
|
25
|
+
return response.bulkOperationRunMutation;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=run-mutation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-mutation.js","sourceRoot":"","sources":["../../../../../src/public/node/api/bulk-operations/run-mutation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAA;AACzC,OAAO,EACL,wBAAwB,IAAI,2BAA2B,GAGxD,MAAM,sFAAsF,CAAA;AAC7F,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAU3C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAwC;IAExC,MAAM,EAAC,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAC,GAAG,OAAO,CAAA;IAExE,MAAM,gBAAgB,GAAG,MAAM,SAAS,CAAC;QACvC,YAAY;QACZ,cAAc;KACf,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAG,MAAM,eAAe,CAA8E;QAClH,KAAK,EAAE,2BAA2B;QAClC,OAAO,EAAE,YAAY;QACrB,SAAS,EAAE;YACT,QAAQ;YACR,gBAAgB;SACjB;QACD,GAAG,CAAC,OAAO,IAAI,EAAC,OAAO,EAAC,CAAC;KAC1B,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,wBAAwB,CAAA;AAC1C,CAAC","sourcesContent":["import {stageFile} from './stage-file.js'\nimport {\n BulkOperationRunMutation as BulkOperationRunMutationDoc,\n BulkOperationRunMutationMutation,\n BulkOperationRunMutationMutationVariables,\n} from '../../../../cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.js'\nimport {adminRequestDoc} from '../admin.js'\nimport {AdminSession} from '../../session.js'\n\ninterface BulkOperationRunMutationOptions {\n adminSession: AdminSession\n query: string\n variablesJsonl?: string\n version?: string\n}\n\n/**\n * Stages a JSONL variables file then starts a bulk mutation operation on the store.\n *\n * @param options - The admin session, mutation, JSONL variables, and optional API version.\n * @returns The bulkOperationRunMutation result, including the created operation and any user errors.\n */\nexport async function runBulkOperationMutation(\n options: BulkOperationRunMutationOptions,\n): Promise<BulkOperationRunMutationMutation['bulkOperationRunMutation']> {\n const {adminSession, query: mutation, variablesJsonl, version} = options\n\n const stagedUploadPath = await stageFile({\n adminSession,\n variablesJsonl,\n })\n\n const response = await adminRequestDoc<BulkOperationRunMutationMutation, BulkOperationRunMutationMutationVariables>({\n query: BulkOperationRunMutationDoc,\n session: adminSession,\n variables: {\n mutation,\n stagedUploadPath,\n },\n ...(version && {version}),\n })\n\n return response.bulkOperationRunMutation\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BulkOperationRunQueryMutation } from '../../../../cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.js';
|
|
2
|
+
import { AdminSession } from '../../session.js';
|
|
3
|
+
interface BulkOperationRunQueryOptions {
|
|
4
|
+
adminSession: AdminSession;
|
|
5
|
+
query: string;
|
|
6
|
+
version?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Starts a bulk query operation on the store.
|
|
10
|
+
*
|
|
11
|
+
* @param options - The admin session, query, and optional API version.
|
|
12
|
+
* @returns The bulkOperationRunQuery result, including the created operation and any user errors.
|
|
13
|
+
*/
|
|
14
|
+
export declare function runBulkOperationQuery(options: BulkOperationRunQueryOptions): Promise<BulkOperationRunQueryMutation['bulkOperationRunQuery']>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BulkOperationRunQuery, } from '../../../../cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.js';
|
|
2
|
+
import { adminRequestDoc } from '../admin.js';
|
|
3
|
+
/**
|
|
4
|
+
* Starts a bulk query operation on the store.
|
|
5
|
+
*
|
|
6
|
+
* @param options - The admin session, query, and optional API version.
|
|
7
|
+
* @returns The bulkOperationRunQuery result, including the created operation and any user errors.
|
|
8
|
+
*/
|
|
9
|
+
export async function runBulkOperationQuery(options) {
|
|
10
|
+
const { adminSession, query, version } = options;
|
|
11
|
+
const response = await adminRequestDoc({
|
|
12
|
+
query: BulkOperationRunQuery,
|
|
13
|
+
session: adminSession,
|
|
14
|
+
variables: { query },
|
|
15
|
+
...(version && { version }),
|
|
16
|
+
});
|
|
17
|
+
return response.bulkOperationRunQuery;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=run-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-query.js","sourceRoot":"","sources":["../../../../../src/public/node/api/bulk-operations/run-query.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAEtB,MAAM,mFAAmF,CAAA;AAC1F,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAS3C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAqC;IAErC,MAAM,EAAC,YAAY,EAAE,KAAK,EAAE,OAAO,EAAC,GAAG,OAAO,CAAA;IAE9C,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAiD;QACrF,KAAK,EAAE,qBAAqB;QAC5B,OAAO,EAAE,YAAY;QACrB,SAAS,EAAE,EAAC,KAAK,EAAC;QAClB,GAAG,CAAC,OAAO,IAAI,EAAC,OAAO,EAAC,CAAC;KAC1B,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,qBAAqB,CAAA;AACvC,CAAC","sourcesContent":["import {\n BulkOperationRunQuery,\n BulkOperationRunQueryMutation,\n} from '../../../../cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.js'\nimport {adminRequestDoc} from '../admin.js'\nimport {AdminSession} from '../../session.js'\n\ninterface BulkOperationRunQueryOptions {\n adminSession: AdminSession\n query: string\n version?: string\n}\n\n/**\n * Starts a bulk query operation on the store.\n *\n * @param options - The admin session, query, and optional API version.\n * @returns The bulkOperationRunQuery result, including the created operation and any user errors.\n */\nexport async function runBulkOperationQuery(\n options: BulkOperationRunQueryOptions,\n): Promise<BulkOperationRunQueryMutation['bulkOperationRunQuery']> {\n const {adminSession, query, version} = options\n\n const response = await adminRequestDoc<BulkOperationRunQueryMutation, {query: string}>({\n query: BulkOperationRunQuery,\n session: adminSession,\n variables: {query},\n ...(version && {version}),\n })\n\n return response.bulkOperationRunQuery\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AdminSession } from '../../session.js';
|
|
2
|
+
interface StageFileOptions {
|
|
3
|
+
adminSession: AdminSession;
|
|
4
|
+
variablesJsonl?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Uploads bulk mutation variables to a staged upload target and returns the staged upload key.
|
|
8
|
+
*
|
|
9
|
+
* @param options - The admin session and JSONL variables.
|
|
10
|
+
* @returns The staged upload key used as `stagedUploadPath` for the bulk mutation.
|
|
11
|
+
*/
|
|
12
|
+
export declare function stageFile(options: StageFileOptions): Promise<string>;
|
|
13
|
+
export {};
|