Skip to content

Generate types for UI extension intents#7342

Draft
JoviDeCroock wants to merge 4 commits intomainfrom
generate-types-for-ui-extension-intents
Draft

Generate types for UI extension intents#7342
JoviDeCroock wants to merge 4 commits intomainfrom
generate-types-for-ui-extension-intents

Conversation

@JoviDeCroock
Copy link
Copy Markdown
Contributor

@JoviDeCroock JoviDeCroock commented Apr 17, 2026

WHY are these changes introduced?

UI extensions can now declare intents — a
declarative way of saying "this target handles the create:application/email
intent" and shipping an input/output/value JSON Schema alongside it.

At runtime the host passes the intent payload to the extension via
shopify.intents.request, and the extension acknowledges it with
shopify.intents.response.ok(data). Without type generation, developers have no
way of knowing the shape of request.data, what request.value contains, or
what response.ok expects — they're back to any territory and have to cross-
reference the schema file by hand.

We already generate types for the related tools concept in the same
shopify.d.ts file. This PR brings intents to feature parity.

WHAT is this pull request doing?

For any UI-extension target that declares [[extensions.targeting.intents]]
entries with a schema file, the CLI now:

  1. Reads each referenced intent schema JSON file.
  2. Validates it against a zod schema (inputSchema required, value and
    outputSchema optional).
  3. Compiles each schema into a named TypeScript interface via
    json-schema-to-typescript, yielding (for e.g. create /
    application/email):
    • CreateApplicationEmailIntentInput
    • CreateApplicationEmailIntentValue
    • CreateApplicationEmailIntentOutput
    • CreateApplicationEmailIntentRequest — the discriminated request shape
      with literal action / type and a typed data / value.
  4. Emits two reusable helpers:
    • ShopifyGeneratedIntentResponse<Data> — the ok(data?: Data) handle.
    • ShopifyGeneratedIntentsApi<Request, ResponseData> — request/response
      pair, plus a ShopifyGeneratedIntentVariants union of every declared
      intent.
  5. Wires the generated types into the module's shopify declaration through a
    new WithGeneratedIntents<T> wrapper that merges them with whatever the
    target's own Api['intents'] already exposes (so base host properties like
    cancel, etc. survive augmentation).

The wrapper composes with the existing WithGeneratedTools<T>:

const shopify: WithGeneratedTools<
  WithGeneratedIntents<
    import('@shopify/ui-extensions/admin.app.intent.render').Api
  >
>;

Duplicate action:type pairs within a target throw an AbortError, matching
the existing behaviour for duplicate tool names. Missing / invalid schema files
emit a warning and skip generation rather than aborting, consistent with how
tools handles bad input.

Intent types are only emitted for the extension's entry-point file, not for any
file it imports (same behaviour as tools).

Edge cases to spot-check:

  • Removing the schema file: the CLI should outputWarn and regenerate
    shopify.d.ts without the intent types (no crash).
  • Duplicating an action:type pair within a single target: the CLI should
    abort with a clear error.
  • Intent schema with a root-level value key: the compiled
    *IntentValue interface should reflect that schema and be wired into
    request.value.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant