graphql_schema_annotation 0.1.1 copy "graphql_schema_annotation: ^0.1.1" to clipboard
graphql_schema_annotation: ^0.1.1 copied to clipboard

Annotations read by graphql_schema_generator: GraphQL directives, interfaces and scalars, declared on the plain Dart classes the schema is generated from.

GraphQL Schema Annotation #

Build Pub Version Maintainer License Maintenance Platforms

Four annotations read by graphql_schema_generator, which writes a GraphQL schema from the Dart sources of a package.

Start without them. The generator already reads a class as a type, its public instance fields as the fields, an enum as an enum, a sealed class as a union and an abstract class as an interface. Reach for one of these when the schema needs something the Dart has no way of saying.

Annotation What it does Where it goes
@GraphQLDirective Declares the class as a GraphQL directive on a class
@GraphQLScalar Sends a type to a named scalar, such as ID on a class, an extension type or an enum
@GraphQLSkip Keeps a member out of the schema on a field, a getter or a method
@GraphQLInterface Publishes an abstract class a type reaches through extends on a class

Install #

dependencies:
  graphql_schema_annotation: ^0.1.0

dev_dependencies:
  graphql_schema_generator: ^0.1.0

Your models import the annotations, so they go in dependencies. The generator is a command that reads your sources and ships with nothing, so it goes in dev_dependencies.

Directives #

A GraphQL field can carry a directive, @_len_12_ or @auth, and a Dart field has no way of writing one. So here a directive is a class: the class is the declaration, and an instance of it is an application.

import 'package:graphql_schema_annotation/graphql_schema_annotation.dart';

/// The field holds 12 characters forming a Belgian VAT number.
@GraphQLDirective(name: '_len_12_', on: {DirectiveLocation.inputFieldDefinition})
class Len12 {
  const Len12();
}

class CompanyDraft {
  @Len12()
  final String vatNo;

  const CompanyDraft({required this.vatNo});
}

The class becomes the directive line, and the annotated field carries it. The /// comment on the class becomes the description of the directive:

"""The field holds 12 characters forming a Belgian VAT number."""
directive @_len_12_ on INPUT_FIELD_DEFINITION

input CompanyDraftInput {
  vatNo: String! @_len_12_
}

name: is what the schema calls the directive. It is not derived from the class name, so a name no Dart identifier could spell, _len_12_, is yours to write.

Arguments #

Give the class fields and they become the arguments of the directive. Their values come from the call that applies it.

/// Restricts the field to certain roles.
@GraphQLDirective(name: '_restricted_to_', on: {DirectiveLocation.fieldDefinition})
class RestrictedTo {
  final List<Role> role;

  const RestrictedTo({required this.role});
}

class Company {
  @RestrictedTo(role: [Role.staff])
  final String owner;

  const Company({required this.owner});
}
directive @_restricted_to_(role: [Role!]!) on FIELD_DEFINITION

type Company {
  owner: String! @_restricted_to_(role: [staff])
}

A default written in the constructor becomes the default of the argument. An enum used as an argument type reaches the schema on its own, which is where Role above comes from.

Where a directive may go #

on: lists the places the schema allows. Apply the directive anywhere else and the generator stops and names the place, rather than writing a schema no server would accept.

Written in Dart on Reaches
a class emitted as an object type OBJECT
a class emitted as an input type INPUT_OBJECT
a field of either FIELD_DEFINITION or INPUT_FIELD_DEFINITION
a method of a root class FIELD_DEFINITION
a parameter of such a method ARGUMENT_DEFINITION
an abstract class INTERFACE
a sealed class UNION
an enum, or one of its constants ENUM or ENUM_VALUE
a type marked @GraphQLScalar SCALAR

Applying the same directive twice at one place also stops the generator, unless the declaration says repeatable: true.

DirectiveLocation holds the 19 locations the specification defines. Eight of them describe a query document rather than a schema, QUERY and FIELD among them. A directive can declare those, and nothing in Dart can apply them.

Scalars #

@GraphQLScalar says which GraphQL scalar carries a type. An extension type without it reaches the schema as the type underneath, String below, so this is how a field reaches ID.

/// The stock keeping unit a product is stored under.
@GraphQLScalar('ID')
extension type const Sku(String value) {}
type Product {
  sku: ID!
}

Int, Float, String, Boolean and ID are the five the specification defines, and a field reaches them as it is. Any other name is declared in the schema as scalar <name>, and specifiedByUrl: adds @specifiedBy to that declaration.

Skipped members #

@GraphQLSkip keeps a member out of the schema, so it can stay public in Dart without being part of your API.

class Product {
  /// Where the rendered page for this product is cached.
  @GraphQLSkip()
  final String cacheKey;

  const Product({required this.cacheKey});
}

The generator also takes a skip: list of ClassName.memberName in pubspec.yaml, which does the same for a class you cannot annotate. Prefer the annotation on your own code: it follows the member when you rename it, where the list goes stale in silence.

Interfaces #

You will rarely need this one. An abstract class is already an interface, and a class naming it after implements already says so in the schema. Neither needs an annotation.

What inference cannot settle is extends. It means implementation reuse, so the superclass hands its fields to the type and stays out of the schema. @GraphQLInterface is how you ask for it to be published instead.

/// Something the catalogue dates.
@GraphQLInterface()
abstract class Timestamped {
  const Timestamped();

  /// When the record was created.
  DateTime get createdAt;
}

class Product extends Timestamped {
  @override
  final DateTime createdAt;

  const Product({required this.createdAt});
}
interface Timestamped {
  createdAt: DateTime!
}

type Product implements Timestamped {
  createdAt: DateTime!
}

License #

MIT. See LICENSE.

0
likes
160
points
135
downloads

Documentation

API reference

Publisher

verified publishercomapps.be

Weekly Downloads

Annotations read by graphql_schema_generator: GraphQL directives, interfaces and scalars, declared on the plain Dart classes the schema is generated from.

Homepage
Repository (GitHub)
View/report issues

Topics

#graphql #annotations #schema #codegen

License

MIT (license)

Dependencies

meta

More

Packages that depend on graphql_schema_annotation