Skip to content
Open
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
6 changes: 6 additions & 0 deletions .changeset/migration-refusal-known-values.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@shopify/app': patch
'@shopify/cli': patch
---

Document plan requirement and shop verification failure reasons in the subscription migration JSON schema.
6 changes: 5 additions & 1 deletion packages/app/src/cli/models/subscription-migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ export const MIGRATABLE_SUBSCRIPTION_STATUSES = ['UNSCHEDULED', 'SCHEDULED', 'MI
export type MigratableSubscriptionStatus = (typeof MIGRATABLE_SUBSCRIPTION_STATUSES)[number]

export type ManualSubscriptionInterval = 'EVERY_30_DAYS' | 'ANNUAL'
export type MigrationFailureReason = 'SUPERSEDED' | 'SCHEDULING_FAILED'
export type MigrationFailureReason =
| 'SUPERSEDED'
| 'SCHEDULING_FAILED'
| 'PLAN_REQUIREMENTS_NOT_MET'
| 'SHOP_FEATURES_UNVERIFIED'
export type MigratableSubscriptionNotificationKind = 'NONE' | 'OPT_OUT' | 'WHEN_REQUIRED'
export type MigratableSubscriptionPriceBehavior = 'HONOR_BILLING_PRICE' | 'PLAN_PRICE'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ const MigratableSubscriptionSchema = zod
.union([CalendarDateSchema, UtcInstantSchema])
.nullable()
.describe('The upstream calendar date or whole-second UTC instant; date-only values retain their format.'),
lastFailureReason: zod.string().nullable().describe('Known values: SUPERSEDED, SCHEDULING_FAILED.'),
lastFailureReason: zod
.string()
.nullable()
.describe('Known values: SUPERSEDED, SCHEDULING_FAILED, PLAN_REQUIREMENTS_NOT_MET, SHOP_FEATURES_UNVERIFIED.'),
})
.strict()
.describe('All subscription projection fields are present; unavailable values are null.')
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6577,7 +6577,7 @@ DESCRIPTION
"string",
"null"
],
"description": "Known values: SUPERSEDED, SCHEDULING_FAILED."
"description": "Known values: SUPERSEDED, SCHEDULING_FAILED, PLAN_REQUIREMENTS_NOT_MET, SHOP_FEATURES_UNVERIFIED."
}
},
"required": [
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/oclif.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4935,7 +4935,7 @@
"args": {
},
"customPluginName": "@shopify/app",
"description": "Lists every app subscription eligible for migration.\n\nBy default, the command writes CSV to stdout, streaming each page of results as it arrives. If a later page fails, the rows already written remain valid CSV. Use `--json` to fetch all pages first and then write a single JSON envelope to stdout. Use shell redirection to save either format, for example `shopify app subscription-migrations list > subscriptions.csv` or `shopify app subscription-migrations list --json > subscriptions.json`.\n\nUse `--status` to filter subscriptions by migration status. Supported values are `UNSCHEDULED`, `SCHEDULED`, and `MIGRATED`.\n\nRun the command from an app project. By default, it uses the Client ID from the active app configuration. Use `--path` to select an app directory or `--config` to select a configuration. Pass `--client-id` to select a different app within the project. Use `--reset` to relink the app.\n\nUse `--json-schema` to print the result, error, and event schemas.\n\nOutput from `--json` conforms to the `MigrationListResult` schema.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"subscriptions\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/MigratableSubscription\"\n },\n \"description\": \"The complete list across every fetched page.\"\n }\n },\n \"required\": [\n \"subscriptions\"\n ],\n \"additionalProperties\": false,\n \"title\": \"MigrationListResult\",\n \"definitions\": {\n \"MigratableSubscription\": {\n \"type\": \"object\",\n \"properties\": {\n \"shopGid\": {\n \"type\": \"string\",\n \"pattern\": \"^gid:\\\\/\\\\/shopify\\\\/Shop\\\\/\\\\d+$\",\n \"description\": \"The Shopify Shop GID.\"\n },\n \"status\": {\n \"type\": \"string\",\n \"description\": \"Known values: UNSCHEDULED, SCHEDULED, MIGRATED.\"\n },\n \"manualSubscriptionName\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"manualSubscriptionPrice\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/definitions/MigratableSubscriptionPrice\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"manualSubscriptionInterval\": {\n \"type\": \"string\",\n \"description\": \"Known values: EVERY_30_DAYS, ANNUAL.\"\n },\n \"targetPlanHandle\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"notification\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/definitions/MigratableSubscriptionNotification\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"priceBehavior\": {\n \"type\": [\n \"string\",\n \"null\"\n ],\n \"description\": \"Known values: HONOR_BILLING_PRICE, PLAN_PRICE.\"\n },\n \"effectiveDate\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"format\": \"date\"\n },\n {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2}T\\\\d{2}:\\\\d{2}:\\\\d{2}Z$\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"The upstream calendar date or whole-second UTC instant; date-only values retain their format.\"\n },\n \"lastFailureReason\": {\n \"type\": [\n \"string\",\n \"null\"\n ],\n \"description\": \"Known values: SUPERSEDED, SCHEDULING_FAILED.\"\n }\n },\n \"required\": [\n \"shopGid\",\n \"status\",\n \"manualSubscriptionName\",\n \"manualSubscriptionPrice\",\n \"manualSubscriptionInterval\",\n \"targetPlanHandle\",\n \"notification\",\n \"priceBehavior\",\n \"effectiveDate\",\n \"lastFailureReason\"\n ],\n \"additionalProperties\": false,\n \"description\": \"All subscription projection fields are present; unavailable values are null.\"\n },\n \"MigratableSubscriptionPrice\": {\n \"type\": \"object\",\n \"properties\": {\n \"amount\": {\n \"type\": \"string\",\n \"pattern\": \"^-?\\\\d+(?:\\\\.\\\\d+)?$\"\n },\n \"currencyCode\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Z]{3}$\"\n }\n },\n \"required\": [\n \"amount\",\n \"currencyCode\"\n ],\n \"additionalProperties\": false\n },\n \"MigratableSubscriptionNotification\": {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"type\": \"string\",\n \"description\": \"Known values: NONE, OPT_OUT, WHEN_REQUIRED.\"\n },\n \"optOutDeadline\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/definitions/MigratableSubscription/properties/effectiveDate/anyOf/0/anyOf/1\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sentAt\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/definitions/MigratableSubscription/properties/effectiveDate/anyOf/0/anyOf/1\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"kind\",\n \"optOutDeadline\",\n \"sentAt\"\n ],\n \"additionalProperties\": false\n }\n },\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```",
"description": "Lists every app subscription eligible for migration.\n\nBy default, the command writes CSV to stdout, streaming each page of results as it arrives. If a later page fails, the rows already written remain valid CSV. Use `--json` to fetch all pages first and then write a single JSON envelope to stdout. Use shell redirection to save either format, for example `shopify app subscription-migrations list > subscriptions.csv` or `shopify app subscription-migrations list --json > subscriptions.json`.\n\nUse `--status` to filter subscriptions by migration status. Supported values are `UNSCHEDULED`, `SCHEDULED`, and `MIGRATED`.\n\nRun the command from an app project. By default, it uses the Client ID from the active app configuration. Use `--path` to select an app directory or `--config` to select a configuration. Pass `--client-id` to select a different app within the project. Use `--reset` to relink the app.\n\nUse `--json-schema` to print the result, error, and event schemas.\n\nOutput from `--json` conforms to the `MigrationListResult` schema.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"subscriptions\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/MigratableSubscription\"\n },\n \"description\": \"The complete list across every fetched page.\"\n }\n },\n \"required\": [\n \"subscriptions\"\n ],\n \"additionalProperties\": false,\n \"title\": \"MigrationListResult\",\n \"definitions\": {\n \"MigratableSubscription\": {\n \"type\": \"object\",\n \"properties\": {\n \"shopGid\": {\n \"type\": \"string\",\n \"pattern\": \"^gid:\\\\/\\\\/shopify\\\\/Shop\\\\/\\\\d+$\",\n \"description\": \"The Shopify Shop GID.\"\n },\n \"status\": {\n \"type\": \"string\",\n \"description\": \"Known values: UNSCHEDULED, SCHEDULED, MIGRATED.\"\n },\n \"manualSubscriptionName\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"manualSubscriptionPrice\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/definitions/MigratableSubscriptionPrice\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"manualSubscriptionInterval\": {\n \"type\": \"string\",\n \"description\": \"Known values: EVERY_30_DAYS, ANNUAL.\"\n },\n \"targetPlanHandle\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"notification\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/definitions/MigratableSubscriptionNotification\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"priceBehavior\": {\n \"type\": [\n \"string\",\n \"null\"\n ],\n \"description\": \"Known values: HONOR_BILLING_PRICE, PLAN_PRICE.\"\n },\n \"effectiveDate\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"format\": \"date\"\n },\n {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2}T\\\\d{2}:\\\\d{2}:\\\\d{2}Z$\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"The upstream calendar date or whole-second UTC instant; date-only values retain their format.\"\n },\n \"lastFailureReason\": {\n \"type\": [\n \"string\",\n \"null\"\n ],\n \"description\": \"Known values: SUPERSEDED, SCHEDULING_FAILED, PLAN_REQUIREMENTS_NOT_MET, SHOP_FEATURES_UNVERIFIED.\"\n }\n },\n \"required\": [\n \"shopGid\",\n \"status\",\n \"manualSubscriptionName\",\n \"manualSubscriptionPrice\",\n \"manualSubscriptionInterval\",\n \"targetPlanHandle\",\n \"notification\",\n \"priceBehavior\",\n \"effectiveDate\",\n \"lastFailureReason\"\n ],\n \"additionalProperties\": false,\n \"description\": \"All subscription projection fields are present; unavailable values are null.\"\n },\n \"MigratableSubscriptionPrice\": {\n \"type\": \"object\",\n \"properties\": {\n \"amount\": {\n \"type\": \"string\",\n \"pattern\": \"^-?\\\\d+(?:\\\\.\\\\d+)?$\"\n },\n \"currencyCode\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Z]{3}$\"\n }\n },\n \"required\": [\n \"amount\",\n \"currencyCode\"\n ],\n \"additionalProperties\": false\n },\n \"MigratableSubscriptionNotification\": {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"type\": \"string\",\n \"description\": \"Known values: NONE, OPT_OUT, WHEN_REQUIRED.\"\n },\n \"optOutDeadline\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/definitions/MigratableSubscription/properties/effectiveDate/anyOf/0/anyOf/1\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sentAt\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/definitions/MigratableSubscription/properties/effectiveDate/anyOf/0/anyOf/1\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"kind\",\n \"optOutDeadline\",\n \"sentAt\"\n ],\n \"additionalProperties\": false\n }\n },\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```",
"descriptionWithMarkdown": "Lists every app subscription eligible for migration.\n\nBy default, the command writes CSV to stdout, streaming each page of results as it arrives. If a later page fails, the rows already written remain valid CSV. Use `--json` to fetch all pages first and then write a single JSON envelope to stdout. Use shell redirection to save either format, for example `shopify app subscription-migrations list > subscriptions.csv` or `shopify app subscription-migrations list --json > subscriptions.json`.\n\nUse `--status` to filter subscriptions by migration status. Supported values are `UNSCHEDULED`, `SCHEDULED`, and `MIGRATED`.\n\nRun the command from an app project. By default, it uses the Client ID from the active app configuration. Use `--path` to select an app directory or `--config` to select a configuration. Pass `--client-id` to select a different app within the project. Use `--reset` to relink the app.",
"examples": [
"<%= config.bin %> <%= command.id %>",
Expand Down
Loading