Skip to content

Route theme mutations through requestThemeAdminDoc - #8897

Open
iaineh wants to merge 4 commits into
mainfrom
iain/theme-api-route-mutations
Open

iaineh wants to merge 4 commits into
mainfrom
iain/theme-api-route-mutations

Conversation

@iaineh

@iaineh iaineh commented Oct 14, 2026 •

Copy link
Copy Markdown

WHY are these changes introduced?

Theme reads (theme pull, theme list, theme info, ...) already go through requestThemeAdminDoc, which turns an ACCESS_DENIED GraphQL error into a friendly message that names the missing scope. Theme mutations still called adminRequestDoc directly, so the same error surfaced as a raw GraphQL failure.

This also creates the single wrapper that #8562 needs for Trust Battery challenge handling.

WHAT is this pull request doing?

  • Moves themePublish from adminRequestDoc to requestThemeAdminDoc for the missing-scope message that theme reads already show.
  • Moves themeDelete from adminRequestDoc to requestThemeAdminDoc for the missing-scope message that theme reads already show.
  • Moves themeUpdate from adminRequestDoc to requestThemeAdminDoc for the missing-scope message that theme reads already show.
  • Moves themeDuplicate from adminRequestDoc to requestThemeAdminDoc for the missing-scope message that theme reads already show.
  • Moves deleteThemeAssets (ThemeFilesDelete) from adminRequestDoc to requestThemeAdminDoc for the missing-scope message that theme reads already show.
  • Moves uploadFiles (ThemeFilesUpsert) from adminRequestDoc to requestThemeAdminDoc for the missing-scope message that theme reads already show.
  • Changes abortIfMissingThemeAccessScope from ClientError only to ClientError or GraphQLClientError, because theme mutations keep the default Admin error handling, which maps the ClientError to a GraphQLClientError before the check runs. Without this, the six mutations above never show the missing-scope message.
  • Adds tests for themePublish and themeDelete that assert the write_themes missing-scope abort. They reject with the output of the real errorHandler('Admin'), which is what a mutation gets. The existing read tests keep the raw ClientError, because reads pass handleErrors: false.
  • Adds extractGraphQLErrors to private/node/api/graphql.ts, next to errorHandler, for one reader of the GraphQL errors before and after mapping. The scope check uses it, and Handle Trust Battery challenges in theme commands #8562's challenge check uses it too. A test proves that errorHandler keeps the errors that both checks read.

fetchTheme, metafieldDefinitionsByOwnerType, and passwordProtected stay on adminRequestDoc: their queries read no theme files, so no theme decision runs for them on Core's side.

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes
  • I've considered analytics changes to measure impact
  • The change is user-facing — I've identified the correct bump type (patch for bug fixes · minor for new features · major for breaking changes) and added a changeset with pnpm changeset add

@github-actions github-actions Bot added the Area: @shopify/cli @shopify/cli package issues label Oct 14, 2026
@iaineh
iaineh marked this pull request as ready for review October 15, 2026 12:22
@iaineh
iaineh requested a review from a team as a code owner October 15, 2026 12:22
Copilot AI balanced review requested due to automatic review settings October 15, 2026 12:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Default error mapping prevents all six migrated requests from reaching the intended missing-scope handling.

1 open finding
What changed in this PR

Routes theme mutations through the shared theme request wrapper to improve missing-scope errors and prepare for Trust Battery handling in #8562.

Changes:

  • Migrates six mutation requests to requestThemeAdminDoc.
  • Adds missing-scope tests for publishing and deletion.
  • Adds a patch changeset.
File Description
packages/​cli-kit/​src/​public/​node/​themes/​api.ts Routes six mutations through the shared wrapper.
packages/​cli-kit/​src/​public/​node/​themes/​api.test.ts Tests publishing and deletion scope errors.
.changeset/​theme-mutations-missing-scope.md Documents the intended error-message improvement.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

const batch = filenames.slice(i, i + batchSize)
// eslint-disable-next-line no-await-in-loop
const {themeFilesDelete} = await adminRequestDoc({
const {themeFilesDelete} = await requestThemeAdminDoc({
@iaineh
iaineh requested a review from a team as a code owner October 15, 2026 13:10
Comment thread packages/cli-kit/src/public/node/themes/api.test.ts
Comment thread packages/cli-kit/src/public/node/themes/api.ts

@catlee catlee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Two non-blocking notes inline.


Generated with Pi.

Theme mutations keep the default Admin error handling. It changes the ClientError into a GraphQLClientError, so the missing-scope check did not see the ACCESS_DENIED error. The check now reads the GraphQL errors from both error types. The tests use the mapped error that theme mutations get.
extractGraphQLErrors returns the GraphQL errors of a ClientError or of the GraphQLClientError that errorHandler maps it to. The theme access scope check uses it instead of its own copy.
@iaineh
iaineh force-pushed the iain/theme-api-route-mutations branch from 1a3a3cd to 309f40b Compare October 16, 2026 12:22
- The `write_themes` next step now names `theme publish`, `theme delete`,
  `theme rename` and `theme duplicate` as well as `theme push` and
  `theme dev`, because those commands now reach this message too.
- Add the missing-scope test for `themeUpdate`, `deleteThemeAssets`,
  `themeDuplicate` and `bulkUploadThemeAssets`, so that all six theme
  mutations that use `requestThemeAdminDoc` are covered.
@github-actions

Copy link
Copy Markdown
Contributor

Differences in type declarations

We detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

We found no new type declarations in this PR

Existing type declarations

packages/cli-kit/dist/private/node/api/graphql.d.ts
@@ -1,4 +1,4 @@
-import { Variables } from 'graphql-request';
+import { ClientError, Variables } from 'graphql-request';
 export declare function debugLogRequestInfo(api: string, query: string, url: string, variables?: Variables, headers?: Record<string, string>): void;
 export declare function sanitizeVariables(variables: Variables): string;
 /**
@@ -11,4 +11,5 @@ export declare function sanitizeVariables(variables: Variables): string;
  * the full JSON representation if no messages can be extracted.
  */
 export declare function extractGraphQLErrorMessages(errors: any[] | undefined): string | undefined;
-export declare function errorHandler(api: string): (error: unknown, requestId?: string) => unknown;
\ No newline at end of file
+export declare function errorHandler(api: string): (error: unknown, requestId?: string) => unknown;
+export declare function extractGraphQLErrors(error: unknown): NonNullable<ClientError['response']['errors']>;
\ No newline at end of file

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: @shopify/cli @shopify/cli package issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants