Skip to content

feat: implement sequential stages PoC for plugin output hand-off - #10945

Draft
eddeee888 wants to merge 1 commit into
masterfrom
claude/inspiring-keller-f02kf4
Draft

feat: implement sequential stages PoC for plugin output hand-off#10945
eddeee888 wants to merge 1 commit into
masterfrom
claude/inspiring-keller-f02kf4

Conversation

@eddeee888

Copy link
Copy Markdown
Collaborator

Description

This PR implements a proof-of-concept for RFC #10943 ("Sequential Execution & Output Hand-off Between GraphQL Codegen Plugins/Presets"), specifically Option 1: Sequential Stages.

What Changed

The implementation allows generates entries to be defined as an array of stage objects (instead of just a single ConfiguredOutput), where:

  1. Stages execute sequentially (not in parallel) against the same output file
  2. Meta hand-off between stages: Each stage's plugins can produce meta that is passed to the next stage via pluginContext.previousStageMeta, keyed by plugin name
  3. Content concatenation: Output from each stage is appended to the same file in order

Key Modifications

  • packages/graphql-codegen-cli/src/codegen.ts: Added generatesStages collection and sequential stage execution logic with proper schema/document loading and meta threading
  • packages/utils/plugins-helpers/src/helpers.ts: Added isSequentialStagesArray() type guard to distinguish sequential stages from plugin arrays, and updated normalizeOutputParam() to handle stages
  • packages/utils/plugins-helpers/src/types.ts:
    • Added SequentialStages type definition
    • Added onPluginOutput callback to GenerateOptions for observing plugin output and meta
    • Updated generates config to accept SequentialStages
  • packages/graphql-codegen-core/src/codegen.ts: Added onPluginOutput callback invocation to expose plugin output to callers

Testing

Added comprehensive test suite (sequential-stages.spec.ts) with:

  • Test verifying stages run in order and content is concatenated
  • Test verifying meta hand-off between stages via pluginContext.previousStageMeta
  • Test verifying backward compatibility with single-stage (non-array) generates entries

Added fixture plugins (sequential-stage-1.js, sequential-stage-2.js) demonstrating the meta hand-off pattern.

Backward Compatibility

✅ Fully backward compatible - existing single-stage generates entries continue to work as before. The new array syntax is opt-in.

Related #10943

https://claude.ai/code/session_01Xva2iGJ4Xw5GYGAHxyCEra

Small, additive proof-of-concept for the RFC's recommended "Sequential
Stages" design: a `generates` entry can be an array of `{ plugins }` /
`{ preset }` stage objects that run one after another against the same
output path, instead of only the existing plugins-within-one-stage
parallel execution.

- `Types.SequentialStages` (`ConfiguredOutput[]`) is a new accepted shape
  for `generates[path]`, alongside the existing `ConfiguredOutput` and
  `ConfiguredPlugin[]` shorthand. `isSequentialStagesArray()` tells the two
  array shapes apart by checking for a `plugins`/`preset` key on each item.
- `@graphql-codegen/core`'s `codegen()` gains an optional
  `onPluginOutput` callback, so a caller can observe each plugin's raw
  `Types.PluginOutput` (including `meta`) without changing its existing
  `Promise<string>` return type.
- The CLI (`executeCodegen`) runs a stages array through a dedicated code
  path: stages execute sequentially (not via `Promise.all`), a stage's
  `meta` (collected via `onPluginOutput`) is threaded into the next
  stage's `pluginContext.previousStageMeta`, and stage outputs are
  concatenated into one `FileOutput`.
- `normalizeOutputParam()` also accepts a stages array (merging each
  stage's `schema`/`documents`/`watchPattern`) so existing callers like
  watch-mode pattern matching don't break.

Scope/limitations of this PoC (by design, to keep it small):
- No per-stage `schema`/`documents` overrides - stages share the root
  `schema`/`documents`.
- No `documentTransforms`/hooks/`contentComparison` per stage.
- `{ preset }` stages are accepted by the type/detection but not executed
  by the CLI's stages loop yet.

Demonstrated end-to-end in
`packages/graphql-codegen-cli/tests/sequential-stages.spec.ts` using two
toy plugins standing in for `typescript` -> `typescript-resolvers`: the
second stage's plugin reads the first stage's `meta`
(`pluginContext.previousStageMeta`) instead of re-deriving it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xva2iGJ4Xw5GYGAHxyCEra
@changeset-bot

changeset-bot Bot commented Sep 12, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: dc42bcc

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

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.

2 participants