Skip to content

Support target-level input query variables on functions - #8471

Draft
saga-dasgupta wants to merge 1 commit into
mainfrom
sd.target_level_input_query_variables
Draft

Support target-level input query variables on functions#8471
saga-dasgupta wants to merge 1 commit into
mainfrom
sd.target_level_input_query_variables

Conversation

@saga-dasgupta

Copy link
Copy Markdown
Contributor

WHY are these changes introduced?

Function input queries have always been per-target — each [[targeting]] entry gets its own input_query. Their variables, however, were per-function: a single extension-level [input.variables] applied to every target.

shop/world#1015868 closes that asymmetry in Core by adding input_query_variables to Execution::FunctionTarget. That PR's own description lists three CLI follow-ups; this is all three.

WHAT is this pull request doing?

In function.ts:

  1. Accepts input_variables on a [[targeting]] entry. Same {namespace, key} shape as the extension-level field, now extracted into a shared InputVariablesSchema so the two can't drift.

  2. Forwards it to the deploy payload as input_query_variables: {single_json_metafield: ...} on each target — identical wrapping to the extension-level field, matching Functions::SingleJsonMetafieldInputQueryVariables.

  3. Rejects mixing the two levels via superRefine. An issue is added per offending target at ['targeting', <index>, 'input_variables'], so the error points at the same line Core's deploy-time validator would, rather than at the top of the TOML.

# now valid
[[targeting]]
target = "cart.lines.discounts.generate.run"
input_query = "run.graphql"
input_variables = { namespace = "my-namespace", key = "my-key" }

# rejected locally, as it is at deploy
[input.variables]
namespace = "extension-namespace"
key = "extension-key"

[[targeting]]
target = "cart.lines.discounts.generate.run"
input_variables = { namespace = "target-namespace", key = "target-key" }

The config.targeting.map callback parameter is renamed configtargeting; it shadowed the outer config, which made the new targeting.input_variables line read as though it were reaching for extension-level configuration.

FunctionExtensionSchema is now exported so the tests can safeParse configurations directly rather than reaching through the spec object (schema is on CreateExtensionSpecType, not on the returned ExtensionSpecification). This follows the UIExtensionSchema precedent in ui_extension.ts. Knip is happy with it, but it is a genuine visibility change worth a reviewer's eye.

⚠️ Shipping order

This must not reach a CLI release before shop/world#1015868 merges and deploys. Until then the Core property does not exist, and a deployed CLI sending input_query_variables on targets[] writes a field the platform drops. Happy to drop the changeset and re-add it at merge time if that's the safer sequencing — say the word.

Out of scope

  • prepare-target rules. Deliberately excluded, mirroring the Core PR: that target does not exist in the codebase yet, so CLI validation would have no server counterpart and would be validating a handle Core rejects as unknown.
  • Detecting a sibling target that needs input_variables but lacks them. Core's per_target_variables mode is all-or-nothing: targets.any?(&:input_query_variables) switches every target to the per-target validator. So adding input_variables to target 0 can make target 1 fail deploy with "Variable definitions are missing" if target 1's query declares GraphQL variables. Catching that locally requires parsing each target's .graphql for variable declarations — worth its own change.

How to test your changes?

pnpm vitest run packages/app/src/cli/models/extensions/specifications/function.test.ts

New coverage: the deploy-payload mapping, plus a describe('input variables placement') block covering rejection with the exact message and path, multiple offending targets (asserting non-offending siblings are left alone), target-level-only, and extension-level-only.

Measuring impact

  • n/a - this doesn't need measurement, e.g. a linter rule or a bug-fix

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've added a changeset if this PR contains user-facing or noteworthy changes
  • I've added tests to cover my changes
  • I've updated the documentation if applicable

🤖 Generated with Claude Code

Input queries have always been per-target (`input_query` on each `[[targeting]]`
entry) while their variables were per-function (`[input.variables]`). shop/world
PR 1015868 closes that asymmetry in Core by adding `input_query_variables` to
`Execution::FunctionTarget`; this is the CLI half.

- Accepts `input_variables` on a `[[targeting]]` entry and forwards it to the
  deploy payload as `input_query_variables.single_json_metafield`, the same
  shape already used at the extension level.
- Rejects mixing extension-level `[input.variables]` with target-level
  `input_variables`, reported per offending target so the error points at the
  same line Core's deploy-time validator would.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the Area: @shopify/app @shopify/app package issues label Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: @shopify/app @shopify/app package issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant