Apollo + Meteor: which features exactly are coming in 1.5?

Indeed, manually refetching would be a hassle. You can do this at will when you need to (like a refresh button on a mobile app).

However, your mutation has to return something (I think at least) and most of the time you would return the data it’s changed. When you do this you want to return the _id of the document so that Apollo can merge the old object with the new one you just returned. The react-apollo binding take care of re-rending the view whenever the apollo cache has changed.

// in click handler
      this.props.mutate({ variables: { text: "task", list_id: 1 } })
        .then(({ data }) => {
           // use it here if you like, this will also update the redux cache
          console.log('got data', data);
        }).catch((error) => {
          console.log('there was an error sending the query', error);
        });  

Note you can also call this from outside the view when needed. Sometimes i’ll want to preload the “feed” data right after logging in so I’ll manually fetch the minimum for that, then hide the spinner and redirect, to make the view feel “fast”.

5 Likes

I agree with this 100%. If you’re getting ready for Apollo then writing methods over pubsub is well worth the investment. Migrating old code from methods to Apollo has been super nice. Still struggling with bugs in migrating pubsub.

The root cause for us was tracker and subscribes and all this jazz are hard to keep predictable. So just opens up a can of worms when moving it from pubsub which had its own set of characteristics.

With methods it’s quite predictable already so the migration was very 1 to 1.

My 2 cents

2 Likes

Good to see both perspectives! Just wanted to chime in and say all of the stuff I have personally seen moved in our internal apps was pub/sub, but it’s good to know that migrating methods is easy as well.

2 Likes

Maybe some kind of Mongo package driver for GraphQL like this one: https://github.com/RisingStack/graffiti-mongoose

Why not just use Mongoose just like here?

Yeah personally I think it’s a good idea to separate the API from the database models.

1 Like

For what it’s worth I think it might be nice to use Apollo with minimongo. I would have no problem with running GraphQL queries and depositing them into local collections. Maybe minimongo can be rebranded as a reactive cache and maybe the two actions could be integrated somehow.

5 Likes

I haven’t looked into Apollo too much. but here’s how I’d guess it should look in Meteor:

// run query
UserList = new Apollo.query('add-query-here')

// returns reactive data to template
UserList.data().fieldName 

// re-run Query
UserList.update()
2 Likes

Yep, this is totally do-able. I wonder if you would want to wrap the GraphQL call with a function that will handle inserting the local collection? That might clean up some of the verboseness with Blaze. maybe something like the code below? (though if one is using React the apollo-react bindings are more simple since it has it’s own cache).

I think trying to shoehorn mutations into the minimongo API would be awkward since you tend to think differently about data.

Categories = new Mongo.Collection(null);

function getCategory() {
  client.query({
    query: gql`
    query getCategory($categoryId: Int!) {
      category(id: $categoryId) {
        name
        color
      }
    }
  `,
    variables: {
      categoryId: 5,
    },
    forceFetch: true,
  }).then(({ data }) => {
    Categories.upsert(data._id, data);
  }).catch((error) => {
    console.log('there was an error sending the query', error);
  });
}

I don’t know after writing this out maybe a better approach would be to create some kind of Blaze bindings to get a more similar API like apollo-react?

2 Likes

What is that? Since when porps mutable?

Right now the core API looks like:

// A bit verbose since we intend most people will use an integration
const observableQuery = client.watchQuery({ query: `...` });

observableQuery.subscribe({
  next: (data) => { ... data here ...}
});

observableQuery.refetch();

Most people use it through react-apollo or angular2-apollo, though, which looks more like:

graphql(`query`)(MyReactComponent)

I’d imagine the Blaze version, if someone wanted to build one, would be something like:

Template.myTemplate.onCreated(function () {
   this.queryData = this.query('...');
});

And queryData would probably be a ReactiveVar.

We gotta make it prettier than that. One of the things I liked about Meteor is that it was very pretty.

3 Likes

If you are the maintainer of the Blaze-Apollo integration, you can make it look however you like :]

I had a few ideas for a Blaze-Apollo hyperframework (IDK if that is a word) where you would basically write zero code, and your templates would look like:

<template name="stuff">
  <graphql>
    query allPosts {
      posts {
        id
        title
        votes
        author {
          id
          firstName
          lastName
        }
      }
    }

    mutation addPost($id: ID!) {
      addPost(authorId: $id)
    }
  </graphql>
  <div>
    {{#each post in posts}}
      <h1>{{post.title}}</h1>
      <p>By {{post.author.firstName}} {{post.author.lastName}}</p>
    {{/each}}
    <button onClick={{addPost(id = post.author.id)}}>Add post</button>
  </div>
</template>

We’re probably a while away from building apps like that, but I think it would be super sick. Basically, the data “just shows up” when you need it, you can define all of your data updates in GraphQL, and then you just need a server. Jonas has some ideas for how to make the server super trivial as well.

Anyway, this isn’t at all what we are prioritizing right now, or probably for the next year. But it’s a glimpse into what I mean when I say “GraphQL doesn’t have to be complicated”.

*hyperframework: something that will blow your mind because the app just writes itself

10 Likes

5 Likes

Not a fan of mixing logic and views to that degree… however, I think this can be even easier:

<template name="stuff">
  <div>
    **{{#each post in allPosts via GraphQL}}** <!-- focus is here -->
      <h1>{{post.title}}</h1>
      <p>By {{post.author.firstName}} {{post.author.lastName}}</p>
    {{/each}}
    <button onClick={{addPost(id = post.author.id)}}>Add post</button>
  </div>
</template>

The application should be able to infer how to construct the query. :sunglasses:

6 Likes

With you here…

Full 360!!

Two points:

  1. Generating the query from the UI is definitely mixing logic and UI
  2. I kinda like the idea of writing it twice, and having the UI check if it’s consistent with the query. Otherwise, you have to reimplement all of the features of GraphQL (directives, fragments, type conditions, aliases, and more) in Blaze, and that doesn’t sound great at all.
  3. (bonus point) Using the GraphQL language directly will make it easy to integrate with existing and future GraphQL tools, without needing to build a special tool for the BlazeQL language.
5 Likes

I don’t see how you figured that. The idea here is the build tool will magically construct the query from the handlebars and then embed the code into the application.

Hmm, I think magic opens a lot of opportunities here :wink:

Sure, but not relevant in the context of a goal to build a hyper framework.

Anyways, just a wild idea. Not sure how much effort its worth yet.

Yeah, I guess in my mind there are some things that improve code clarity, and IMO GraphQL query strings are really clear where HTML and property accesses aren’t, especially if you add custom expressions, helpers, etc.

Please explain this more.

Please elaborate.

Basically, magic is…

The build tool can parse the template file, extract all the data fields necessary, and then bundle a query into the app code files. It’d be like a cracked out transpiler.

3 Likes