One missing part needed by the community to provide external directives is a way to configure the directive.
Here is a draft of the API to provide configuration.
The Directive classes won't extend any tartiflette abstract classes. Instead, you will have to implement the methods you want to support depending on the feature you want to compliant with. (see above regarding the feature set)
from
from tartiflette.directive import Directive, CommonDirective
@Directive("myDirective")
class MyDirective(CommonDirective):
pass
to
from tartiflette.directive import Directive
@Directive("myDirective")
class MyDirective:
pass
This is currently impossible to configure a directive/scalar (pass configuration as API Key, URL etc ...). The directives are a set of static methods (the same behavior is applied on every engine contained in your application).
The Tartiflette DNA is to provide as much as possible an extensible Engine. We decided to base our extensibility on the Directive feature of the GraphQL Specification. It will allow the developers to hook some behaviors at different stages (build and execution time) of the Engine.
Here are some interesting features which could be created:
- Directive to apply JSON Schema validation on
input
types. - Directive to add monitoring on specific fields
- Directive to apply access rules on fields (e.g
@auth
) with dynamic introspection which will allow the developer to hide the fields from the introspection. - Directive to map the resolution of a field dirrectly to the result of an AWS Lambda / GCP Function
and so one... let your imagination take you away.
engine = Engine(
sdl,
modules=[
"yourapp.query_resolvers",
"yourapp.mutation_resolvers",
{
"name": "tartiflette_external_lib",
"config": {
"your": "configuration",
"foo": {
"bar": "baz"
}
}
}
]
)
Based on the current modules
property (which currently allow only string), add a new kind of entry with that shape.
{
"name": "string",
"config": "dict"
}
This configuration will helps the tartiflette users to configure the library third party librarythey want to use.
For the Tartiflette developers, they will have to handle this configuration within their packages.
The idea is to give ability to the tartiflette developers to provide Tartiflette objects (directives, scalars, resolvers and so on) to the community, easily.
Package name: tartiflette-directive-validators-jsonschema
Package main module name: tartiflette_directive_validators_jsonschema
The Engine
will guess the method named bake(schema_name: str, config: dict)
at the root level of the module.
e.g ./tartiflette_directive_validators_jsonschema/init.py
from tartiflette import Directive
from tartiflette_directive_validators_jsonschema.validate_by_ref import ValidateByRef
async def bake(schema_name: str, config: dict) -> str:
sdl = """
directive @validateByRef(
ref: String!
) on ARGUMENT_DEFINITION
"""
Directive("validateByRef", schema_name=schema_name)(ValidateByRef(config))
return sdl
e.g ./tartiflette_directive_validators_jsonschema/validate_by_ref.py
class ValidateByRef:
def __init__(self, config):
# API Key ...
# File path ...
pass
async def on_argument_execution(
self,
directive_args: Dict[str, Any],
next_directive: Callable,
argument_definition: "GraphQLArgument",
args: Dict[str, Any],
ctx: Optional[Dict[str, Any]],
info: "Info",
) -> Any:
pass