refactor: from provide to apolloProvider option, closes #319

This commit is contained in:
Guillaume Chau
2018-08-26 18:16:17 +02:00
parent 439a897a7e
commit 62829e4a96
6 changed files with 173 additions and 144 deletions
+2 -2
View File
@@ -45,7 +45,7 @@ Vue.use(VueApollo)
## Apollo provider
The provider holds the apollo client instances that can then be used by all the child components. Inject it into your components with `provide`:
The provider holds the Apollo client instances that can then be used by all the child components. Inject it into your components with `provide`:
```js
const apolloProvider = new VueApollo({
@@ -54,7 +54,7 @@ const apolloProvider = new VueApollo({
new Vue({
el: '#app',
provide: apolloProvider.provide(),
apolloProvider,
render: h => h(App),
})
```
+1
View File
@@ -16,6 +16,7 @@ export class ApolloProvider {
}
provide (key = '$apolloProvider') {
console.warn(`<ApolloProvider>.provide() is deprecated. Use the 'apolloProvider' option instead with the provider object directly.`)
return {
[key]: this,
}
+14 -140
View File
@@ -1,108 +1,23 @@
import { DollarApollo } from './dollar-apollo'
import { ApolloProvider as apolloProvider } from './apollo-provider'
import { ApolloProvider as plugin } from './apollo-provider'
import CApolloQuery from './components/ApolloQuery'
import CApolloSubscribeToMore from './components/ApolloSubscribeToMore'
import CApolloMutation from './components/ApolloMutation'
import { installMixin } from './mixin'
import { Globals, omit } from './utils'
const keywords = [
'$subscribe',
]
function hasProperty (holder, key) {
return typeof holder !== 'undefined' && Object.prototype.hasOwnProperty.call(holder, key)
}
function proxyData () {
let apollo = this.$options.apollo
if (apollo) {
// watchQuery
for (let key in apollo) {
if (key.charAt(0) !== '$') {
let options = apollo[key]
// Property proxy
if (!options.manual && !hasProperty(this.$options.props, key) && !hasProperty(this.$options.computed, key) && !hasProperty(this.$options.methods, key)) {
Object.defineProperty(this, key, {
get: () => this.$data.$apolloData.data[key],
enumerable: true,
configurable: true,
})
}
}
}
}
}
function launch () {
const apolloProvider = this.$apolloProvider
if (this._apolloLaunched || !apolloProvider) return
this._apolloLaunched = true
// Prepare properties
let apollo = this.$options.apollo
if (apollo) {
if (!apollo.$init) {
apollo.$init = true
// Default options applied to `apollo` options
if (apolloProvider.defaultOptions) {
apollo = this.$options.apollo = Object.assign({}, apolloProvider.defaultOptions, apollo)
}
}
defineReactiveSetter(this.$apollo, 'skipAll', apollo.$skipAll, apollo.$deep)
defineReactiveSetter(this.$apollo, 'skipAllQueries', apollo.$skipAllQueries, apollo.$deep)
defineReactiveSetter(this.$apollo, 'skipAllSubscriptions', apollo.$skipAllSubscriptions, apollo.$deep)
defineReactiveSetter(this.$apollo, 'client', apollo.$client, apollo.$deep)
defineReactiveSetter(this.$apollo, 'loadingKey', apollo.$loadingKey, apollo.$deep)
defineReactiveSetter(this.$apollo, 'error', apollo.$error, apollo.$deep)
defineReactiveSetter(this.$apollo, 'watchLoading', apollo.$watchLoading, apollo.$deep)
// Apollo Data
Object.defineProperty(this, '$apolloData', {
get: () => this.$data.$apolloData,
enumerable: true,
configurable: true,
})
// watchQuery
for (let key in apollo) {
if (key.charAt(0) !== '$') {
let options = apollo[key]
this.$apollo.addSmartQuery(key, options)
}
}
if (apollo.subscribe) {
Globals.Vue.util.warn('vue-apollo -> `subscribe` option is deprecated. Use the `$subscribe` option instead.')
}
if (apollo.$subscribe) {
for (let key in apollo.$subscribe) {
this.$apollo.addSmartSubscription(key, apollo.$subscribe[key])
}
}
}
}
function defineReactiveSetter ($apollo, key, value, deep) {
if (typeof value !== 'undefined') {
if (typeof value === 'function') {
$apollo.defineReactiveSetter(key, value, deep)
} else {
$apollo[key] = value
}
}
}
export function install (Vue, options) {
if (install.installed) return
install.installed = true
Globals.Vue = Vue
const vueVersion = Vue.version.substr(0, Vue.version.indexOf('.'))
// Options merging
const merge = Vue.config.optionMergeStrategies.methods
@@ -125,55 +40,14 @@ export function install (Vue, options) {
// Lazy creation
Object.defineProperty(Vue.prototype, '$apollo', {
get () {
if (!this._apollo) {
this._apollo = new DollarApollo(this)
if (!this.$_apollo) {
this.$_apollo = new DollarApollo(this)
}
return this._apollo
return this.$_apollo
},
})
const vueVersion = Vue.version.substr(0, Vue.version.indexOf('.'))
Vue.mixin({
...vueVersion === '1' ? {
init () {
let apolloProvider
if (this.$options.apolloProvider) {
apolloProvider = this._apolloProvider = this.$options.apolloProvider
} else {
apolloProvider = this.$root._apolloProvider
}
this.$apolloProvider = apolloProvider
},
} : {},
...vueVersion === '2' ? {
inject: {
$apolloProvider: { default: null },
},
data () {
return {
'$apolloData': {
queries: {},
loading: 0,
data: {},
},
}
},
} : {},
beforeCreate: proxyData,
created: launch,
destroyed: function () {
if (this._apollo) {
this._apollo.destroy()
this._apollo = null
}
},
})
installMixin(Vue, vueVersion)
if (vueVersion === '2') {
Vue.component('apollo-query', CApolloQuery)
@@ -185,13 +59,13 @@ export function install (Vue, options) {
}
}
apolloProvider.install = install
plugin.install = install
// eslint-disable-next-line no-undef
apolloProvider.version = VERSION
plugin.version = VERSION
// Apollo provider
export const ApolloProvider = apolloProvider
export const ApolloProvider = plugin
export { willPrefetch } from './apollo-provider'
// Components
@@ -207,7 +81,7 @@ if (typeof window !== 'undefined') {
GlobalVue = global.Vue
}
if (GlobalVue) {
GlobalVue.use(apolloProvider)
GlobalVue.use(plugin)
}
export default apolloProvider
export default plugin
+146
View File
@@ -0,0 +1,146 @@
import { Globals } from './utils'
function hasProperty (holder, key) {
return typeof holder !== 'undefined' && Object.prototype.hasOwnProperty.call(holder, key)
}
function initDollarApollo () {
const options = this.$options
// ApolloProvider injection
const optionValue = options.apolloProvider
if (optionValue) {
this.$apolloProvider = typeof optionValue === 'function'
? optionValue()
: optionValue
} else if (options.parent && options.parent.$apolloProvider) {
this.$apolloProvider = options.parent.$apolloProvider
} else if (options.provide) {
// TODO remove
// Temporary retro-compatibility
const provided = typeof options.provide === 'function'
? options.provide.call(this)
: options.provide
if (provided.$apolloProvider) {
this.$apolloProvider = provided.$apolloProvider
}
}
}
function proxyData () {
let apollo = this.$options.apollo
if (apollo) {
// watchQuery
for (let key in apollo) {
if (key.charAt(0) !== '$') {
let options = apollo[key]
// Property proxy
if (!options.manual && !hasProperty(this.$options.props, key) && !hasProperty(this.$options.computed, key) && !hasProperty(this.$options.methods, key)) {
Object.defineProperty(this, key, {
get: () => this.$data.$apolloData.data[key],
enumerable: true,
configurable: true,
})
}
}
}
}
}
function launch () {
const apolloProvider = this.$apolloProvider
if (this._apolloLaunched || !apolloProvider) return
this._apolloLaunched = true
// Prepare properties
let apollo = this.$options.apollo
if (apollo) {
if (!apollo.$init) {
apollo.$init = true
// Default options applied to `apollo` options
if (apolloProvider.defaultOptions) {
apollo = this.$options.apollo = Object.assign({}, apolloProvider.defaultOptions, apollo)
}
}
defineReactiveSetter(this.$apollo, 'skipAll', apollo.$skipAll, apollo.$deep)
defineReactiveSetter(this.$apollo, 'skipAllQueries', apollo.$skipAllQueries, apollo.$deep)
defineReactiveSetter(this.$apollo, 'skipAllSubscriptions', apollo.$skipAllSubscriptions, apollo.$deep)
defineReactiveSetter(this.$apollo, 'client', apollo.$client, apollo.$deep)
defineReactiveSetter(this.$apollo, 'loadingKey', apollo.$loadingKey, apollo.$deep)
defineReactiveSetter(this.$apollo, 'error', apollo.$error, apollo.$deep)
defineReactiveSetter(this.$apollo, 'watchLoading', apollo.$watchLoading, apollo.$deep)
// Apollo Data
Object.defineProperty(this, '$apolloData', {
get: () => this.$data.$apolloData,
enumerable: true,
configurable: true,
})
// watchQuery
for (let key in apollo) {
if (key.charAt(0) !== '$') {
let options = apollo[key]
this.$apollo.addSmartQuery(key, options)
}
}
if (apollo.subscribe) {
Globals.Vue.util.warn('vue-apollo -> `subscribe` option is deprecated. Use the `$subscribe` option instead.')
}
if (apollo.$subscribe) {
for (let key in apollo.$subscribe) {
this.$apollo.addSmartSubscription(key, apollo.$subscribe[key])
}
}
}
}
function defineReactiveSetter ($apollo, key, value, deep) {
if (typeof value !== 'undefined') {
if (typeof value === 'function') {
$apollo.defineReactiveSetter(key, value, deep)
} else {
$apollo[key] = value
}
}
}
export function installMixin (Vue, vueVersion) {
Vue.mixin({
...vueVersion === '1' ? {
init: initDollarApollo,
} : {},
...vueVersion === '2' ? {
data () {
return {
'$apolloData': {
queries: {},
loading: 0,
data: {},
},
}
},
beforeCreate () {
initDollarApollo.call(this)
proxyData.call(this)
},
} : {},
created: launch,
destroyed: function () {
if (this.$_apollo) {
this.$_apollo.destroy()
this.$_apollo = null
}
},
})
}
+6
View File
@@ -10,10 +10,16 @@
<script>
import ChannelList from './components/ChannelList.vue'
import CHANNELS from './graphql/channels.gql'
export default {
components: {
ChannelList,
},
apollo: {
channels: CHANNELS,
},
}
</script>
+4 -2
View File
@@ -6,9 +6,11 @@ import { createProvider } from './vue-apollo'
Vue.config.productionTip = false
const apolloProvider = createProvider({}, { router })
new Vue({
router,
store,
provide: createProvider({}, { router }).provide(),
render: h => h(App),
apolloProvider,
...App,
}).$mount('#app')