Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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/pretty-brooms-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/app': minor
---

Added `shopify app execute` for convenient execution of queries and mutations against the Admin API.
34 changes: 34 additions & 0 deletions docs-shopify.dev/commands/app-execute.doc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// This is an autogenerated file. Don't edit this file manually.
import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs'

const data: ReferenceEntityTemplateSchema = {
name: 'app execute',
description: `Executes an Admin API GraphQL query or mutation on the specified dev store.`,
overviewPreviewDescription: `Execute GraphQL queries and mutations.`,
type: 'command',
isVisualComponent: false,
defaultExample: {
codeblock: {
tabs: [
{
title: 'app execute',
code: './examples/app-execute.example.sh',
language: 'bash',
},
],
title: 'app execute',
},
},
definitions: [
{
title: 'Flags',
description: 'The following flags are available for the `app execute` command:',
type: 'appexecute',
},
],
category: 'app',
related: [
],
}

export default data
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
shopify app execute [flags]
68 changes: 68 additions & 0 deletions docs-shopify.dev/commands/interfaces/app-execute.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// This is an autogenerated file. Don't edit this file manually.
export interface appexecute {
/**
* The Client ID of your app.
* @environment SHOPIFY_FLAG_CLIENT_ID
*/
'--client-id <value>'?: string

/**
* The name of the app configuration.
* @environment SHOPIFY_FLAG_APP_CONFIG
*/
'-c, --config <value>'?: string

/**
* Disable color output.
* @environment SHOPIFY_FLAG_NO_COLOR
*/
'--no-color'?: ''

/**
* The file name where results should be written, instead of STDOUT.
* @environment SHOPIFY_FLAG_OUTPUT_FILE
*/
'--output-file <value>'?: string

/**
* The path to your app directory.
* @environment SHOPIFY_FLAG_PATH
*/
'--path <value>'?: string

/**
* The GraphQL query or mutation, as a string.
* @environment SHOPIFY_FLAG_QUERY
*/
'-q, --query <value>'?: string

/**
* Reset all your settings.
* @environment SHOPIFY_FLAG_RESET
*/
'--reset'?: ''

/**
* The myshopify.com domain of the store to execute against. The app must be installed on the store. If not specified, you will be prompted to select a store.
* @environment SHOPIFY_FLAG_STORE
*/
'-s, --store <value>'?: string

/**
* The values for any GraphQL variables in your query or mutation, in JSON format.
* @environment SHOPIFY_FLAG_VARIABLES
*/
'-v, --variables <value>'?: string

/**
* Increase the verbosity of the output.
* @environment SHOPIFY_FLAG_VERBOSE
*/
'--verbose'?: ''

/**
* The API version to use for the query or mutation. Defaults to the latest stable version.
* @environment SHOPIFY_FLAG_VERSION
*/
'--version <value>'?: string
}
137 changes: 137 additions & 0 deletions docs-shopify.dev/generated/generated_docs_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,143 @@
"category": "app",
"related": []
},
{
"name": "app execute",
"description": "Executes an Admin API GraphQL query or mutation on the specified dev store.",
"overviewPreviewDescription": "Execute GraphQL queries and mutations.",
"type": "command",
"isVisualComponent": false,
"defaultExample": {
"codeblock": {
"tabs": [
{
"title": "app execute",
"code": "shopify app execute [flags]",
"language": "bash"
}
],
"title": "app execute"
}
},
"definitions": [
{
"title": "Flags",
"description": "The following flags are available for the `app execute` command:",
"type": "appexecute",
"typeDefinitions": {
"appexecute": {
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"name": "appexecute",
"description": "",
"members": [
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "--client-id <value>",
"value": "string",
"description": "The Client ID of your app.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_CLIENT_ID"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "--no-color",
"value": "\"\"",
"description": "Disable color output.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_NO_COLOR"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "--output-file <value>",
"value": "string",
"description": "The file name where results should be written, instead of STDOUT.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_OUTPUT_FILE"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "--path <value>",
"value": "string",
"description": "The path to your app directory.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_PATH"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "--reset",
"value": "\"\"",
"description": "Reset all your settings.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_RESET"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "--verbose",
"value": "\"\"",
"description": "Increase the verbosity of the output.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_VERBOSE"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "--version <value>",
"value": "string",
"description": "The API version to use for the query or mutation. Defaults to the latest stable version.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_VERSION"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "-c, --config <value>",
"value": "string",
"description": "The name of the app configuration.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_APP_CONFIG"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "-q, --query <value>",
"value": "string",
"description": "The GraphQL query or mutation, as a string.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_QUERY"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "-s, --store <value>",
"value": "string",
"description": "The myshopify.com domain of the store to execute against. The app must be installed on the store. If not specified, you will be prompted to select a store.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_STORE"
},
{
"filePath": "docs-shopify.dev/commands/interfaces/app-execute.interface.ts",
"syntaxKind": "PropertySignature",
"name": "-v, --variables <value>",
"value": "string",
"description": "The values for any GraphQL variables in your query or mutation, in JSON format.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_VARIABLES"
}
],
"value": "export interface appexecute {\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id <value>'?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config <value>'?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The file name where results should be written, instead of STDOUT.\n * @environment SHOPIFY_FLAG_OUTPUT_FILE\n */\n '--output-file <value>'?: string\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path <value>'?: string\n\n /**\n * The GraphQL query or mutation, as a string.\n * @environment SHOPIFY_FLAG_QUERY\n */\n '-q, --query <value>'?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * The myshopify.com domain of the store to execute against. The app must be installed on the store. If not specified, you will be prompted to select a store.\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store <value>'?: string\n\n /**\n * The values for any GraphQL variables in your query or mutation, in JSON format.\n * @environment SHOPIFY_FLAG_VARIABLES\n */\n '-v, --variables <value>'?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n\n /**\n * The API version to use for the query or mutation. Defaults to the latest stable version.\n * @environment SHOPIFY_FLAG_VERSION\n */\n '--version <value>'?: string\n}"
}
}
}
],
"category": "app",
"related": []
},
{
"name": "app function build",
"description": "Compiles the function in your current directory to WebAssembly (Wasm) for testing purposes.",
Expand Down
29 changes: 4 additions & 25 deletions packages/app/src/cli/commands/app/bulk/execute.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import {appFlags, bulkOperationFlags} from '../../../flags.js'
import AppLinkedCommand, {AppLinkedCommandOutput} from '../../../utilities/app-linked-command.js'
import {linkedAppContext} from '../../../services/app-context.js'
import {storeContext} from '../../../services/store-context.js'
import {executeBulkOperation} from '../../../services/bulk-operations/execute-bulk-operation.js'
import {prepareExecuteContext} from '../../../utilities/execute-command-helpers.js'
import {globalFlags} from '@shopify/cli-kit/node/cli'
import {readStdinString} from '@shopify/cli-kit/node/system'
import {AbortError} from '@shopify/cli-kit/node/error'

export default class BulkExecute extends AppLinkedCommand {
static summary = 'Execute bulk operations.'

static description = 'Execute bulk operations against the Shopify Admin API.'
static description =
'Executes an Admin API GraphQL query or mutation on the specified dev store, as a bulk operation.'

static hidden = true

Expand All @@ -23,26 +21,7 @@ export default class BulkExecute extends AppLinkedCommand {
async run(): Promise<AppLinkedCommandOutput> {
const {flags} = await this.parse(BulkExecute)

const query = flags.query ?? (await readStdinString())
if (!query) {
throw new AbortError(
'No query provided. Use the --query flag or pipe input via stdin.',
'Example: echo "query { ... }" | shopify app bulk execute',
)
}

const appContextResult = await linkedAppContext({
directory: flags.path,
clientId: flags['client-id'],
forceRelink: flags.reset,
userProvidedConfigName: flags.config,
})

const store = await storeContext({
appContextResult,
storeFqdn: flags.store,
forceReselectStore: flags.reset,
})
const {query, appContextResult, store} = await prepareExecuteContext(flags, 'bulk execute')

await executeBulkOperation({
remoteApp: appContextResult.remoteApp,
Expand Down
16 changes: 2 additions & 14 deletions packages/app/src/cli/commands/app/bulk/status.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {appFlags} from '../../../flags.js'
import AppLinkedCommand, {AppLinkedCommandOutput} from '../../../utilities/app-linked-command.js'
import {linkedAppContext} from '../../../services/app-context.js'
import {storeContext} from '../../../services/store-context.js'
import {prepareAppStoreContext} from '../../../utilities/execute-command-helpers.js'
import {getBulkOperationStatus, listBulkOperations} from '../../../services/bulk-operations/bulk-operation-status.js'
import {Flags} from '@oclif/core'
import {globalFlags} from '@shopify/cli-kit/node/cli'
Expand Down Expand Up @@ -33,18 +32,7 @@ export default class BulkStatus extends AppLinkedCommand {
async run(): Promise<AppLinkedCommandOutput> {
const {flags} = await this.parse(BulkStatus)

const appContextResult = await linkedAppContext({
directory: flags.path,
clientId: flags['client-id'],
forceRelink: flags.reset,
userProvidedConfigName: flags.config,
})

const store = await storeContext({
appContextResult,
storeFqdn: flags.store,
forceReselectStore: flags.reset,
})
const {appContextResult, store} = await prepareAppStoreContext(flags)

if (flags.id) {
await getBulkOperationStatus({
Expand Down
34 changes: 34 additions & 0 deletions packages/app/src/cli/commands/app/execute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {appFlags, operationFlags} from '../../flags.js'
import AppLinkedCommand, {AppLinkedCommandOutput} from '../../utilities/app-linked-command.js'
import {executeOperation} from '../../services/execute-operation.js'
import {prepareExecuteContext} from '../../utilities/execute-command-helpers.js'
import {globalFlags} from '@shopify/cli-kit/node/cli'

export default class Execute extends AppLinkedCommand {
static summary = 'Execute GraphQL queries and mutations.'

static description = 'Executes an Admin API GraphQL query or mutation on the specified dev store.'

static flags = {
...globalFlags,
...appFlags,
...operationFlags,
}

async run(): Promise<AppLinkedCommandOutput> {
const {flags} = await this.parse(Execute)

const {query, appContextResult, store} = await prepareExecuteContext(flags, 'execute')

await executeOperation({
remoteApp: appContextResult.remoteApp,
storeFqdn: store.shopDomain,
query,
variables: flags.variables,
outputFile: flags['output-file'],
...(flags.version && {version: flags.version}),
})

return {app: appContextResult.app}
}
}
Loading