First, I've added my directive:

<?php

namespace App\GraphQL\Directives;

use Closure;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Schema\Directives\BaseDirective;
use Nuwave\Lighthouse\Schema\Values\FieldValue;
use Nuwave\Lighthouse\Support\Contracts\FieldMiddleware;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
use App\GraphQL\Grid\Types;

class MyDirective extends BaseDirective implements FieldMiddleware {

    public static function definition(): Directive
    {
        return new Types\Directive();
    }

    public function handleField(FieldValue $fieldValue, Closure $next)
    {
        $resolver = $fieldValue->getResolver();
        return $next(
            $fieldValue->setResolver(function (
                $root,
                array $args,
                GraphQLContext $context,
                ResolveInfo $resolveInfo
            ) use ($resolver) {
                info("Middleware");
                return $resolver($root, $args, $context, $resolveInfo);
            })
        );
    }
}

And defined my query:

extend type Query {
    myQuery( arg1: String! @fieldDirective1, arg2: String! @fieldDirective2 ): [MyType] @paginate @myDirective
}

I had two arguments with field directives and @paginate directive.

To each directive, I've added info a function with the class name. In case of a trace is added at the beginning and just before the end (when a query is resolved).

First, run:

MyDirective
Paginate Begin
FieldDirective1
FieldDirective2
Paginate End

Paginate directive Resolve field arguments in the middle. I need to add my middleware after FieldDirective2 and before Paginate End.

A little change in the code of MyDirective

$result = $resolver($root, $args, $context, $resolveInfo);
info("middleware");
return $result;

Result as expected:

Paginate Begin
FieldDirective1
FieldDirective2
Paginate End
MyDirective

Paginate directive runs field directives. I'm not able to catch the moment with FieldMiddleware. I need to be here:

// PaginateDirective.php
$query = $resolveInfo->argumentSet->enhanceBuilder($query, $this->directiveArgValue("scopes", []));

Add bogus argument

I've changed my directive resolver to inject additional arguments into arguments stored in $resolveInfo

class MyDirective extends BaseDirective implements
    FieldManipulator,
    DefinedDirective,
    FieldMiddleware,
    \Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective
{
    public function handleField(FieldValue $fieldValue, Closure $next)
    {
        $resolver = $fieldValue->getResolver();
        return $next(
            $fieldValue->setResolver(function (
                $root,
                array $args,
                GraphQLContext $context,
                ResolveInfo $resolveInfo
            ) use ($resolver) {
                $argument = new \Nuwave\Lighthouse\Execution\Arguments\Argument();
                $argument->value = true;
                $argument->type = \GraphQL\Type\Definition\Type::boolean();
                $argument->directives->push($this);
                $resolveInfo->argumentSet->arguments["my_directive_arg"] = $argument;
                info("MyDirective Begin");
                $result = $resolver($root, $args, $context, $resolveInfo);
                info("MyDirective End");
                return $result;
            })
        );
    }


    public function handleBuilder($builder, $filters)
    {
        info("MyDirective Bulder");
        return $builder;
    }
}

And result:

MyDirective Begin
Pagination Begin
FieldDirective1
FieldDirective2
MyDirective Bulder
Paginate End
MyDirective End

This gives me the ability to modify eloquent queries just before execute knowing all conditions made by argument directives.