# Différences avec TypeGraphQL
Ce framework est basé sur le même principe que TypeGraphQL, cependant il vient corriger et changer certains modes de fonctionnement qui peuvent être parfois être restrictifs.
# API
Le principal changement se trouve dans le fait que ce module est séparé en deux modules distincts au lieu d'un seul plus lourd, ce qui permet également de vous fournir une API de composition nommée graphql-composer
.
# Décorateurs de champs
Il y'a également des décorateurs supplémentaires tel que @ObjectField
@InputField
et @InterfaceField
, qui permettent de paramétrer un champ pour un certain type GraphQL de la class
.
# ArgsType
Il n'a pas de type ArgsType
, car n'existant pas dans GraphQL. Ceci peut donc se trouver être peu intuitif. En contre partie c'est du côté de la déclaration des arguments d'une query que l'on va pouvoir utiliser tout un type input pour déclarer l'ensemble des arguments avec le décorateur @Args
(tout comme ArgsType
):
@InputType()
class User {
@Field()
username: string;
@Field()
email: string;
}
@Resolver()
class Resolver {
@Query()
getUser(@Args() user: User): Boolean {
// ...
}
}
ce qui donne en SDL:
input User {
username: String
email: String
}
type Query {
getUser(username: String, email: String): Bool
}
# Nullable
ou Requis
La définition des types nullable et requis est très restrictive avec TypeGraphQL, ce qui a été réglé ici grâce à deux fonctions: Nullable(type: Type)
(N(type: Type)
) et Required(type: Type)
(R(type: Type)
).
Prenons l'exemple de la déclaration d'un tableau avec un contenu interne requis (c'est en étant explicite, vous pouvez évidemment préciser si vos types sont nullable ou requis par défaut):
@InputType()
class User {
@Field(type => [Required(String)])
// or shorter with @Field(type => [R(String)])
username: string[];
@Field(type => Nullable([Required(String)]))
// or shorter with @Field(type => N([R(String)]))
email?: string[];
}
Il n'est pas possible de faire ceci avec TypeGraphQL pour le moment, car le paramètre nullable est appliqué à l'ensemble de @Field
# Les subscriptions
Le décorateur de @Subscription
fonctionne de manière différente, n'étant pas satisfait du fait d'imposer grahphql-subcriptions
comme gestionnaire de subscriptions (le fonctionnement des subscription n'est donc pas très libre pour le développeur) et de ne pas laisser le choix au développeur, j'ai opté pour une manière un peu différente.
Ces deux choix se défendent, mais je préfère être libre de gérer mon mécanisme de subscription via mon application, de plus que ça ne rajoute pas énormément de complexité
Avec graphql-composer-decorators
import { PubSub } from "graphql-subcriptions";
const pubsub = new PubSub();
@Resolver() class Resolver {
@Subscription({
subscription: (args) => pubsub.asyncIterator("NOTIFICATION"),
})
mySubscription(): Boolean {
// ...
}
@Query()
trigger(): Boolean {
pubsub.publish("NOTIFICATION");
// ...
}
}
Avec TypeGraphQL:
@Resolver()
class Resolver {
@Subscription({ topics: "NOTIFICATION" })
mySubscription() {
// ...
}
@Query()
trigger(@PubSub() pubSub): Boolean {
pubsub.publish("NOTIFICATION");
// ...
}
}
# Le context
Les arguments spécifiques au context GraphQL (infos, source, root, etc...) sont injectés via des décorateurs avec TypeGraphQL (@Root
, @Source
, @Infos
, ...) ce qui peut alourdir énormément la déclaration de vos méthodes. Ici nous avons opté l'injection d'un objet contenant l'ensemble de ces informations après vos arguments:
import { Context } from "graphql-composer";
@Resolver()
class Resolver {
@Query()
trigger(
@Arg("username") username: string,
context: Context, // Injected here (after all your arguments)
): Boolean {
// ...
}
}
← Commencer ObjectType →