Skip to content

Commit

Permalink
Added initialisation patter, improved docs
Browse files Browse the repository at this point in the history
  • Loading branch information
theodorDiaconu committed Apr 4, 2018
1 parent 92e6e2c commit 8e15fbf
Show file tree
Hide file tree
Showing 19 changed files with 223 additions and 146 deletions.
24 changes: 10 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ meteor add cultofcoders:apollo
meteor add swydo:graphql
```

Now, if you start your Meteor app it will complain because you don't have any `Query` set up yet, just set up an easy one:
Let's setup a basic query and initialize our GraphQL server:

```js
// file: server/index.js
// file: server/load.js
import { load } from 'graphql-load';

load({
Expand All @@ -46,6 +46,12 @@ load({
},
},
});

// file: server/index.js
import { initialize } from 'meteor/cultofcoders:apollo';
import './load.js';

initialize();
```

Now you can safely run your project:
Expand All @@ -62,19 +68,9 @@ query {
}
```

## Documentation

### Table of Contents
## [Documentation](docs/table-of-contents.md)

* [Simple Usage](docs/sample.md)
* [Work with Database](docs/db.md)
* [Accounts](docs/accounts.md)
* [Scalars](docs/scalars.md)
* [Live Queries](docs/live_queries.md)
* [Client](docs/client.md)
* [DDP](docs/ddp.md)
* [Visualising](docs/visualising.md)
* [Settings](docs/settings.md)
[Click here to go to the documentation](docs/table-of-contents.md)

### Useful packages

Expand Down
77 changes: 45 additions & 32 deletions client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,55 @@ import {
AUTH_TOKEN_KEY,
} from '../constants';

let links = [];

