├── .gitignore
├── DateTimeTypeDef.js
├── package.js
├── server.js
├── DateTimeResolver.js
├── client.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 |
--------------------------------------------------------------------------------
/DateTimeTypeDef.js:
--------------------------------------------------------------------------------
1 | export const DateTimeTypeDef = `
2 | scalar DateTime
3 |
4 | type Now {
5 | dateTime: DateTime
6 | }
7 |
8 | type Query {
9 | now: Now
10 | }
11 | `;
12 |
--------------------------------------------------------------------------------
/package.js:
--------------------------------------------------------------------------------
1 | Package.describe({
2 | name: 'quave:graphql',
3 | version: '1.0.0',
4 | summary: 'Utility package to create GraphQL setup in a standard way',
5 | git: 'https://github.com/quavedev/graphql',
6 | });
7 |
8 | Package.onUse(function(api) {
9 | api.versionsFrom('1.10.1');
10 | api.use('ecmascript');
11 | api.use('swydo:ddp-apollo@3.0.0', 'server');
12 |
13 | api.mainModule('server.js', 'server');
14 | api.mainModule('client.js', 'client');
15 | });
16 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | import {setup} from 'meteor/swydo:ddp-apollo';
2 |
3 | import {makeExecutableSchema} from 'graphql-tools';
4 | import {getSchema, load} from 'graphql-load';
5 |
6 | const defaultLog = e => console.error('GraphQL server error', e);
7 |
8 | export const startGraphQLServer = ({typeDefs, resolvers, log}) => {
9 | load({
10 | typeDefs,
11 | resolvers,
12 | });
13 | const schema = makeExecutableSchema({
14 | ...getSchema(),
15 | logger: { log: log || defaultLog },
16 | });
17 | setup({schema});
18 | };
19 |
--------------------------------------------------------------------------------
/DateTimeResolver.js:
--------------------------------------------------------------------------------
1 | export const DateTimeResolver = {
2 | DateTime:
3 | {
4 | __parseValue(value) {
5 | return new Date(value); // value from the client
6 | },
7 | __serialize(value) {
8 | return value.getTime(); // value sent to the client
9 | },
10 | __parseLiteral(ast) {
11 | // eslint-disable-next-line no-undef
12 | if (ast.kind === Kind.INT) {
13 | return parseInt(ast.value, 10); // ast value is always in string format
14 | }
15 | return null;
16 | },
17 | },
18 | Query: {
19 | async now() {
20 | return {
21 | dateTime: new Date()
22 | };
23 | },
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/client.js:
--------------------------------------------------------------------------------
1 | import {InMemoryCache} from 'apollo-cache-inmemory';
2 | import ApolloClient from 'apollo-client';
3 | import {onError} from 'apollo-link-error';
4 | import {DDPLink} from 'apollo-link-ddp';
5 |
6 | const link = onError(({graphQLErrors, networkError}) => {
7 | if (graphQLErrors) {
8 | graphQLErrors.map(({message, locations, path, ...rest}) =>
9 | console.error(
10 | `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
11 | rest
12 | )
13 | );
14 | }
15 |
16 | if (networkError) console.error('[Network error]: ', networkError);
17 | });
18 |
19 | export const startGraphQLClient = ({connectToDevTools = false} = {}) => new ApolloClient({
20 | link: link.concat(new DDPLink()),
21 | cache: new InMemoryCache(),
22 | connectToDevTools,
23 | });
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # quave:graphql
2 |
3 | `quave:graphql` is a Meteor package that allows you to create your GraphQL server and client in a standard way.
4 |
5 | ## Why
6 | Every application that wants to use GraphQL needs to connect some packages and some npm modules. Also need:
7 | - Declare types and resolvers in separate files
8 | - Log for errors
9 | - Connect to Devtools
10 |
11 | We believe we are not reinventing the wheel in this package but what we are doing is like putting together the wheels in the vehicle :).
12 |
13 | ## Installation
14 |
15 | Meteor package
16 | ```sh
17 | meteor add quave:graphql
18 | ```
19 | Server NPM packages
20 | ```sh
21 | meteor npm install graphql-tools graphql-load graphql
22 | ```
23 | Client NPM packages
24 | ```sh
25 | meteor npm install apollo-client apollo-cache-inmemory apollo-link-error apollo-link-ddp
26 | ```
27 |
28 | ### Usage
29 |
30 | #### Server
31 | In the server you should call `startGraphQLServer` providing your types and your resolvers. This function needs to be called during the server start so you should place it in the files imported by your main server file.
32 |
33 | Here you can check one example of [type](https://github.com/quavedev/graphql/blob/master/DateTimeTypeDef.js) and [resolver](https://github.com/quavedev/graphql/blob/master/DateTimeResolver.js).
34 |
35 | See below how to use it:
36 | ```javascript
37 | import { startGraphQLServer } from "meteor/quave:graphql/server";
38 |
39 | import { logger } from 'meteor/quave:logs/logger';
40 |
41 |
42 | import { DateTimeTypeDef } from "meteor/quave:graphql/DateTimeTypeDef";
43 | import { DateTimeResolver } from "meteor/quave:graphql/DateTimeResolver";
44 |
45 | const log = error => logger.error({ message: 'GraphQL server error', error })
46 |
47 | startGraphQLServer({ typeDefs: [DateTimeTypeDef], resolvers: [DateTimeResolver], log });
48 | ```
49 | `typeDefs` expects an array of types definitions (schemas) and `resolvers` expects an array of resolvers. You can use a single type definition and a single resolver but usually is better to split them in multiple files.
50 |
51 | You don't need to use `DateTimeTypeDef` and `DateTimeResolver` they are just examples.
52 |
53 | You also don't need to provide a log function, by default it will log to console.error.
54 |
55 | #### Client
56 | In the client you should call `startGraphQLClient`, this is going to return an Apollo client already configured to you.
57 | ```javascript
58 | import { startGraphQLClient } from "meteor/quave:graphql/client";
59 |
60 | const apolloClient = startGraphQLClient({ connectToDevTools: true });
61 | ```
62 | Then you can use the `apolloClient` as you want, see below two examples.
63 |
64 | ### Optional installations
65 |
66 | #### React
67 | To use GraphQL with React you probably want to have a provider around your app main component so you need to install `@apollo/react-hooks`
68 |
69 | ```sh
70 | meteor npm install @apollo/react-hooks
71 | ```
72 |
73 | then you can use `ApolloProvider`
74 |
75 | ```javascript
76 | import { startGraphQLClient } from "meteor/quave:graphql/client";
77 |
78 | import { ApolloProvider } from '@apollo/react-hooks';
79 |
80 | const apolloClient = startGraphQLClient({ connectToDevTools: true });
81 |
82 | Meteor.startup(() => {
83 | render(
84 |