Skip to content

Commit 3e149c1

Browse files
committed
Upgrade to Apollo v3
No breaking changes
1 parent 573a7ca commit 3e149c1

13 files changed

+20290
-17642
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/node_modules
2+
*.sublime*
3+
.DS_Store

Readme.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ A knockoutjs extension to connect to a GraphQL endpoint through an ApolloClient
66
* Utilises the structure and loading features of [ko.plus](http://stevegreatrex.github.io/ko.plus/) for queries and mutations
77

88
## How it works
9-
Attaches additional methods to Observables/Observable Arrays via a [Custom Function](http://knockoutjs.com/documentation/fn.html). This library is strongly influenced by [Vue-Apollo](https://github.com/Akryum/vue-apollo).
9+
Attaches additional methods to Observables/Observable Arrays via a [Custom Function](http://knockoutjs.com/documentation/fn.html). This library is strongly influenced by [Vue-Apollo v1](https://github.com/Akryum/vue-apollo).
1010

1111
## Requirements
12-
* [Apollo Client & Apollo Link](https://github.com/apollographql/apollo-client)
12+
* [Apollo Client](https://github.com/apollographql/apollo-client)
1313
* [GraphQL Tag](https://github.com/apollographql/graphql-tag)
1414
* [Knockout](http://knockoutjs.com)
1515
* [ko.plus](http://stevegreatrex.github.io/ko.plus/)
@@ -22,9 +22,9 @@ Attaches additional methods to Observables/Observable Arrays via a [Custom Funct
2222
To run a demo in localhost open a terminal and:
2323
* `git clone https://github.com/AntonyThorpe/knockout-apollo.git`.
2424
* And `cd knockout-apollo` and type `npm install`.
25-
* Then `npm run tests` (we use Meteor Tests as a server for the demo)
26-
* To update demo.js with any of your changes open a new terminal and `npm run watch`.
27-
* Once Meteor is up and running open a third terminal, cd to the project root and `npm run demo` to open in Chrome.
25+
* Then `npm run test` (we use Meteor Tests as a server for the demo)
26+
* To update any of the demo files open a new terminal and `npm run watch` to save changes to `dist/demo.js`.
27+
* Once Meteor is up and running open a third terminal, cd to the project root and `npm run demo` to open in Firefox.
2828

2929
## Tests
3030
In the terminal cd to the `tests` folder and `meteor test --driver-package=practicalmeteor:mocha --port 3002`. Or, from project root, `npm run tests`.
@@ -48,4 +48,3 @@ None sorry.
4848
* [The Anatomy of a GraphQL Query](https://dev-blog.apollodata.com/the-anatomy-of-a-graphql-query-6dffa9e9e747) - Apollo Blog by Sashko Stubailo. The code follows these definitions.
4949
* [Apollo-Vue](https://github.com/Akryum/vue-apollo) - contains good non-React examples
5050
* [Meteor-Ticker](https://github.com/quintstoffers/meteornl-ticker) - Apollo+Meteor app showcasing GraphQL subscriptions in its simplest form
51-
* [How to get Apollo 2.0 working with GraphQL + subscriptions](https://medium.com/@michaelcbrook/how-to-get-apollo-2-0-working-with-graphql-subscriptions-321388be030c)

babel.config.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": ["@babel/preset-env"]
3+
}

changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog of Knockout Apollo
22

3+
#### 0.5.0
4+
* Upgraded to Apollo v3 (no breaking changes)
5+
* Enabled accessible methods for the Apollo Client of watchQuery, subscribe, readQuery, readFragment, writeQuery, writeFragment, resetStore, onResetStore, clearStore, onClearStore, stop and reFetchObservableQueries
36
#### 0.4.1
47
* Upgraded Browsersync to lastest version to correct dependency vulnerability
58
#### 0.4.0

demo/src/viewModel.js

Lines changed: 51 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,20 @@
11
/**
22
* viewModel
33
* @link https://www.apollographql.com/docs/react/advanced/subscriptions.html#subscriptions-client
4-
* @type function
4+
* @link https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/#using-apollo-client-without-react
55
*/
6-
import { ApolloClient } from 'apollo-client';
7-
import { split } from 'apollo-link';
8-
import { HttpLink } from 'apollo-link-http';
9-
import { WebSocketLink } from 'apollo-link-ws';
10-
import { InMemoryCache } from 'apollo-cache-inmemory';
11-
import { getMainDefinition } from 'apollo-utilities';
12-
import gql from 'graphql-tag';
13-
14-
// Establish a GraphQL connection
15-
const link = split(
16-
// split based on operation type
17-
({ query }) => {
18-
const { kind, operation } = getMainDefinition(query);
19-
return kind === 'OperationDefinition' && operation === 'subscription';
20-
},
21-
new WebSocketLink({
22-
uri: 'ws://localhost:4000/graphql',
23-
options: {
24-
reconnect: true
25-
}
26-
}),
27-
new HttpLink(
28-
{ uri: 'http://localhost:4000/graphql' }
29-
)
30-
);
31-
32-
const cache = new InMemoryCache({
33-
dataIdFromObject: object => object._id
6+
import { ApolloClient, InMemoryCache, gql } from '@apollo/client/core';
7+
import { WebSocketLink } from "@apollo/client/link/ws";
8+
import { SubscriptionClient } from "subscriptions-transport-ws";
9+
10+
// Establish a GraphQL connection using websockets
11+
// @link
12+
const client = new SubscriptionClient('ws://localhost:4000/graphql', {
13+
reconnect: true
3414
});
15+
const link = new WebSocketLink(client);
16+
17+
const cache = new InMemoryCache();
3518

3619
const apolloClient = new ApolloClient({
3720
link,
@@ -87,12 +70,12 @@ function TodoViewModel() {
8770
var self = this;
8871
var data;
8972

73+
// First example - update server based upon multiple changes
9074
self.todoList = ko.observableArray().crud({
9175
constructor: TodoList,
9276
uniqueIdentifier: "_id"
9377
}).launchApollo(apolloClient);
9478
self.todoList.messages = ko.observableArray();
95-
9679
self.todoList.apollo(
9780
{
9881
query: getTodoListQuery
@@ -197,7 +180,7 @@ function TodoViewModel() {
197180
};
198181

199182
self.cancel = function() {
200-
// return model to cache version
183+
// return model to prior version
201184
self.todoList.cancelEdit();
202185
self.todoList.beforeEdit(null);
203186
};
@@ -207,7 +190,7 @@ function TodoViewModel() {
207190
self.todoList.selectItem(item);
208191
};
209192

210-
// Second example
193+
// Second example - subscribe to changes in the ViewModel and update the server for each change
211194
self.todoList2 = ko.observableArray().crud({
212195
constructor: TodoList,
213196
uniqueIdentifier: "_id"
@@ -291,13 +274,14 @@ function TodoViewModel() {
291274
constructor: TodoList,
292275
uniqueIdentifier: "_id"
293276
}).liftOffSubscription(apolloClient);
294-
277+
self.todoList3.messages = ko.observableArray();
295278
self.todoList3.startGraphqlSubscription(
296279
{
297280
query: graphqlDocumentTodoList,
298281
},
299282
{
300283
next: function(data) {
284+
self.todoList3.messages.push(ko.toJSON(data));
301285
switch (data.data.todoList.status) {
302286
case "added":
303287
self.todoList3.insert(data.data.todoList.value);
@@ -325,7 +309,6 @@ function TodoViewModel() {
325309
constructor: TodoList,
326310
uniqueIdentifier: "_id"
327311
}).launchApollo(apolloClient);
328-
329312
self.todoList4.messages = ko.observableArray();
330313
self.todoList4.loading = true;
331314

@@ -357,28 +340,36 @@ function TodoViewModel() {
357340
};
358341
},
359342
update: function(cache, {data: {createTodo}}) {
360-
// Read the data from our cache for this query.
343+
// Read the data from our cache for this query
361344
const data = cache.readQuery({ query: getTodoListQuery });
362345

363346
if (createTodo._id < 0) {
364-
// Optimistic data goes into cache
365-
data.todoList.push(createTodo.todoList);
347+
// Optimistic data goes into the cache
348+
let newDataOptimistic = {
349+
...data,
350+
todoList: [...data.todoList, createTodo.todoList]
351+
};
352+
// Write the Optimistic data back to the cache
353+
cache.writeQuery({ query: getTodoListQuery, newDataOptimistic });
366354
} else {
367355
// _id returned from server so push again
368-
data.todoList.push(
369-
{
370-
_id: createTodo._id,
371-
task: item.task.peek(),
372-
completed: item.completed.peek(),
373-
__typename: createTodo.__typename
374-
}
375-
);
376-
356+
let newData = {
357+
...data,
358+
todoList: [
359+
...data.todoList,
360+
{
361+
_id: createTodo._id,
362+
task: item.task.peek(),
363+
completed: item.completed.peek(),
364+
__typename: createTodo.__typename
365+
}
366+
]
367+
};
368+
369+
// Write our data back to the cache
370+
cache.writeQuery({ query: getTodoListQuery, newData });
377371
item._id(createTodo._id); // update _id in knockout
378372
}
379-
380-
// Write our data back to the cache.
381-
cache.writeQuery({ query: getTodoListQuery, data });
382373
}
383374
// close optimistic update
384375
},
@@ -416,19 +407,24 @@ function TodoViewModel() {
416407
};
417408
},
418409
update: function(cache, {data: {removeTodo}}) {
419-
// Read the data from our cache for this query.
410+
// Read the data from our cache for this query
420411
const data = cache.readQuery({ query: getTodoListQuery });
421412

422-
// remove from store
413+
let newData = {
414+
...data,
415+
todoList: [...data.todoList]
416+
}; // clone
417+
418+
// remove from newData
423419
ko.utils.arrayRemoveItem(
424-
data.todoList,
425-
ko.utils.arrayFirst(data.todoList, function(obj){
420+
newData.todoList,
421+
ko.utils.arrayFirst(newData.todoList, function(obj){
426422
return obj._id === removeTodo._id;
427423
})
428424
);
429425

430-
// Write our data back to the cache.
431-
cache.writeQuery({ query: getTodoListQuery, data });
426+
// Write our data back to the cache
427+
cache.writeQuery({ query: getTodoListQuery, newData });
432428
}
433429
// close optimistic update
434430
},
@@ -506,8 +502,6 @@ function TodoViewModel() {
506502
};
507503

508504

509-
510-
511505
// Vanilla subscription
512506
/* apolloClient.subscribe({
513507
query: graphqlDocumentTodoList

0 commit comments

Comments
 (0)