Skip to content

Commit 756d78a

Browse files
Merge pull request #6662 from anakafeel/feature/skip-prompts-config-link-6293
fix(app): skip app prompt when config is already linked
2 parents fb2af80 + 22772e3 commit 756d78a

File tree

11 files changed

+394
-2
lines changed

11 files changed

+394
-2
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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 config pull',
6+
description: `Pulls the latest configuration from the already-linked Shopify app and updates the selected configuration file.
7+
8+
This command reuses the existing linked app and organization and skips all interactive prompts. Use \`--config\` to target a specific configuration file, or omit it to use the default one.`,
9+
overviewPreviewDescription: `Refresh an already-linked app configuration without prompts.`,
10+
type: 'command',
11+
isVisualComponent: false,
12+
defaultExample: {
13+
codeblock: {
14+
tabs: [
15+
{
16+
title: 'app config pull',
17+
code: './examples/app-config-pull.example.sh',
18+
language: 'bash',
19+
},
20+
],
21+
title: 'app config pull',
22+
},
23+
},
24+
definitions: [
25+
{
26+
title: 'Flags',
27+
description: 'The following flags are available for the `app config pull` command:',
28+
type: 'appconfigpull',
29+
},
30+
],
31+
category: 'app',
32+
related: [
33+
],
34+
}
35+
36+
export default data
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
shopify app config pull [flags]
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// This is an autogenerated file. Don't edit this file manually.
2+
export interface appconfigpull {
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+
* Disable color output.
17+
* @environment SHOPIFY_FLAG_NO_COLOR
18+
*/
19+
'--no-color'?: ''
20+
21+
/**
22+
* The path to your app directory.
23+
* @environment SHOPIFY_FLAG_PATH
24+
*/
25+
'--path <value>'?: string
26+
27+
/**
28+
* Reset all your settings.
29+
* @environment SHOPIFY_FLAG_RESET
30+
*/
31+
'--reset'?: ''
32+
33+
/**
34+
* Increase the verbosity of the output.
35+
* @environment SHOPIFY_FLAG_VERBOSE
36+
*/
37+
'--verbose'?: ''
38+
}

