Skip to content

Commit 929ecb4

Browse files
Merge pull request #6541 from Shopify/sd.function-runner-direct-invocation
Adding function runner info command
2 parents 1565cbc + 20372b4 commit 929ecb4

File tree

10 files changed

+459
-0
lines changed

10 files changed

+459
-0
lines changed

.changeset/hungry-ravens-sip.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/app': minor
3+
---
4+
5+
Added a `function info` command to display function information.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// This is an autogenerated file. Don't edit this file manually.
2+
import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs'
3+
4+
const data: ReferenceEntityTemplateSchema = {
5+
name: 'app function info',
6+
description: `The information returned includes the following:
7+
8+
- The function handle
9+
- The function name
10+
- The function API version
11+
- The targeting configuration
12+
- The schema path
13+
- The WASM path
14+
- The function runner path`,
15+
overviewPreviewDescription: `Print basic information about your function.`,
16+
type: 'command',
17+
isVisualComponent: false,
18+
defaultExample: {
19+
codeblock: {
20+
tabs: [
21+
{
22+
title: 'app function info',
23+
code: './examples/app-function-info.example.sh',
24+
language: 'bash',
25+
},
26+
],
27+
title: 'app function info',
28+
},
29+
},
30+
definitions: [
31+
{
32+
title: 'Flags',
33+
description: 'The following flags are available for the `app function info` command:',
34+
type: 'appfunctioninfo',
35+
},
36+
],
37+
category: 'app',
38+
related: [
39+
],
40+
}
41+
42+
export default data
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
shopify app function info [flags]
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// This is an autogenerated file. Don't edit this file manually.
2+
export interface appfunctioninfo {
3+
/**
4+
* The Client ID of your app.
5+
* @environment SHOPIFY_FLAG_CLIENT_ID
6+
*/
7+
'--client-id <value>'?: string
8+
9+
/**
10+
* The name of the app configuration.
11+
* @environment SHOPIFY_FLAG_APP_CONFIG
12+
*/
13+
'-c, --config <value>'?: string
14+
15+
/**
16+
* Output the result as JSON.
17+
* @environment SHOPIFY_FLAG_JSON
18+
*/
19+
'-j, --json'?: ''
20+
21+
/**
22+
* Disable color output.
23+
* @environment SHOPIFY_FLAG_NO_COLOR
24+
*/
25+
'--no-color'?: ''
26+
27+
/**
28+
* The path to your function directory.
29+
* @environment SHOPIFY_FLAG_PATH
30+
*/
31+
'--path <value>'?: string
32+
33+
/**
34+
* Reset all your settings.
35+
* @environment SHOPIFY_FLAG_RESET
36+
*/
37+
'--reset'?: ''
38+
39+
/**
40+
* Increase the verbosity of the output.
41+
* @environment SHOPIFY_FLAG_VERBOSE
42+
*/
43+
'--verbose'?: ''
44+
}

