Last updated:
0 purchases
galileo graphql
Installation
Usage
Subscriptions
Integration with Galileo Services
Documenting API's
Deprecated - Mirrors Usage
A complete implementation of the official
GraphQL specification - these
are the Galileo framework-specific
bindings.
The goal of this project is to provide to server-side
users of Dart an alternative to REST API's. package:galileo_graphql, which, when combined with the allows
server-side Dart users to build backends with GraphQL and
virtually any database imaginable.
Installation #
To install package:galileo_graphql, add the following to your
pubspec.yaml:
dependencies:
galileo_framework: ^2.0.0-alpha
galileo_graphql: ^1.0.0-alpha
copied to clipboard
Usage #
Using this package is very similar to GraphQL.js - you define
a schema, and then mount graphQLHttp in your router to start
serving. This implementation supports GraphQL features like
introspection, so you can play around with graphiql as well!
Firstly, define your schema. A GraphQL schema contains an
object type that defines all querying operations that can be
applied to the backend.
A GraphQL schema may also have a mutation object type,
which defines operations that change the backend's state, and
optionally a subscription type, which defines real-time
interactions (coming soon!).
You can use the convertDartType helper to wrap your existing
Model/PODO classes, and make GraphQL aware of them without duplicated
effort.
import 'package:galileo_framework/galileo_framework.dart';
import 'package:galileo_graphql/galileo_graphql.dart';
import 'package:graphql_schema/graphql_schema.dart';
import 'package:graphql_server/graphql_server.dart';
import 'package:graphql_server/mirrors.dart';
Future configureServer(Galileo app) async {
var queryType = objectType(
'Query',
description: 'A simple API that manages your to-do list.',
fields: [
field(
'todos',
listOf(convertDartType(Todo).nonNullable()),
resolve: resolveViaServiceIndex(todoService),
),
field(
'todo',
convertDartType(Todo),
resolve: resolveViaServiceRead(todoService),
inputs: [
GraphQLFieldInput('id', graphQLId.nonNullable()),
],
),
],
);
var mutationType = objectType(
'Mutation',
description: 'Modify the to-do list.',
fields: [
field(
'create',
graphQLString,
),
],
);
var schema = graphQLSchema(
queryType: queryType,
mutationType: mutationType,
);
}
copied to clipboard
After you've created your GraphQLSchema, you just need to
wrap in a call to graphQLHttp, a request handler that responds
to GraphQL.
In development, it's also highly recommended to mount the
graphiQL handler, which serves GraphQL's official visual
interface, for easy querying and feedback.
app.all('/graphql', graphQLHttp(GraphQL(schema)));
app.get('/graphiql', graphiQL());
copied to clipboard
All that's left now is just to start the server!
var server = await http.startServer('127.0.0.1', 3000);
var uri =
Uri(scheme: 'http', host: server.address.address, port: server.port);
var graphiqlUri = uri.replace(path: 'graphiql');
print('Listening at $uri');
print('Access graphiql at $graphiqlUri');
copied to clipboard
Visit your /graphiql endpoint, and you'll see the graphiql
UI, ready-to-go!
Now you're ready to build a GraphQL API!
Subscriptions #
Example:
https://github.com/galileo-dart/graphql/blob/master/galileo_graphql/example/subscription.dart
In GraphQL, as of the June 2018 spec, clients can subscribe to streams of events
from the server. In your schema, all you need to do is return a Stream from a resolve
callback, rather than a plain object:
var postAdded = postService.afterCreated
.asStream()
.map((e) => {'postAdded': e.result})
.asBroadcastStream();
var schema = graphQLSchema(
// ...
subscriptionType: objectType(
'Subscription',
fields: [
field('postAdded', postType, resolve: (_, __) => postAdded),
],
),
);
copied to clipboard
By default, graphQLHttp has no support for subscriptions, because regular
HTTP requests are stateless, and are not ideal for continuous data pushing.
You can add your own handler:
graphQLHttp(graphQL, onSubscription: (req, res, stream) {
// Do something with the stream here. It's up to you.
});
copied to clipboard
There is, however, graphQLWS, which implements Apollo's
subscriptions-transport-ws protocol:
app.get('/subscriptions', graphQLWS(GraphQL(schema)));
copied to clipboard
You can then use existing JavaScript clients to handle subscriptions.
The graphiQL handler also supports using subscriptions. In the following snippet, the
necessary scripts will be added to the rendered page, so that the subscriptions-transport-ws
client can be used by GraphiQL:
app.get('/graphiql',
graphiQL(subscriptionsEndpoint: 'ws://localhost:3000/subscriptions'));
copied to clipboard
NOTE: Apollo's spec for the aforementioned protocol is very far outdated, and completely inaccurate,
See this issue for more:
https://github.com/apollographql/subscriptions-transport-ws/issues/551
Using Services #
What would Galileo be without services? For those unfamiliar - in Galileo,
Service is a base class that implements CRUD functionality, and serves
as the database interface within an Galileo application. They are well-suited
for NoSQL or other databases without a schema (they can be used with
SQL, but that's not their primary focus).
package:galileo_graphql has functionality to resolve fields by interacting with
services.
Consider our previous example, and note the calls to
resolveViaServiceIndex and resolveViaServiceRead:
var queryType = objectType(
'Query',
description: 'A simple API that manages your to-do list.',
fields: [
field(
'todos',
listOf(convertDartType(Todo).nonNullable()),
resolve: resolveViaServiceIndex(todoService),
),
field(
'todo',
convertDartType(Todo),
resolve: resolveViaServiceRead(todoService),
inputs: [
GraphQLFieldInput('id', graphQLId.nonNullable()),
],
),
],
);
copied to clipboard
In all, there are:
resolveViaServiceIndex
resolveViaServiceFindOne
resolveViaServiceRead
resolveViaServiceCreate
resolveViaServiceModify
resolveViaServiceUpdate
resolveViaServiceRemove
As one might imagine, using these convenience helpers makes
it much quicker to implement CRUD functionality in a GraphQL
API.
Documentation #
Using package:graphql_generator, you can generate GraphQL schemas for concrete Dart
types:
configureServer(Galileo app) async {
var schema = graphQLSchema(
queryType: objectType('Query', fields: [
field('todos', listOf(todoGraphQLType), resolve: (_, __) => ...)
]);
);
}
@graphQLClass
class Todo {
String text;
@GraphQLDocumentation(description: 'Whether this item is complete.')
bool isComplete;
}
copied to clipboard
For more documentation, see:
https://pub.dartlang.org/packages/graphql_generator
Mirrors #
NOTE: Mirrors support is deprecated, and will not be updated further.
The convertDartType function can automatically read the documentation
from a type like the following:
@GraphQLDocumentation(description: 'Any object with a .text (String) property.')
abstract class HasText {
String get text;
}
@serializable
@GraphQLDocumentation(
description: 'A task that might not be completed yet. **Yay! Markdown!**')
class Todo extends Model implements HasText {
String text;
@GraphQLDocumentation(deprecationReason: 'Use `completion_status` instead.')
bool completed;
CompletionStatus completionStatus;
Todo({this.text, this.completed, this.completionStatus});
}
@GraphQLDocumentation(description: 'The completion status of a to-do item.')
enum CompletionStatus { COMPLETE, INCOMPLETE }
copied to clipboard
You can also manually provide documentation for
parameters and endpoints, via a description parameter on almost
all related functions.
See package:graphql_schema
for more documentation.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.