Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
92 changes: 92 additions & 0 deletions docs-shopify.dev/generated/generated_docs_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -3084,6 +3084,98 @@
"category": "app",
"related": []
},
{
"name": "app validate",
"description": "Validates the selected app configuration file and all extension configurations against their schemas and reports any errors found.",
"overviewPreviewDescription": "Validate your app configuration and extensions.",
"type": "command",
"isVisualComponent": false,
"defaultExample": {
"codeblock": {
"tabs": [
{
"title": "app validate",
"code": "shopify app validate [flags]",
"language": "bash"
}
],
"title": "app validate"
}
},
"definitions": [
{
"title": "Flags",
"description": "The following flags are available for the `app validate` command:",
"type": "appvalidate",
"typeDefinitions": {
"appvalidate": {
"filePath": "docs-shopify.dev/commands/interfaces/app-validate.interface.ts",
"name": "appvalidate",
"description": "",
"members": [
{
"filePath": "docs-shopify.dev/commands/interfaces/app-validate.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-validate.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-validate.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-validate.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-validate.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-validate.interface.ts",
"syntaxKind": "PropertySignature",
"name": "-c, --config <value>",
"value": "string",
"description": "The name of the app configuration.",
"isOptional": true,
"environmentValue": "SHOPIFY_FLAG_APP_CONFIG"
}
],
"value": "export interface appvalidate {\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}"
}
}
}
],
"category": "app",
"related": []
},
{
"name": "app versions list",
"description": "Lists the deployed app versions. An app version is a snapshot of your app extensions.",
Expand Down
34 changes: 34 additions & 0 deletions packages/app/src/cli/commands/app/validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {appFlags} from '../../flags.js'
import {validateApp} from '../../services/validate.js'
import AppLinkedCommand, {AppLinkedCommandOutput} from '../../utilities/app-linked-command.js'
import {linkedAppContext} from '../../services/app-context.js'
import {globalFlags} from '@shopify/cli-kit/node/cli'

export default class Validate extends AppLinkedCommand {
static summary = 'Validate your app configuration and extensions.'

static descriptionWithMarkdown = `Validates the selected app configuration file and all extension configurations against their schemas and reports any errors found.`

static description = this.descriptionWithoutMarkdown()

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

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

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

await validateApp(app)

return {app}
}
}
2 changes: 2 additions & 0 deletions packages/app/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import GenerateSchema from './commands/app/generate/schema.js'
import ImportExtensions from './commands/app/import-extensions.js'
import AppInfo from './commands/app/info.js'
import Init from './commands/app/init.js'
import Validate from './commands/app/validate.js'
import Release from './commands/app/release.js'
import VersionsList from './commands/app/versions/list.js'
import WebhookTrigger from './commands/app/webhook/trigger.js'
Expand Down Expand Up @@ -55,6 +56,7 @@ export const commands: {[key: string]: typeof AppLinkedCommand | typeof AppUnlin
'app:import-extensions': ImportExtensions,
'app:info': AppInfo,
'app:init': Init,
'app:validate': Validate,
'app:release': Release,
'app:config:link': ConfigLink,
'app:config:use': ConfigUse,
Expand Down
52 changes: 52 additions & 0 deletions packages/app/src/cli/services/validate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {validateApp} from './validate.js'
import {testAppLinked} from '../models/app/app.test-data.js'
import {AppErrors} from '../models/app/loader.js'
import {describe, expect, test, vi} from 'vitest'
import {renderError, renderSuccess} from '@shopify/cli-kit/node/ui'
import {AbortSilentError} from '@shopify/cli-kit/node/error'

vi.mock('@shopify/cli-kit/node/ui')

describe('validateApp', () => {
test('renders success when there are no errors', async () => {
// Given
const app = testAppLinked()

// When
await validateApp(app)

// Then
expect(renderSuccess).toHaveBeenCalledWith({headline: 'App configuration is valid.'})
expect(renderError).not.toHaveBeenCalled()
})

test('renders errors and throws when there are validation errors', async () => {
// Given
const errors = new AppErrors()
errors.addError('/path/to/shopify.app.toml', 'client_id is required')
errors.addError('/path/to/extensions/my-ext/shopify.extension.toml', 'invalid type "unknown"')
const app = testAppLinked()
app.errors = errors

// When / Then
await expect(validateApp(app)).rejects.toThrow(AbortSilentError)
expect(renderError).toHaveBeenCalledWith({
headline: 'Validation errors found.',
body: expect.stringContaining('client_id is required'),
})
expect(renderSuccess).not.toHaveBeenCalled()
})

test('renders success when errors object exists but is empty', async () => {
// Given
const errors = new AppErrors()
const app = testAppLinked()
app.errors = errors

// When
await validateApp(app)

// Then
expect(renderSuccess).toHaveBeenCalledWith({headline: 'App configuration is valid.'})
})
})
22 changes: 22 additions & 0 deletions packages/app/src/cli/services/validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {AppLinkedInterface} from '../models/app/app.js'
import {stringifyMessage} from '@shopify/cli-kit/node/output'
import {renderError, renderSuccess} from '@shopify/cli-kit/node/ui'
import {AbortSilentError} from '@shopify/cli-kit/node/error'

export async function validateApp(app: AppLinkedInterface): Promise<void> {
const errors = app.errors

if (!errors || errors.isEmpty()) {
renderSuccess({headline: 'App configuration is valid.'})
return
}

const errorMessages = errors.toJSON().map((error) => stringifyMessage(error).trim())

renderError({
headline: 'Validation errors found.',
body: errorMessages.join('\n\n'),
})

throw new AbortSilentError()
}
24 changes: 24 additions & 0 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* [`shopify app logs`](#shopify-app-logs)
* [`shopify app logs sources`](#shopify-app-logs-sources)
* [`shopify app release --version <version>`](#shopify-app-release---version-version)
* [`shopify app validate`](#shopify-app-validate)
* [`shopify app versions list`](#shopify-app-versions-list)
* [`shopify app webhook trigger`](#shopify-app-webhook-trigger)
* [`shopify auth login`](#shopify-auth-login)
Expand Down Expand Up @@ -919,6 +920,29 @@ DESCRIPTION
Releases an existing app version. Pass the name of the version that you want to release using the `--version` flag.
```

## `shopify app validate`

Validate your app configuration and extensions.

```
USAGE
$ shopify app validate [--client-id <value> | -c <value>] [--no-color] [--path <value>] [--reset | ] [--verbose]

FLAGS
-c, --config=<value> [env: SHOPIFY_FLAG_APP_CONFIG] The name of the app configuration.
--client-id=<value> [env: SHOPIFY_FLAG_CLIENT_ID] The Client ID of your app.
--no-color [env: SHOPIFY_FLAG_NO_COLOR] Disable color output.
--path=<value> [env: SHOPIFY_FLAG_PATH] The path to your app directory.
--reset [env: SHOPIFY_FLAG_RESET] Reset all your settings.
--verbose [env: SHOPIFY_FLAG_VERBOSE] Increase the verbosity of the output.

DESCRIPTION
Validate your app configuration and extensions.

Validates the selected app configuration file and all extension configurations against their schemas and reports any
errors found.
```

## `shopify app versions list`

List deployed versions of your app.
Expand Down
78 changes: 78 additions & 0 deletions packages/cli/oclif.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2852,6 +2852,84 @@
"summary": "Release an app version.",
"usage": "app release --version <version>"
},
"app:validate": {
"aliases": [
],
"args": {
},
"customPluginName": "@shopify/app",
"description": "Validates the selected app configuration file and all extension configurations against their schemas and reports any errors found.",
"descriptionWithMarkdown": "Validates the selected app configuration file and all extension configurations against their schemas and reports any errors found.",
"flags": {
"client-id": {
"description": "The Client ID of your app.",
"env": "SHOPIFY_FLAG_CLIENT_ID",
"exclusive": [
"config"
],
"hasDynamicHelp": false,
"hidden": false,
"multiple": false,
"name": "client-id",
"type": "option"
},
"config": {
"char": "c",
"description": "The name of the app configuration.",
"env": "SHOPIFY_FLAG_APP_CONFIG",
"hasDynamicHelp": false,
"hidden": false,
"multiple": false,
"name": "config",
"type": "option"
},
"no-color": {
"allowNo": false,
"description": "Disable color output.",
"env": "SHOPIFY_FLAG_NO_COLOR",
"hidden": false,
"name": "no-color",
"type": "boolean"
},
"path": {
"description": "The path to your app directory.",
"env": "SHOPIFY_FLAG_PATH",
"hasDynamicHelp": false,
"multiple": false,
"name": "path",
"noCacheDefault": true,
"type": "option"
},
"reset": {
"allowNo": false,
"description": "Reset all your settings.",
"env": "SHOPIFY_FLAG_RESET",
"exclusive": [
"config"
],
"hidden": false,
"name": "reset",
"type": "boolean"
},
"verbose": {
"allowNo": false,
"description": "Increase the verbosity of the output.",
"env": "SHOPIFY_FLAG_VERBOSE",
"hidden": false,
"name": "verbose",
"type": "boolean"
}
},
"hasDynamicHelp": false,
"hiddenAliases": [
],
"id": "app:validate",
"pluginAlias": "@shopify/cli",
"pluginName": "@shopify/cli",
"pluginType": "core",
"strict": true,
"summary": "Validate your app configuration and extensions."
},
"app:versions:list": {
"aliases": [
],
Expand Down
1 change: 1 addition & 0 deletions packages/e2e/data/snapshots/commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
│ ├─ logs
│ │ └─ sources
│ ├─ release
│ ├─ validate
│ ├─ versions
│ │ └─ list
│ └─ webhook
Expand Down
Loading