docs-shopify.dev/generated/generated_docs_data.json

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,107 @@
998998
"category": "app",
999999
"related": []
10001000
},
1001+
{
1002+
"name": "app function info",
1003+
"description": "The information returned includes the following:\n\n - The function handle\n - The function name\n - The function API version\n - The targeting configuration\n - The schema path\n - The WASM path\n - The function runner path",
1004+
"overviewPreviewDescription": "Print basic information about your function.",
1005+
"type": "command",
1006+
"isVisualComponent": false,
1007+
"defaultExample": {
1008+
"codeblock": {
1009+
"tabs": [
1010+
{
1011+
"title": "app function info",
1012+
"code": "shopify app function info [flags]",
1013+
"language": "bash"
1014+
}
1015+
],
1016+
"title": "app function info"
1017+
}
1018+
},
1019+
"definitions": [
1020+
{
1021+
"title": "Flags",
1022+
"description": "The following flags are available for the `app function info` command:",
1023+
"type": "appfunctioninfo",
1024+
"typeDefinitions": {
1025+
"appfunctioninfo": {
1026+
"filePath": "docs-shopify.dev/commands/interfaces/app-function-info.interface.ts",
1027+
"name": "appfunctioninfo",
1028+
"description": "",
1029+
"members": [
1030+
{
1031+
"filePath": "docs-shopify.dev/commands/interfaces/app-function-info.interface.ts",
1032+
"syntaxKind": "PropertySignature",
1033+
"name": "--client-id <value>",
1034+
"value": "string",
1035+
"description": "The Client ID of your app.",
1036+
"isOptional": true,
1037+
"environmentValue": "SHOPIFY_FLAG_CLIENT_ID"
1038+
},
1039+
{
1040+
"filePath": "docs-shopify.dev/commands/interfaces/app-function-info.interface.ts",
1041+
"syntaxKind": "PropertySignature",
1042+
"name": "--no-color",
1043+
"value": "\"\"",
1044+
"description": "Disable color output.",
1045+
"isOptional": true,
1046+
"environmentValue": "SHOPIFY_FLAG_NO_COLOR"
1047+
},
1048+
{
1049+
"filePath": "docs-shopify.dev/commands/interfaces/app-function-info.interface.ts",
1050+
"syntaxKind": "PropertySignature",
1051+
"name": "--path <value>",
1052+
"value": "string",
1053+
"description": "The path to your function directory.",
1054+
"isOptional": true,
1055+
"environmentValue": "SHOPIFY_FLAG_PATH"
1056+
},
1057+
{
1058+
"filePath": "docs-shopify.dev/commands/interfaces/app-function-info.interface.ts",
1059+
"syntaxKind": "PropertySignature",
1060+
"name": "--reset",
1061+
"value": "\"\"",
1062+
"description": "Reset all your settings.",
1063+
"isOptional": true,
1064+
"environmentValue": "SHOPIFY_FLAG_RESET"
1065+
},
1066+
{
1067+
"filePath": "docs-shopify.dev/commands/interfaces/app-function-info.interface.ts",
1068+
"syntaxKind": "PropertySignature",
1069+
"name": "--verbose",
1070+
"value": "\"\"",
1071+
"description": "Increase the verbosity of the output.",
1072+
"isOptional": true,
1073+
"environmentValue": "SHOPIFY_FLAG_VERBOSE"
1074+
},
1075+
{
1076+
"filePath": "docs-shopify.dev/commands/interfaces/app-function-info.interface.ts",
1077+
"syntaxKind": "PropertySignature",
1078+
"name": "-c, --config <value>",
1079+
"value": "string",
1080+
"description": "The name of the app configuration.",
1081+
"isOptional": true,
1082+
"environmentValue": "SHOPIFY_FLAG_APP_CONFIG"
1083+
},
1084+
{
1085+
"filePath": "docs-shopify.dev/commands/interfaces/app-function-info.interface.ts",
1086+
"syntaxKind": "PropertySignature",
1087+
"name": "-j, --json",
1088+
"value": "\"\"",
1089+
"description": "Output the result as JSON.",
1090+
"isOptional": true,
1091+
"environmentValue": "SHOPIFY_FLAG_JSON"
1092+
}
1093+
],
1094+
"value": "export interface appfunctioninfo {\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 * Output the result as JSON.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your function directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path <value>'?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}"
1095+
}
1096+
}
1097+
}
1098+
],
1099+
"category": "app",
1100+
"related": []
1101+
},
10011102
{
10021103
"name": "app function replay",
10031104
"description": "Runs the function from your current directory for [testing purposes](/docs/apps/functions/testing-and-debugging). To learn how you can monitor and debug functions when errors occur, refer to [Shopify Functions error handling](/docs/api/functions/errors).",
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import {chooseFunction, functionFlags, getOrGenerateSchemaPath} from '../../../services/function/common.js'
2+
import {functionRunnerBinary, downloadBinary} from '../../../services/function/binaries.js'
3+
import {localAppContext} from '../../../services/app-context.js'
4+
import {appFlags} from '../../../flags.js'
5+
import AppUnlinkedCommand, {AppUnlinkedCommandOutput} from '../../../utilities/app-unlinked-command.js'
6+
import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli'
7+
import {outputContent, outputResult, outputToken} from '@shopify/cli-kit/node/output'
8+
import {InlineToken, renderInfo} from '@shopify/cli-kit/node/ui'
9+
10+
export default class FunctionInfo extends AppUnlinkedCommand {
11+
static summary = 'Print basic information about your function.'
12+
13+
static descriptionWithMarkdown = `The information returned includes the following:
14+
15+
- The function handle
16+
- The function name
17+
- The function API version
18+
- The targeting configuration
19+
- The schema path
20+
- The WASM path
21+
- The function runner path`
22+
23+
static description = this.descriptionWithoutMarkdown()
24+
25+
static flags = {
26+
...globalFlags,
27+
...appFlags,
28+
...functionFlags,
29+
...jsonFlag,
30+
}
31+
32+
public async run(): Promise<AppUnlinkedCommandOutput> {
33+
const {flags} = await this.parse(FunctionInfo)
34+
35+
const app = await localAppContext({
36+
directory: flags.path,
37+
userProvidedConfigName: flags.config,
38+
})
39+
40+
const ourFunction = await chooseFunction(app, flags.path)
41+
const functionRunner = functionRunnerBinary()
42+
await downloadBinary(functionRunner)
43+
44+
const targeting: {[key: string]: {inputQueryPath?: string; export?: string}} = {}
45+
ourFunction?.configuration.targeting?.forEach((target) => {
46+
if (target.target) {
47+
targeting[target.target] = {
48+
...(target.input_query && {inputQueryPath: `${ourFunction.directory}/${target.input_query}`}),
49+
...(target.export && {export: target.export}),
50+
}
51+
}
52+
})
53+
54+
const schemaPath = await getOrGenerateSchemaPath(
55+
ourFunction,
56+
flags.path,
57+
flags['client-id'],
58+
flags.reset,
59+
flags.config,
60+
)
61+
62+
if (flags.json) {
63+
outputResult(
64+
JSON.stringify(
65+
{
66+
handle: ourFunction.configuration.handle,
67+
name: ourFunction.name,
68+
apiVersion: ourFunction.configuration.api_version,
69+
targeting,
70+
schemaPath,
71+
wasmPath: ourFunction.outputPath,
72+
functionRunnerPath: functionRunner.path,
73+
},
74+
null,
75+
2,
76+
),
77+
)
78+
} else {
79+
const configData: InlineToken[][] = [
80+
['Handle', ourFunction.configuration.handle ?? 'N/A'],
81+
['Name', ourFunction.name ?? 'N/A'],
82+
['API Version', ourFunction.configuration.api_version ?? 'N/A'],
83+
]
84+
85+
const sections: {title: string; body: {tabularData: InlineToken[][]; firstColumnSubdued?: boolean}}[] = [
86+
{
87+
title: 'CONFIGURATION\n',
88+
body: {
89+
tabularData: configData,
90+
firstColumnSubdued: true,
91+
},
92+
},
93+
]
94+
95+
if (Object.keys(targeting).length > 0) {
96+
const targetingData: InlineToken[][] = []
97+
Object.entries(targeting).forEach(([target, config]) => {
98+
targetingData.push([outputContent`${outputToken.cyan(target)}`.value, ''])
99+
if (config.inputQueryPath) {
100+
targetingData.push([{subdued: ' Input Query Path'}, {filePath: config.inputQueryPath}])
101+
}
102+
if (config.export) {
103+
targetingData.push([{subdued: ' Export'}, config.export])
104+
}
105+
})
106+
107+
sections.push({
108+
title: '\nTARGETING\n',
109+
body: {
110+
tabularData: targetingData,
111+
},
112+
})
113+
}
114+
115+
sections.push(
116+
{
117+
title: '\nBUILD\n',
118+
body: {
119+
tabularData: [
120+
['Schema Path', {filePath: schemaPath ?? 'N/A'}],
121+
['Wasm Path', {filePath: ourFunction.outputPath}],
122+
],
123+
firstColumnSubdued: true,
124+
},
125+
},
126+
{
127+
title: '\nFUNCTION RUNNER\n',
128+
body: {
129+
tabularData: [['Path', {filePath: functionRunner.path}]],
130+
firstColumnSubdued: true,
131+
},
132+
},
133+
)
134+
135+
renderInfo({
136+
customSections: sections,
137+
})
138+
}
139+
140+
return {app}
141+
}
142+
}

packages/app/src/cli/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import gatherSensitiveMetadata from './hooks/sensitive_metadata.js'
2828
import AppLinkedCommand from './utilities/app-linked-command.js'
2929
import DevClean from './commands/app/dev/clean.js'
3030
import AppUnlinkedCommand from './utilities/app-unlinked-command.js'
31+
import FunctionInfo from './commands/app/function/info.js'
3132

3233
/**
3334
* All app commands should extend AppCommand.
@@ -51,6 +52,7 @@ export const commands: {[key: string]: typeof AppLinkedCommand | typeof AppUnlin
5152
'app:function:build': FunctionBuild,
5253
'app:function:replay': FunctionReplay,
5354
'app:function:run': FunctionRun,
55+
'app:function:info': FunctionInfo,
5456
'app:function:schema': FetchSchema,
5557
'app:function:typegen': FunctionTypegen,
5658
'app:generate:extension': AppGenerateExtension,

0 commit comments

Comments
 (0)