Skip to content

Add operation arguments to inject extra params into generated operations#90

Merged
ruudk merged 1 commit into
mainfrom
claude/graphql-operation-hooks-x8zros
Jun 9, 2026
Merged

Add operation arguments to inject extra params into generated operations#90
ruudk merged 1 commit into
mainfrom
claude/graphql-operation-hooks-x8zros

Conversation

@ruudk

@ruudk ruudk commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Some operations need to forward something to the client that is not a GraphQL variable: an actor, a tenant, a correlation or idempotency id. Until now the generated execute()/executeOrThrow() signatures were derived solely from the operation's variables, so there was no way to thread such transport-level context through the generated code.

withOperationArgument() lets you declare an extra, typed parameter that is prepended to the generated execute()/executeOrThrow() methods and forwarded to the client's graphql() call as a named argument (e.g. actor: $actor):

Config::create(...)
    ->withOperationArgument(
        name: 'actor',
        type: Type::object(Actor::class),
        directive: 'requiresActor',
    );

Targeting is flexible:

  • With a directive, the parameter is opt-in: only operations tagged with that marker (e.g. mutation Foo @requiresActor) receive it. Without one, it applies to every operation.
  • operations restricts the argument to specific operation types; it defaults to an empty list, meaning any type.
  • Call it multiple times to inject more than one argument.

The marker directive is a code-generation concern, not part of the server's schema, so it is handled end to end: auto-registered on the schema for the configured operation types (so documents validate and KnownDirectives rejects misuse such as putting it on a field), and stripped from the operation before it is sent to the server. Running --update-schema writes these directive definitions into the schema file.

Components:

  • OperationArgument value object + Config::withOperationArgument()
  • OperationArgumentDirectiveSchemaExtender registers the marker directive(s)
  • OperationArgumentDirectiveRemover strips them before the query is printed
  • Planner resolves the applicable arguments per operation; OperationClassGenerator prepends the parameters and forwards them as named arguments to graphql()

Covered by the tests/OperationArgument fixture (opt-in mutation, opt-in query, untouched query) plus a behavioural test asserting the actor reaches the client, and documented in the README.

Some operations need to forward something to the client that is not a GraphQL
variable: an actor, a tenant, a correlation or idempotency id. Until now the
generated execute()/executeOrThrow() signatures were derived solely from the
operation's variables, so there was no way to thread such transport-level
context through the generated code.

withOperationArgument() lets you declare an extra, typed parameter that is
prepended to the generated execute()/executeOrThrow() methods and forwarded to
the client's graphql() call as a named argument (e.g. actor: $actor):

    Config::create(...)
        ->withOperationArgument(
            name: 'actor',
            type: Type::object(Actor::class),
            directive: 'requiresActor',
        );

Targeting is flexible:

- With a directive, the parameter is opt-in: only operations tagged with that
  marker (e.g. mutation Foo @requiresActor) receive it. Without one, it applies
  to every operation.
- operations restricts the argument to specific operation types; it defaults to
  an empty list, meaning any type.
- Call it multiple times to inject more than one argument.

The marker directive is a code-generation concern, not part of the server's
schema, so it is handled end to end: auto-registered on the schema for the
configured operation types (so documents validate and KnownDirectives rejects
misuse such as putting it on a field), and stripped from the operation before
it is sent to the server. Running --update-schema writes these directive
definitions into the schema file.

Components:

- OperationArgument value object + Config::withOperationArgument()
- OperationArgumentDirectiveSchemaExtender registers the marker directive(s)
- OperationArgumentDirectiveRemover strips them before the query is printed
- Planner resolves the applicable arguments per operation; OperationClassGenerator
  prepends the parameters and forwards them as named arguments to graphql()

Covered by the tests/OperationArgument fixture (opt-in mutation, opt-in query,
untouched query) plus a behavioural test asserting the actor reaches the client,
and documented in the README.
@ruudk ruudk force-pushed the claude/graphql-operation-hooks-x8zros branch from d6a45fc to ca4fb3b Compare June 9, 2026 11:05
@ruudk ruudk changed the title Add operation argument injection via withOperationArgument() Add operation arguments to inject extra params into generated operations Jun 9, 2026
@ruudk ruudk merged commit 5332051 into main Jun 9, 2026
3 checks passed
@ruudk ruudk deleted the claude/graphql-operation-hooks-x8zros branch June 9, 2026 11:06
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