docs-shopify.dev/generated/generated_docs_data.json

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,98 @@
192192
"category": "app",
193193
"related": []
194194
},
195+
{
196+
"name": "app config pull",
197+
"description": "Pulls the latest configuration from the already-linked Shopify app and updates the selected configuration file.\n\nThis command reuses the existing linked app and organization and skips all interactive prompts. Use `--config` to target a specific configuration file, or omit it to use the default one.",
198+
"overviewPreviewDescription": "Refresh an already-linked app configuration without prompts.",
199+
"type": "command",
200+
"isVisualComponent": false,
201+
"defaultExample": {
202+
"codeblock": {
203+
"tabs": [
204+
{
205+
"title": "app config pull",
206+
"code": "shopify app config pull [flags]",
207+
"language": "bash"
208+
}
209+
],
210+
"title": "app config pull"
211+
}
212+
},
213+
"definitions": [
214+
{
215+
"title": "Flags",
216+
"description": "The following flags are available for the `app config pull` command:",
217+
"type": "appconfigpull",
218+
"typeDefinitions": {
219+
"appconfigpull": {
220+
"filePath": "docs-shopify.dev/commands/interfaces/app-config-pull.interface.ts",
221+
"name": "appconfigpull",
222+
"description": "",
223+
"members": [
224+
{
225+
"filePath": "docs-shopify.dev/commands/interfaces/app-config-pull.interface.ts",
226+
"syntaxKind": "PropertySignature",
227+
"name": "--client-id <value>",
228+
"value": "string",
229+
"description": "The Client ID of your app.",
230+
"isOptional": true,
231+
"environmentValue": "SHOPIFY_FLAG_CLIENT_ID"
232+
},
233+
{
234+
"filePath": "docs-shopify.dev/commands/interfaces/app-config-pull.interface.ts",
235+
"syntaxKind": "PropertySignature",
236+
"name": "--no-color",
237+
"value": "\"\"",
238+
"description": "Disable color output.",
239+
"isOptional": true,
240+
"environmentValue": "SHOPIFY_FLAG_NO_COLOR"
241+
},
242+
{
243+
"filePath": "docs-shopify.dev/commands/interfaces/app-config-pull.interface.ts",
244+
"syntaxKind": "PropertySignature",
245+
"name": "--path <value>",
246+
"value": "string",
247+
"description": "The path to your app directory.",
248+
"isOptional": true,
249+
"environmentValue": "SHOPIFY_FLAG_PATH"
250+
},
251+
{
252+
"filePath": "docs-shopify.dev/commands/interfaces/app-config-pull.interface.ts",
253+
"syntaxKind": "PropertySignature",
254+
"name": "--reset",
255+
"value": "\"\"",
256+
"description": "Reset all your settings.",
257+
"isOptional": true,
258+
"environmentValue": "SHOPIFY_FLAG_RESET"
259+
},
260+
{
261+
"filePath": "docs-shopify.dev/commands/interfaces/app-config-pull.interface.ts",
262+
"syntaxKind": "PropertySignature",
263+
"name": "--verbose",
264+
"value": "\"\"",
265+
"description": "Increase the verbosity of the output.",
266+
"isOptional": true,
267+
"environmentValue": "SHOPIFY_FLAG_VERBOSE"
268+
},
269+
{
270+
"filePath": "docs-shopify.dev/commands/interfaces/app-config-pull.interface.ts",
271+
"syntaxKind": "PropertySignature",
272+
"name": "-c, --config <value>",
273+
"value": "string",
274+
"description": "The name of the app configuration.",
275+
"isOptional": true,
276+
"environmentValue": "SHOPIFY_FLAG_APP_CONFIG"
277+
}
278+
],
279+
"value": "export interface appconfigpull {\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 path to your app 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}"
280+
}
281+
}
282+
}
283+
],
284+
"category": "app",
285+
"related": []
286+
},
195287
{
196288
"name": "app config use",
197289
"description": "Sets default configuration when you run app-related CLI commands. If you omit the `config-name` parameter, then you'll be prompted to choose from the configuration files in your project.",
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {appFlags} from '../../../flags.js'
2+
import {linkedAppContext} from '../../../services/app-context.js'
3+
import pull from '../../../services/app/config/pull.js'
4+
import AppLinkedCommand, {AppLinkedCommandOutput} from '../../../utilities/app-linked-command.js'
5+
import {renderSuccess} from '@shopify/cli-kit/node/ui'
6+
import {globalFlags} from '@shopify/cli-kit/node/cli'
7+
import {basename} from '@shopify/cli-kit/node/path'
8+
9+
export default class ConfigPull extends AppLinkedCommand {
10+
static summary = 'Refresh an already-linked app configuration without prompts.'
11+
12+
static descriptionWithMarkdown = `Pulls the latest configuration from the already-linked Shopify app and updates the selected configuration file.
13+
14+
This command reuses the existing linked app and organization and skips all interactive prompts. Use \`--config\` to target a specific configuration file, or omit it to use the default one.`
15+
16+
static description = this.descriptionWithoutMarkdown()
17+
18+
static flags = {
19+
...globalFlags,
20+
...appFlags,
21+
}
22+
23+
public async run(): Promise<AppLinkedCommandOutput> {
24+
const {flags} = await this.parse(ConfigPull)
25+
26+
const {app, remoteApp} = await linkedAppContext({
27+
directory: flags.path,
28+
clientId: flags['client-id'],
29+
forceRelink: flags.reset,
30+
userProvidedConfigName: flags.config,
31+
})
32+
33+
const {configuration} = await pull({
34+
directory: flags.path,
35+
configName: flags.config,
36+
configuration: app.configuration,
37+
remoteApp,
38+
})
39+
40+
renderSuccess({
41+
headline: `Pulled latest configuration for "${configuration.name}"`,
42+
body: `Updated ${basename(configuration.path)} with the remote data.`,
43+
})
44+
45+
return {app}
46+
}
47+
}

packages/app/src/cli/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Build from './commands/app/build.js'
22
import BulkStatus from './commands/app/bulk/status.js'
33
import ConfigLink from './commands/app/config/link.js'
44
import ConfigUse from './commands/app/config/use.js'
5+
import ConfigPull from './commands/app/config/pull.js'
56
import DemoWatcher from './commands/app/demo/watcher.js'
67
import Deploy from './commands/app/deploy.js'
78
import Dev from './commands/app/dev.js'
@@ -49,6 +50,7 @@ export const commands: {[key: string]: typeof AppLinkedCommand | typeof AppUnlin
4950
'app:release': Release,
5051
'app:config:link': ConfigLink,
5152
'app:config:use': ConfigUse,
53+
'app:config:pull': ConfigPull,
5254
'app:env:pull': EnvPull,
5355
'app:env:show': EnvShow,
5456
'app:execute': Execute,

packages/app/src/cli/services/app/config/link.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ type LocalAppOptions =
239239
* @param specifications - Module specs to use for loading. These must have come from the platform.
240240
* @returns Either a loaded app, or some placeholder data
241241
*/
242-
async function loadLocalAppOptions(
242+
export async function loadLocalAppOptions(
243243
options: LinkOptions,
244244
specifications: RemoteAwareExtensionSpecification[],
245245
remoteFlags: Flag[],
@@ -344,7 +344,7 @@ async function loadConfigurationFileName(
344344
* Build a new app configuration object based on the remote app's modules, and write it to the filesystem, merging
345345
* with the existing local file.
346346
*/
347-
async function overwriteLocalConfigFileWithRemoteAppConfiguration(options: {
347+
export async function overwriteLocalConfigFileWithRemoteAppConfiguration(options: {
348348
remoteApp: OrganizationApp
349349
developerPlatformClient: DeveloperPlatformClient
350350
specifications: RemoteAwareExtensionSpecification[]
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// packages/app/src/cli/services/app/config/pull.ts
2+
3+
import {LinkOptions, loadLocalAppOptions, overwriteLocalConfigFileWithRemoteAppConfiguration} from './link.js'
4+
import {CurrentAppConfiguration, isCurrentAppSchema} from '../../../models/app/app.js'
5+
import {OrganizationApp} from '../../../models/organization.js'
6+
import {AppConfigurationFileName} from '../../../models/app/loader.js'
7+
import {fetchSpecifications} from '../../generate/fetch-extension-specifications.js'
8+
import {RemoteAwareExtensionSpecification} from '../../../models/extensions/specification.js'
9+
import {Flag} from '../../../utilities/developer-platform-client.js'
10+
import {AbortError} from '@shopify/cli-kit/node/error'
11+
import {basename} from '@shopify/cli-kit/node/path'
12+
13+
interface PullOptions {
14+
directory: string
15+
configName?: string
16+
configuration: CurrentAppConfiguration
17+
remoteApp: OrganizationApp
18+
}
19+
20+
interface PullOutput {
21+
configuration: CurrentAppConfiguration
22+
remoteApp: OrganizationApp
23+
}
24+
25+
/**
26+
* Refresh an already-linked app configuration without prompting for org/app.
27+
*/
28+
export default async function pull(options: PullOptions): Promise<PullOutput> {
29+
const {directory, configName, configuration, remoteApp} = options
30+
31+
if (!isCurrentAppSchema(configuration) || !configuration.client_id) {
32+
throw new AbortError(
33+
'The selected configuration is not linked to a remote app.',
34+
'Run `shopify app config link` first to link this configuration to a Shopify app.',
35+
)
36+
}
37+
38+
const developerPlatformClient = remoteApp.developerPlatformClient
39+
40+
// Fetch remote specs/flags for that app
41+
const specifications: RemoteAwareExtensionSpecification[] = await fetchSpecifications({
42+
developerPlatformClient,
43+
app: remoteApp,
44+
})
45+
const flags: Flag[] = remoteApp.flags
46+
47+
// Reuse helpers from link.ts to build and write the file
48+
const linkOptions: LinkOptions = {
49+
directory,
50+
configName,
51+
developerPlatformClient,
52+
apiKey: configuration.client_id,
53+
}
54+
55+
const localAppOptions = await loadLocalAppOptions(linkOptions, specifications, flags, remoteApp.apiKey)
56+
57+
// Decide which config file to overwrite: the configuration should always have a path here.
58+
const configFileName: AppConfigurationFileName = basename(configuration.path) as AppConfigurationFileName
59+
60+
const mergedConfiguration = await overwriteLocalConfigFileWithRemoteAppConfiguration({
61+
remoteApp,
62+
developerPlatformClient,
63+
specifications,
64+
flags,
65+
configFileName,
66+
appDirectory: localAppOptions.appDirectory ?? directory,
67+
localAppOptions,
68+
})
69+
70+
return {configuration: mergedConfiguration, remoteApp}
71+
}

packages/cli/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<!-- commands -->
33
* [`shopify app build`](#shopify-app-build)
44
* [`shopify app config link`](#shopify-app-config-link)
5+
* [`shopify app config pull`](#shopify-app-config-pull)
56
* [`shopify app config use [config] [flags]`](#shopify-app-config-use-config-flags)
67
* [`shopify app deploy`](#shopify-app-deploy)
78
* [`shopify app dev`](#shopify-app-dev)
@@ -142,6 +143,31 @@ DESCRIPTION
142143
(https://shopify.dev/docs/apps/tools/cli/configuration) page.
143144
```
144145

146+
## `shopify app config pull`
147+
148+
Refresh an already-linked app configuration without prompts.
149+
150+
```
151+
USAGE
152+
$ shopify app config pull [--client-id <value> | -c <value>] [--no-color] [--path <value>] [--reset | ] [--verbose]
153+
154+
FLAGS
155+
-c, --config=<value> The name of the app configuration.
156+
--client-id=<value> The Client ID of your app.
157+
--no-color Disable color output.
158+
--path=<value> The path to your app directory.
159+
--reset Reset all your settings.
160+
--verbose Increase the verbosity of the output.
161+
162+
DESCRIPTION
163+
Refresh an already-linked app configuration without prompts.
164+
165+
Pulls the latest configuration from the already-linked Shopify app and updates the selected configuration file.
166+
167+
This command reuses the existing linked app and organization and skips all interactive prompts. Use `--config` to
168+
target a specific configuration file, or omit it to use the default one.
169+
```
170+
145171
## `shopify app config use [config] [flags]`
146172

147173
Activate an app configuration.

0 commit comments

Comments
 (0)