Files
apollo/src/index.js
T
2018-05-21 20:15:36 +02:00

204 lines
5.6 KiB
JavaScript

import { DollarApollo } from './dollar-apollo'
import { ApolloProvider as apolloProvider } from './apollo-provider'
import CApolloQuery from './components/ApolloQuery'
import CApolloSubscribeToMore from './components/ApolloSubscribeToMore'
import CApolloMutation from './components/ApolloMutation'
import { Globals, omit } from './utils'
const keywords = [
'$subscribe',
]
function hasProperty (holder, key) {
return typeof holder !== 'undefined' && holder.hasOwnProperty(key)
}
const launch = 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]
// Default options from component
if (apollo.$query) {
options = Object.assign({}, apollo.$query, options)
}
// Property proxy
if (!hasProperty(this, key) && !hasProperty(this.$props, key) && !hasProperty(this.$data, key)) {
Object.defineProperty(this, key, {
get: () => this.$data.$apolloData.data[key],
enumerable: true,
configurable: true,
})
}
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) {
if (typeof value !== 'undefined') {
if (typeof value === 'function') {
$apollo.defineReactiveSetter(key, value)
} else {
$apollo[key] = value
}
}
}
export function install (Vue, options) {
if (install.installed) return
install.installed = true
Globals.Vue = Vue
// Options merging
const merge = Vue.config.optionMergeStrategies.methods
Vue.config.optionMergeStrategies.apollo = function (toVal, fromVal, vm) {
if (!toVal) return fromVal
if (!fromVal) return toVal
const toData = Object.assign({}, omit(toVal, keywords), toVal.data)
const fromData = Object.assign({}, omit(fromVal, keywords), fromVal.data)
const map = {}
for (let i = 0; i < keywords.length; i++) {
const key = keywords[i]
map[key] = merge(toVal[key], fromVal[key])
}
return Object.assign(map, merge(toData, fromData))
}
// Lazy creation
Object.defineProperty(Vue.prototype, '$apollo', {
get () {
if (!this._apollo) {
this._apollo = new DollarApollo(this)
}
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: {},
},
}
},
} : {},
created: launch,
destroyed: function () {
if (this._apollo) {
this._apollo.destroy()
this._apollo = null
}
},
})
if (vueVersion === '2') {
Vue.component('apollo-query', CApolloQuery)
Vue.component('ApolloQuery', CApolloQuery)
Vue.component('apollo-subscribe-to-more', CApolloSubscribeToMore)
Vue.component('ApolloSubscribeToMore', CApolloSubscribeToMore)
Vue.component('apollo-mutation', CApolloMutation)
Vue.component('ApolloMutation', CApolloMutation)
}
}
apolloProvider.install = install
// eslint-disable-next-line no-undef
apolloProvider.version = VERSION
// Apollo provider
export const ApolloProvider = apolloProvider
export { willPrefetch } from './apollo-provider'
// Components
export const ApolloQuery = CApolloQuery
export const ApolloSubscribeToMore = CApolloSubscribeToMore
export const ApolloMutation = CApolloMutation
// Auto-install
let GlobalVue = null
if (typeof window !== 'undefined') {
GlobalVue = window.Vue
} else if (typeof global !== 'undefined') {
GlobalVue = global.Vue
}
if (GlobalVue) {
GlobalVue.use(apolloProvider)
}
export default apolloProvider