platform/example_star_wars/lib/star_wars.dart

150 lines
4.6 KiB
Dart
Raw Normal View History

import 'dart:async';
2018-08-04 15:01:49 +00:00
import 'dart:math';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_graphql/angel_graphql.dart';
import 'package:graphql_schema/graphql_schema.dart';
import 'package:graphql_server/graphql_server.dart';
import 'src/models/models.dart';
Future configureServer(Angel app) async {
// Create standard Angel services. Note that these will also *automatically* be
// exposed via a REST API as well.
2019-03-29 03:37:56 +00:00
var droidService = app.use('/api/droids', MapService());
var humansService = app.use('/api/humans', MapService());
var starshipService = app.use('/api/starships', MapService());
2019-03-29 01:33:21 +00:00
var rnd = Random();
// Create the GraphQL schema.
2019-03-29 03:37:56 +00:00
// `package:graphql_generator` has generated schemas for some of our
// classes.
2018-08-04 19:18:53 +00:00
// A Hero can be either a Droid or Human; create a union type that represents this.
2019-03-29 03:37:56 +00:00
var heroType = GraphQLUnionType('Hero', [droidGraphQLType, humanGraphQLType]);
// Create the query type.
//
// Use the `resolveViaServiceIndex` helper to load data directly from an
// Angel service.
2018-08-04 15:01:49 +00:00
var queryType = objectType(
'StarWarsQuery',
description: 'A long time ago, in a galaxy far, far away...',
fields: [
field(
'droids',
2019-03-29 03:37:56 +00:00
listOf(droidGraphQLType.nonNullable()),
2018-08-04 19:18:53 +00:00
description: 'All droids in the known galaxy.',
2018-08-04 15:01:49 +00:00
resolve: resolveViaServiceIndex(droidService),
),
field(
'humans',
2019-03-29 03:37:56 +00:00
listOf(humanGraphQLType.nonNullable()),
2018-08-04 19:18:53 +00:00
description: 'All humans in the known galaxy.',
2018-08-04 15:01:49 +00:00
resolve: resolveViaServiceIndex(humansService),
),
field(
'starships',
2019-03-29 03:37:56 +00:00
listOf(starshipGraphQLType.nonNullable()),
2018-08-04 19:18:53 +00:00
description: 'All starships in the known galaxy.',
2018-08-04 15:01:49 +00:00
resolve: resolveViaServiceIndex(starshipService),
),
field(
'hero',
2018-08-04 19:18:53 +00:00
heroType,
description:
'Finds a random hero within the known galaxy, whether a Droid or Human.',
inputs: [
2019-03-29 03:37:56 +00:00
GraphQLFieldInput('ep', episodeGraphQLType),
2018-08-04 19:18:53 +00:00
],
resolve: randomHeroResolver(droidService, humansService, rnd),
),
],
);
// Convert our object types to input objects, so that they can be passed to
// mutations.
2019-03-29 03:37:56 +00:00
var humanChangesType = humanGraphQLType.toInputObject('HumanChanges');
2018-08-04 19:18:53 +00:00
// Create the mutation type.
var mutationType = objectType(
'StarWarsMutation',
fields: [
// We'll use the `modify_human` mutation to modify a human in the database.
field(
'modify_human',
2019-03-29 03:37:56 +00:00
humanGraphQLType.nonNullable(),
2018-08-04 19:18:53 +00:00
description: 'Modifies a human in the database.',
inputs: [
2019-03-29 01:33:21 +00:00
GraphQLFieldInput('id', graphQLId.nonNullable()),
GraphQLFieldInput('data', humanChangesType.nonNullable()),
2018-08-04 15:12:26 +00:00
],
2018-08-04 19:18:53 +00:00
resolve: resolveViaServiceModify(humansService),
2018-08-04 15:01:49 +00:00
),
],
);
// Finally, create the schema.
2018-08-04 19:18:53 +00:00
var schema = graphQLSchema(
queryType: queryType,
mutationType: mutationType,
);
// Next, create a GraphQL object, which will be passed to `graphQLHttp`, and
// used to mount a spec-compliant GraphQL endpoint on the server.
2019-03-29 01:33:21 +00:00
var graphQL = GraphQL(schema);
// Mount the GraphQL endpoint.
app.all('/graphql', graphQLHttp(graphQL));
// In development, we'll want to mount GraphiQL, for easy management of the database.
if (!app.isProduction) {
app.get('/graphiql', graphiQL());
}
2018-08-04 15:01:49 +00:00
// Seed the database.
var leia = await humansService.create({
'name': 'Leia Organa',
'appears_in': ['NEWHOPE', 'EMPIRE', 'JEDI'],
'total_credits': 520,
});
2018-08-04 15:12:26 +00:00
var lando = await humansService.create({
'name': 'Lando Calrissian',
'appears_in': ['EMPIRE', 'JEDI'],
'total_credits': 525430,
});
2018-08-04 15:01:49 +00:00
var hanSolo = await humansService.create({
'name': 'Han Solo',
'appears_in': ['NEWHOPE', 'EMPIRE', 'JEDI'],
'total_credits': 23,
2018-08-04 15:12:26 +00:00
'friends': [leia, lando],
2018-08-04 15:01:49 +00:00
});
2018-08-04 19:18:53 +00:00
// Luke, of course.
await humansService.create({
2018-08-04 15:01:49 +00:00
'name': 'Luke Skywalker',
'appears_in': ['NEWHOPE', 'EMPIRE', 'JEDI'],
'total_credits': 682,
2018-08-04 15:12:26 +00:00
'friends': [leia, hanSolo, lando],
2018-08-04 15:01:49 +00:00
});
}
2018-08-04 19:18:53 +00:00
GraphQLFieldResolver randomHeroResolver(
Service droidService, Service humansService, Random rnd) {
return (_, args) async {
var allHeroes = [];
2019-03-29 01:33:21 +00:00
var allDroids = await droidService.index();
var allHumans = await humansService.index();
2018-08-04 19:18:53 +00:00
allHeroes..addAll(allDroids)..addAll(allHumans);
// Ignore the annoying cast here, hopefully Dart 2 fixes cases like this
allHeroes = allHeroes
.where((m) =>
!args.containsKey('ep') ||
(m['appears_in'].contains(args['ep']) as bool))
.toList();
return allHeroes.isEmpty ? null : allHeroes[rnd.nextInt(allHeroes.length)];
};
2019-03-29 01:33:21 +00:00
}