Skip to content

Commit d07900c

Browse files
author
Guillaume Chau
committed
More special options, default options, provider options, better doc (wip)
1 parent 086b486 commit d07900c

File tree

5 files changed

+216
-25
lines changed

5 files changed

+216
-25
lines changed

README.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ Integrates [apollo](http://www.apollostack.com/) in your [Vue](http://vuejs.org)
3939
- [Skipping the subscription](#skipping-the-subscription)
4040
- [Manually adding a smart Subscription](#manually-adding-a-smart-subscription)
4141
- [Pagination with `fetchMore`](#pagination-with-fetchmore)
42+
- [Special options](#special-options)
4243
- [Skip all](#skip-all)
4344
- [Multiple clients](#multiple-clients)
4445
- [Server-Side Rendering](#server-side-rendering)
46+
- [API Reference](#api-reference)
4547

4648
## Installation
4749

@@ -1040,6 +1042,48 @@ export default {
10401042

10411043
**Don't forget to include the `__typename` to the new result.**
10421044

1045+
## Special options
1046+
1047+
The special options being with `$` in the `apollo` object.
1048+
1049+
- `$skip` to disable all queries and subscriptions (see below)
1050+
- `$skipAllQueries` to disable all queries (see below)
1051+
- `$skipAllSubscriptions` to disable all subscriptions (see below)
1052+
- `$client` to use a client by default (see below)
1053+
- `$loadingKey` for a default loading key (see `loadingKey` advanced options for smart queries)
1054+
- `$error` to catch errors in a default handler (see `error` advanced options for smart queries)
1055+
1056+
Example:
1057+
1058+
```html
1059+
<script>
1060+
export default {
1061+
data () {
1062+
return {
1063+
loading: 0,
1064+
}
1065+
},
1066+
apollo: {
1067+
$loadingKey: 'loading',
1068+
query1: { ... },
1069+
query2: { ... },
1070+
},
1071+
}
1072+
</script>
1073+
```
1074+
1075+
You can define in the apollo provider a default set of options to apply to the `apollo` definitions. For example:
1076+
1077+
```javascript
1078+
const apolloProvider = new VueApollo({
1079+
defaultClient: apolloClient,
1080+
defaultOptions: {
1081+
// apollo options applied to all components that are using apollo
1082+
$loadingKey: 'loading',
1083+
},
1084+
})
1085+
```
1086+
10431087
## Skip all
10441088

10451089
You can disable all the queries for the component with `skipAllQueries`, all the subscriptions with `skipAllSubscriptions` and both with `skipAll`:
@@ -1409,4 +1453,125 @@ router.onReady(() => {
14091453

14101454
---
14111455

1456+
# API Reference
1457+
1458+
WIP (PR welcome!)
1459+
1460+
## ApolloProvider
1461+
1462+
### Constructor
1463+
1464+
```javascript
1465+
const apolloProvider = new VueApollo({
1466+
// Multiple clients support
1467+
// Use the 'client' option inside queries
1468+
// or '$client' on the apollo definition
1469+
clients: {
1470+
a: apolloClientA,
1471+
b: apolloClientB,
1472+
},
1473+
// Default client
1474+
defaultClient: apolloClient,
1475+
// Default 'apollo' definition
1476+
defaultOptions: {
1477+
// See 'apollo' defintion
1478+
},
1479+
// Watch loading state for all queries
1480+
// See the 'watchLoading' advanced option
1481+
watchLoading (state, mod) {
1482+
loading += mod
1483+
console.log('Global loading', loading, mod)
1484+
},
1485+
// Global error handler for all smart queries and subscriptions
1486+
errorHandler (error) {
1487+
console.log('Global error handler')
1488+
console.error(error)
1489+
},
1490+
})
1491+
```
1492+
1493+
Use the apollo provider into your Vue app:
1494+
1495+
```javascript
1496+
new Vue({
1497+
el: '#app',
1498+
apolloProvider,
1499+
render: h => h(App),
1500+
})
1501+
```
1502+
1503+
### Methods
1504+
1505+
#### prefetchAll
1506+
1507+
(SSR) Prefetch all queued component definitions and returns a promise resolved when all corresponding apollo data is ready.
1508+
1509+
```javascript
1510+
await apolloProvider.prefetchAll (context, componentDefs, options)
1511+
```
1512+
1513+
`context` is passed as the argument to the `prefetch` options inside the smart queries. It may contain the route and the store.
1514+
1515+
`options` defaults to:
1516+
1517+
```javascript
1518+
{
1519+
// Include components outside of the routes
1520+
// that are registered with `willPrefetch`
1521+
includeGlobal: true,
1522+
}
1523+
```
1524+
1525+
#### getStates
1526+
1527+
(SSR) Returns the apollo stores states as JavaScript objects.
1528+
1529+
```JavaScript
1530+
const states = apolloProvider.getStates(options)
1531+
```
1532+
1533+
`options` defaults to:
1534+
1535+
```javascript
1536+
{
1537+
// Prefix for the keys of each apollo client state
1538+
exportNamespace: '',
1539+
}
1540+
```
1541+
1542+
#### exportStates
1543+
1544+
(SSR) Returns the apollo stores states as JavaScript code inside a String. This code can be directly injected to the page HTML inside a `<script>` tag.
1545+
1546+
```javascript
1547+
const js = apolloProvider.exportStates(options)
1548+
```
1549+
1550+
`options` defaults to:
1551+
1552+
```javascript
1553+
{
1554+
// Global variable name
1555+
globalName: '__APOLLO_STATE__',
1556+
// Global object on which the variable is set
1557+
attachTo: 'window',
1558+
// Prefix for the keys of each apollo client state
1559+
exportNamespace: '',
1560+
}
1561+
```
1562+
1563+
## Dollar Apollo
1564+
1565+
This is the apollo manager added to any component that uses apollo. It can be accessed inside a component with `this.$apollo`.
1566+
1567+
## Smart Query
1568+
1569+
Each query declared in the `apollo` definition (that is, which doesn't start with a `$` char) in a component results in the creation of a smart query object.
1570+
1571+
## Smart Subscription
1572+
1573+
Each subscription declared in the `apollo.$subscribe` option in a component results in the creation of a smart subscription object.
1574+
1575+
---
1576+
14121577
LICENCE ISC - Created by Guillaume CHAU (@Akryum)

src/apollo-provider.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export class ApolloProvider {
99
}
1010
this.clients = options.clients || {}
1111
this.clients.defaultClient = this.defaultClient = options.defaultClient
12+
this.defaultOptions = options.defaultOptions
13+
this.watchLoading = options.watchLoading
14+
this.errorHandler = options.errorHandler
1215

1316
this.prefetchQueries = []
1417
}

src/dollar-apollo.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export class DollarApollo {
1010
this.queries = {}
1111
this.subscriptions = {}
1212
this.client = undefined
13+
this.loadingKey = undefined
14+
this.error = undefined
1315
}
1416

1517
get provider () {

src/index.js

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,32 @@ const keywords = [
88
]
99

1010
const prepare = function prepare () {
11+
let apolloProvider
1112
if (this.$options.apolloProvider) {
12-
this._apolloProvider = this.$options.apolloProvider
13+
apolloProvider = this._apolloProvider = this.$options.apolloProvider
14+
} else {
15+
apolloProvider = this.$root._apolloProvider
1316
}
1417

1518
if (this._apolloPrepared) return
1619
this._apolloPrepared = true
1720

1821
// Prepare properties
1922
let apollo = this.$options.apollo
23+
2024
if (apollo) {
2125
this._apolloQueries = {}
2226
this._apolloInitData = {}
27+
this.$apollo = new DollarApollo(this)
28+
29+
if (!apollo.$init) {
30+
apollo.$init = true
31+
32+
// Default options applied to `apollo` options
33+
if (apolloProvider.defaultOptions) {
34+
apollo = this.$options.apollo = Object.assign({}, apolloProvider.defaultOptions, apollo)
35+
}
36+
}
2337

2438
// watchQuery
2539
for (let key in apollo) {
@@ -35,14 +49,23 @@ const launch = function launch () {
3549
if (this._apolloLaunched) return
3650
this._apolloLaunched = true
3751

52+
let apollo = this.$options.apollo
53+
if (apollo) {
54+
defineReactiveSetter(this.$apollo, 'skipAll', apollo.$skipAll)
55+
defineReactiveSetter(this.$apollo, 'skipAllQueries', apollo.$skipAllQueries)
56+
defineReactiveSetter(this.$apollo, 'skipAllSubscriptions', apollo.$skipAllSubscriptions)
57+
defineReactiveSetter(this.$apollo, 'client', apollo.$client)
58+
defineReactiveSetter(this.$apollo, 'loadingKey', apollo.$loadingKey)
59+
defineReactiveSetter(this.$apollo, 'error', apollo.$error)
60+
}
61+
3862
if (this._apolloQueries) {
3963
// watchQuery
4064
for (let key in this._apolloQueries) {
4165
this.$apollo.addSmartQuery(key, this._apolloQueries[key])
4266
}
4367
}
4468

45-
let apollo = this.$options.apollo
4669
if (apollo) {
4770
if (apollo.subscribe) {
4871
Globals.Vue.util.warn('vue-apollo -> `subscribe` option is deprecated. Use the `$subscribe` option instead.')
@@ -53,11 +76,6 @@ const launch = function launch () {
5376
this.$apollo.addSmartSubscription(key, apollo.$subscribe[key])
5477
}
5578
}
56-
57-
defineReactiveSetter(this.$apollo, 'skipAll', apollo.$skipAll)
58-
defineReactiveSetter(this.$apollo, 'skipAllQueries', apollo.$skipAllQueries)
59-
defineReactiveSetter(this.$apollo, 'skipAllSubscriptions', apollo.$skipAllSubscriptions)
60-
defineReactiveSetter(this.$apollo, 'client', apollo.$client)
6179
}
6280
}
6381

@@ -95,16 +113,6 @@ export function install (Vue, options) {
95113
return Object.assign(map, merge(toData, fromData))
96114
}
97115

98-
// Lazy creation
99-
Object.defineProperty(Vue.prototype, '$apollo', {
100-
get () {
101-
if (!this._apollo) {
102-
this._apollo = new DollarApollo(this)
103-
}
104-
return this._apollo
105-
},
106-
})
107-
108116
Vue.mixin({
109117

110118
// Vue 1.x

src/smart-apollo.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ class SmartApollo {
115115
throw new Error('Not implemented')
116116
}
117117

118+
errorHandler (...args) {
119+
this.options.error && this.options.error.call(this.vm, ...args)
120+
this.vm.$apollo.error && this.vm.$apollo.error.call(this.vm, ...args)
121+
this.vm.$apollo.provider.errorHandler && this.vm.$apollo.provider.errorHandler.call(this.vm, ...args)
122+
}
123+
118124
catchError (error) {
119125
if (error.graphQLErrors && error.graphQLErrors.length !== 0) {
120126
console.error(`GraphQL execution errors for ${this.type} '${this.key}'`)
@@ -132,9 +138,7 @@ class SmartApollo {
132138
}
133139
}
134140

135-
if (typeof this.options.error === 'function') {
136-
this.options.error.call(this.vm, error)
137-
}
141+
this.errorHandler(error)
138142
}
139143

140144
destroy () {
@@ -233,14 +237,23 @@ export class SmartQuery extends SmartApollo {
233237
this.loadingDone()
234238
}
235239

240+
get loadingKey () {
241+
return this.options.loadingKey || this.vm.$apollo.loadingKey
242+
}
243+
244+
watchLoading (...args) {
245+
this.options.watchLoading && this.options.watchLoading.call(this.vm, ...args)
246+
this.vm.$apollo.watchLoading && this.vm.$apollo.watchLoading.call(this.vm, ...args)
247+
this.vm.$apollo.provider.watchLoading && this.vm.$apollo.provider.watchLoading.call(this.vm, ...args)
248+
}
249+
236250
applyLoadingModifier (value) {
237-
if (this.options.loadingKey) {
238-
this.vm[this.options.loadingKey] += value
251+
const loadingKey = this.loadingKey
252+
if (loadingKey && typeof this.vm[loadingKey] === 'number') {
253+
this.vm[loadingKey] += value
239254
}
240255

241-
if (this.options.watchLoading) {
242-
this.options.watchLoading.call(this.vm, value === 1, value)
243-
}
256+
this.watchLoading(value === 1, value)
244257
}
245258

246259
loadingDone () {

0 commit comments

Comments
 (0)