diff --git a/package.json b/package.json index 7c85a2b9b..f9d1efc3b 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,10 @@ "classnames": "^2.2.5", "cookie-parser": "^1.4.3", "core-js": "^2.4.1", + "dataloader": "^1.3.0", + "express": "^4.15.2", + "express-graphql": "^0.6.4", + "dataloader": "^1.3.0", "express": "^4.15.3", "express-graphql": "^0.6.6", "express-jwt": "^5.3.0", diff --git a/src/data/loaders/index.js b/src/data/loaders/index.js new file mode 100644 index 000000000..907d222bb --- /dev/null +++ b/src/data/loaders/index.js @@ -0,0 +1,10 @@ +import personLoader from './personLoader'; + +// All your dataloaders +const allLoaders = { + ...personLoader, +}; + +export default function loaders() { + return allLoaders; +} diff --git a/src/data/loaders/personLoader.js b/src/data/loaders/personLoader.js new file mode 100644 index 000000000..c875b1d32 --- /dev/null +++ b/src/data/loaders/personLoader.js @@ -0,0 +1,6 @@ +import DataLoader from 'dataloader'; +import getPerson from '../queries/getPerson'; + +export default { + personLoader: new DataLoader(people => Promise.all(people.map(_id => getPerson(_id)))), +}; diff --git a/src/data/queries/getAllPeople.js b/src/data/queries/getAllPeople.js new file mode 100644 index 000000000..4392a8d52 --- /dev/null +++ b/src/data/queries/getAllPeople.js @@ -0,0 +1,23 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-present Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +import { GraphQLList as List } from 'graphql'; +import PersonType from '../types/PersonType'; +import allPeople from '../seed/people'; + +/* eslint-disable no-underscore-dangle */ +const getAllPeople = { + type: new List(PersonType), + resolve: async (req, args, { loaders }) => { + const people = allPeople.map((person => person._id)); + return loaders.personLoader.loadMany(people); + }, +}; + +export default getAllPeople; diff --git a/src/data/queries/getPerson.js b/src/data/queries/getPerson.js new file mode 100644 index 000000000..0209d0def --- /dev/null +++ b/src/data/queries/getPerson.js @@ -0,0 +1,22 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-present Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +import allPeople from '../seed/people'; + +/* eslint-disable no-underscore-dangle */ +export default function getPerson(_id) { + let response = null; + try { + response = allPeople.find(people => people._id === _id); + } catch (err) { + /* eslint-disable no-console */ + console.log('getPerson err', err); + } + return response; +} diff --git a/src/data/schema.js b/src/data/schema.js index 6156b07cd..1dc2b36d2 100644 --- a/src/data/schema.js +++ b/src/data/schema.js @@ -14,6 +14,7 @@ import { import me from './queries/me'; import news from './queries/news'; +import people from './queries/getAllPeople'; const schema = new Schema({ query: new ObjectType({ @@ -21,6 +22,7 @@ const schema = new Schema({ fields: { me, news, + people, }, }), }); diff --git a/src/data/seed/people.js b/src/data/seed/people.js new file mode 100644 index 000000000..ddeb6e3cc --- /dev/null +++ b/src/data/seed/people.js @@ -0,0 +1,63 @@ +export default [ + { + _id: 'person_1', + name: 'Davey Edwards', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_2', + name: 'Konstantin Tarkus', + friends: ['person_1', 'person_2', 'person_3', 'person_8', 'person_9', 'person_9', 'person_10', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_3', + name: 'Lee Byron', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_4', + name: 'Laney Kuenzel', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_5', + name: 'Max Stoiber', + friends: ['person_1', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_6', + name: 'Jing Chen', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10'], + }, { + _id: 'person_7', + name: 'Tyler McGinnis', + friends: ['person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_8', + name: 'Ryan Florence', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_9', + name: 'Michael Jackson', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_10', + name: 'Dan Abramov', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_11', + name: 'Tom Occhino', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_9', 'person_9', 'person_10', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_12', + name: 'Pete Hunt', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_11', 'person_12', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_13', + name: 'Joe Savona', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_14', 'person_15'], + }, { + _id: 'person_14', + name: 'Lin Clark', + friends: ['person_1', 'person_2', 'person_3', 'person_4', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_13', 'person_14', 'person_15'], + }, { + _id: 'person_15', + name: 'Dan Schafer', + friends: ['person_1', 'person_2', 'person_5', 'person_6', 'person_7', 'person_8', 'person_9', 'person_9', 'person_10', 'person_13', 'person_14', 'person_15'], + }, +]; diff --git a/src/data/types/PersonType.js b/src/data/types/PersonType.js new file mode 100644 index 000000000..9e7f85c1e --- /dev/null +++ b/src/data/types/PersonType.js @@ -0,0 +1,27 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-present Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +import { + GraphQLObjectType as ObjectType, + GraphQLString as StringType, + GraphQLList as List, +} from 'graphql'; + +const PersonType = new ObjectType({ + name: 'Person', + fields: () => ({ + name: { type: StringType }, + friends: { + type: new List(PersonType), + resolve: (person, args, { loaders }) => loaders.personLoader.loadMany(person.friends), + }, + }), +}); + +export default PersonType; diff --git a/src/server.js b/src/server.js index 1dad579cb..7fb5c6950 100644 --- a/src/server.js +++ b/src/server.js @@ -28,6 +28,7 @@ import models from './data/models'; import schema from './data/schema'; import assets from './assets.json'; // eslint-disable-line import/no-unresolved import config from './config'; +import loaders from './data/loaders'; const app = express(); @@ -90,6 +91,9 @@ app.use('/graphql', expressGraphQL(req => ({ graphiql: __DEV__, rootValue: { request: req }, pretty: __DEV__, + context: { + loaders: loaders(), + }, }))); // diff --git a/yarn.lock b/yarn.lock index 561d40fbf..93601ba6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2005,6 +2005,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +dataloader@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-1.3.0.tgz#6fec5be4b30a712e4afd30b86b4334566b97673b" + date-fns@^1.27.2: version "1.28.5" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.5.tgz#257cfc45d322df45ef5658665967ee841cd73faf"