if (!Config.DISABLE_WEBSOCKETS) {
export const wsLink = new WebSocketLink({
uri: GRAPHQL_SUBSCRIPTION_ENDPOINT,
options: {
reconnect: true,
connectionParams: () => ({
[AUTH_TOKEN_KEY]: localStorage.getItem('Meteor.loginToken'),
}),
},
export function initialize(config = {}) {
Object.assign(Config, config);
Object.freeze(Config);

let links = [];
let wsLink;

if (!Config.DISABLE_WEBSOCKETS) {
wsLink = new WebSocketLink({
uri: GRAPHQL_SUBSCRIPTION_ENDPOINT,
options: {
reconnect: true,
connectionParams: () => ({
[AUTH_TOKEN_KEY]: localStorage.getItem('Meteor.loginToken'),
}),
},
});

links.push(wsLink);
}

const httpLink = new HttpLink({
uri: GRAPHQL_ENDPOINT,
});

links.push(wsLink);
}
if (meteorAccountsLink) {
links.push(concat(meteorAccountsLink, httpLink));
} else {
links.push(httpLink);
}

export const httpLink = new HttpLink({
uri: GRAPHQL_ENDPOINT,
});
const link = split(({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
}, ...links);

if (meteorAccountsLink) {
links.push(concat(meteorAccountsLink, httpLink));
} else {
links.push(httpLink);
}
const client = new ApolloClient({
link,
cache: new InMemoryCache({
dataIdFromObject: object => object._id || null,
}),
});

const link = split(({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
}, ...links);

export const client = new ApolloClient({
link,
cache: new InMemoryCache({
dataIdFromObject: object => object._id || null,
}),
});
return {
client,
link,
wsLink,
httpLink,
};
}

export { Config };
4 changes: 4 additions & 0 deletions docs/accounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,7 @@ load({
}
})
```

---

### [Table of Contents](table-of-contents.md)
44 changes: 40 additions & 4 deletions docs/client.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# Client

Let's play with Apollo, but outside GraphiQL
This is a quick recipe to get started with Apollo queries and React.

## React

Let's get our dependencies setup:

```js
meteor npm i -S react react-apollo react-dom prop-types graphql-tag
```

```js
// in client/main.html
<body>
Expand All @@ -13,14 +19,14 @@ Let's play with Apollo, but outside GraphiQL

```js
// in client/main.js
import { render } from 'react-dom';
import React from 'react';
import { render } from 'react-dom';
import { ApolloProvider } from 'react-apollo';

import { Meteor } from 'meteor/meteor';
import { client } from 'meteor/cultofcoders:apollo';
import { initialize } from 'meteor/cultofcoders:apollo';

import App from 'YOUR_APP';
const { client } = initialize();

Meteor.startup(() => {
render(
Expand All @@ -30,4 +36,34 @@ Meteor.startup(() => {
document.getElementById('app')
);
});

const QUERY = gql`
query {
sayHello
}
`;

const App = () => {
<Query query={QUERY}>
{(data, loading, error) => {
return data;
}}
</Query>;
};
```

## Settings

Initialize accepts as an argument a configuration object:

```js
initialize({
DISABLE_WEBSOCKETS: false;
})
```

* [Read more about React Apollo](https://www.apollographql.com/docs/react/)

---

### [Table of Contents](table-of-contents.md)
35 changes: 11 additions & 24 deletions docs/db.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ https://github.com/cult-of-coders/grapher-schema-directives
export default {
Query: {
posts(_, args, { db }, ast) {
// Performantly fetch the query using Grapher
// Performantly fetch the query using Grapher (More than 200X faster)
// You don't need to implement resolvers for your links, it's all done automatically
// Grapher will only fetch the fields you require

return db.posts.astToQuery(ast).fetch();
// but you can do whatever you want here since ctx.db.posts is a Mongo.Collection
// https://docs.meteor.com/api/collections.html
Expand All @@ -70,26 +71,6 @@ export default {
});
},
addCommentToPost(_, { postId, text }, { db }) {
// You can do this manually, but with Linker Engine from Grapher is nicer because
// it makes you not care at all about the stored fields, you only care about the linked name
// it takes care of the rest
// https://github.com/cult-of-coders/grapher/blob/master/docs/linker_engine.md
db.posts.getLink('comments').add({
text,
});

// or if you need the comment id:
const commentId = db.comments.insert({ text });
const commentLink = db.posts.getLink(postId, 'comments');
commentLink.add(commentId);

return commentId;

// alternatively, from the other side:
const commentId = db.comments.insert({ text });
db.comments.getLink(commentId, 'post').set(postId);

// Or just avoid Linker Engine
const comment = {
text,
postId,
Expand All @@ -113,8 +94,14 @@ export default {
};
```

Read more about Grapher's GraphQL bridge:
https://github.com/cult-of-coders/grapher/blob/master/docs/graphql.md
* [Read more about Grapher](https://github.com/cult-of-coders/grapher)
* [Read more about Grapher's performance](https://github.com/theodorDiaconu/grapher-performance)
* [Read more about Grapher Directives](https://github.com/cult-of-coders/grapher-schema-directives)
* [Read more about Grapher & GraphQL](https://github.com/cult-of-coders/grapher/blob/master/docs/graphql.md)

Read more about advanced functionalities of Collections:
Read more about advanced functionalities of Collections in Meteor:
http://www.meteor-tuts.com/chapters/3/persistence-layer.html

---

### [Table of Contents](table-of-contents.md)
6 changes: 5 additions & 1 deletion docs/ddp.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ And that's about it, used in conjunction with `DISABLE_WEBSOCKETS` is perfect.

The problem is that many useful packages in `Meteor` depend on `DDP`, it's not a problem if that happens server-side (at the expense of few hundred kbs), but it's a problem on the client, where few hundred kbs make a difference.

The logic here is that you can use `fusion`, and when your app wants to scale and it makes sense, you can think about a separate Meteor app that is designated for the client only, and from which you connect to your `api` with ease
The logic here is that you can use `fusion`, and when your app wants to scale and it makes sense, you can think about a separate Meteor app that is designated for the client only, and from which you connect to your `api` with ease.

---

### [Table of Contents](table-of-contents.md)
40 changes: 40 additions & 0 deletions docs/grapher.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Grapher

You can use Grapher to define your links in your types, for rapid prototyping:

* [Read more about Grapher](https://github.com/cult-of-coders/grapher)
* [Read more about Grapher Directives](https://github.com/cult-of-coders/grapher-schema-directives)
* [Read more about Grapher & GraphQL](https://github.com/cult-of-coders/grapher/blob/master/docs/graphql.md)

## Sample

```js
type Comment @mongo(name: "comments") {
_id: ID!
text: String
userId: String!
user: User @link(field: "userId")
postId: String
post: Post @link(field: "postId")
createdAt: Date
}
```

## Query

With Grapher you don't have to care about resolvers, because it knows exactly
how to create your data, and does it very efficiently, speeds more than 200X in some cases:

```js
export default {
Query: {
comments(_, args, { db }) {
return db.comments.astToQuery().fetch();
},
},
};
```

---

### [Table of Contents](table-of-contents.md)
Loading

0 comments on commit 8e15fbf

Please sign in to comment.