Merge branch 'next' into apollo-1

This commit is contained in:
Guillaume Chau
2018-02-11 22:02:21 +01:00
29 changed files with 3885 additions and 1390 deletions
+4 -6
View File
@@ -1,11 +1,9 @@
{
"presets": [
[
"es2015",
{
"modules": false
}
],
["env", { "modules": false }],
"stage-0"
],
"plugins": [
"external-helpers"
]
}
+2
View File
@@ -0,0 +1,2 @@
node_modules/
dist/
+1
View File
@@ -1 +1,2 @@
node_modules/
types/test/*.js
+1
View File
@@ -1 +1,2 @@
src/
types/test/
+382 -49
View File
@@ -1,14 +1,16 @@
# Apollo and GraphQL for Vue.js
[![npm](https://img.shields.io/npm/v/vue-apollo.svg) ![npm](https://img.shields.io/npm/dm/vue-apollo.svg)](https://www.npmjs.com/package/vue-apollo)
[![vue1](https://img.shields.io/badge/apollo-1.x-blue.svg)](http://apollodata.com/)
[![vue1](https://img.shields.io/badge/vue-1.x-brightgreen.svg) ![vue2](https://img.shields.io/badge/vue-2.x-brightgreen.svg)](https://vuejs.org/)
[![vue1](https://img.shields.io/badge/apollo-2.x-blue.svg)](https://www.apollographql.com/)
[![vue1](https://img.shields.io/badge/vue-1.x-brightgreen.svg) ![vue2](https://img.shields.io/badge/vue-2.2+-brightgreen.svg)](https://vuejs.org/)
![schema](https://cdn-images-1.medium.com/max/800/1*H9AANoofLqjS10Xd5TwRYw.png)
**Apollo 2.x support in preview, [read more here](https://github.com/Akryum/vue-apollo/tree/next#migrating-from-vue-apollo-2x-and-apollo-1x)!**
**Warning! This README is related to the next version of vue-apollo (that supports Apollo 2.x). For the old release (supporting only Apollo 1.x), see [here](https://github.com/Akryum/vue-apollo/tree/apollo-1).**
Integrates [apollo](http://www.apollostack.com/) in your [Vue](http://vuejs.org) components with declarative queries. Compatible with Vue 1.0+ and 2.0+. [Live demo](https://jsfiddle.net/Akryum/oyejk2qL/)
Integrates [apollo](https://www.apollographql.com/) in your [Vue](http://vuejs.org) components with declarative queries. Compatible with Vue 1.0+ and 2.0+. [Live demo](https://jsfiddle.net/Akryum/oyejk2qL/)
[<img src="https://assets-cdn.github.com/favicon.ico" alt="icon" width="16" height="16"/> Vue-cli plugin](https://github.com/Akryum/vue-cli-plugin-apollo)
[<img src="https://assets-cdn.github.com/favicon.ico" alt="icon" width="16" height="16"/> More vue-apollo examples](https://github.com/Akryum/vue-apollo-example)
@@ -28,6 +30,7 @@ Integrates [apollo](http://www.apollostack.com/) in your [Vue](http://vuejs.org)
- [Queries](#queries)
- [Simple query](#simple-query)
- [Query with parameters](#query-with-parameters)
- [Loading state](#loading-state)
- [Option function](#option-function)
- [Reactive query definition](#reactive-query-definition)
- [Reactive parameters](#reactive-parameters)
@@ -46,26 +49,36 @@ Integrates [apollo](http://www.apollostack.com/) in your [Vue](http://vuejs.org)
- [Skip all](#skip-all)
- [Multiple clients](#multiple-clients)
- [Server-Side Rendering](#server-side-rendering)
- [Query Components](#query-components)
- [Migration](#migration)
- [API Reference](#api-reference)
## Installation
**If you are using vue-cli 3.x, you can [use this vue-cli plugin](https://github.com/Akryum/vue-cli-plugin-apollo) to get started in a few minutes!**
Try and install these packages before server side set (of packages), add apollo to meteor.js before then, too.
npm install --save vue-apollo apollo-client
npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
In your app, create an `ApolloClient` instance and install the `VueApollo` plugin:
```javascript
import Vue from 'vue'
import { ApolloClient, createBatchingNetworkInterface } from 'apollo-client'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
const httpLink = new HttpLink({
// You should use an absolute URL here
uri: 'http://localhost:3020/graphql',
})
// Create the apollo client
const apolloClient = new ApolloClient({
networkInterface: createBatchingNetworkInterface({
uri: 'http://localhost:3020/graphql',
}),
link: httpLink,
cache: new InMemoryCache(),
connectToDevTools: true,
})
@@ -84,7 +97,7 @@ const apolloProvider = new VueApollo({
new Vue({
el: '#app',
apolloProvider,
provide: apolloProvider.provide(),
render: h => h(App),
})
```
@@ -101,7 +114,7 @@ new Vue({
})
```
You can access the [apollo-client](http://dev.apollodata.com/core/apollo-client-api.html) instances with `this.$apollo.provider.defaultClient` or `this.$apollo.provider.clients.<key>` (for [Multiple clients](#multiple-clients)) in all your vue components.
You can access the [apollo-client](https://www.apollographql.com/docs/react/) instances with `this.$apollo.provider.defaultClient` or `this.$apollo.provider.clients.<key>` (for [Multiple clients](#multiple-clients)) in all your vue components.
## Queries
@@ -115,7 +128,7 @@ Use `gql` to write your GraphQL queries:
import gql from 'graphql-tag'
```
Put the [gql](http://docs.apollostack.com/apollo-client/core.html#gql) query directly as the value:
Put the [gql](https://github.com/apollographql/graphql-tag) query directly as the value:
```javascript
apollo: {
@@ -159,7 +172,7 @@ export const resolvers = {
}
```
For more info, visit the [apollo doc](http://dev.apollodata.com/tools/).
For more info, visit the [apollo doc](https://www.apollographql.com/docs/apollo-server/).
You can then use your property as usual in your vue component:
@@ -200,9 +213,9 @@ You can use the apollo `watchQuery` options in the object, like:
- `pollInterval`
- ...
See the [apollo doc](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.watchQuery) for more details.
See the [apollo doc](https://www.apollographql.com/docs/react/reference/index.html#ApolloClient\.watchQuery) for more details.
For example, you could add the `forceFetch` apollo option like this:
For example, you could add the `fetchPolicy` apollo option like this:
```javascript
apollo: {
@@ -260,12 +273,26 @@ And then use it in your vue component:
<div class="apollo">
<h3>Ping</h3>
<p>
{{ping}}
{{ ping }}
</p>
</div>
</template>
```
### Loading state
You can display a loading state thanks to the `$apollo.loading` prop:
```html
<div v-if="$apollo.loading">Loading...</div>
```
Or for this specific `ping` query:
```html
<div v-if="$apollo.queries.ping.loading">Loading...</div>
```
### Option function
You can use a function to initialize the key:
@@ -407,7 +434,7 @@ this.$apollo.queries.tags.skip = true
These are the available advanced options you can use:
- `update(data) {return ...}` to customize the value that is set in the vue property, for example if the field names don't match.
- `result(ApolloQueryResult)` is a hook called when a result is received (see documentation for [ApolloQueryResult](http://dev.apollodata.com/core/apollo-client-api.html#ApolloQueryResult)).
- `result(ApolloQueryResult)` is a hook called when a result is received (see documentation for [ApolloQueryResult](https://github.com/apollographql/apollo-client/blob/master/packages/apollo-client/src/core/types.ts)).
- `error(error)` is a hook called when there are errors. `error` is an Apollo error object with either a `graphQLErrors` property or a `networkError` property.
- `loadingKey` will update the component data property you pass as the value. You should initialize this property to `0` in the component `data()` hook. When the query is loading, this property will be incremented by 1; when it is no longer loading, it will be decremented by 1. That way, the property can represent a counter of currently loading queries.
- `watchLoading(isLoading, countModifier)` is a hook called when the loading state of the query changes. The `countModifier` parameter is either equal to `1` when the query is loading, or `-1` when the query is no longer loading.
@@ -566,7 +593,9 @@ created () {
## Mutations
Mutations are queries that change your data state on your apollo server. For more info, visit the [apollo doc](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.mutate). There is a mutation-focused [example app](https://github.com/Akryum/vue-apollo-todos) you can look at.
Mutations are queries that change your data state on your apollo server. For more info, visit the [apollo doc](https://www.apollographql.com/docs/react/reference/index.html#ApolloClient\.mutate). There is a mutation-focused [example app](https://github.com/Akryum/vue-apollo-todos) you can look at.
**You shouldn't send the `__typename` fields in the variables, so it is not recommended to send an Apollo result object directly.**
```javascript
methods: {
@@ -687,40 +716,55 @@ export const resolvers = {
To make enable the websocket-based subscription, a bit of additional setup is required:
```
npm install --save subscriptions-transport-ws
npm install --save apollo-link-ws apollo-utilities
```
```javascript
import Vue from 'vue'
import { ApolloClient, createNetworkInterface } from 'apollo-client'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
// New Imports
import { SubscriptionClient, addGraphQLSubscriptions } from 'subscriptions-transport-ws'
import { split } from 'apollo-link'
import { WebSocketLink } from 'apollo-link-ws'
import { getMainDefinition } from 'apollo-utilities'
import VueApollo from 'vue-apollo'
// Create the network interface
const networkInterface = createNetworkInterface({
uri: 'http://localhost:3000/graphql',
transportBatching: true,
const httpLink = new HttpLink({
// You should use an absolute URL here
uri: 'http://localhost:3020/graphql',
})
// Create the subscription websocket client
const wsClient = new SubscriptionClient('ws://localhost:3000/subscriptions', {
reconnect: true,
// Create the subscription websocket link
const wsLink = new WebSocketLink({
uri: 'ws://localhost:3000/subscriptions',
options: {
reconnect: true,
},
})
// Extend the network interface with the subscription client
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
networkInterface,
wsClient,
// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const link = split(
// split based on operation type
({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' &&
operation === 'subscription'
},
wsLink,
httpLink
)
// Create the apollo client with the new network interface
// Create the apollo client
const apolloClient = new ApolloClient({
networkInterface: networkInterfaceWithSubscriptions,
link,
cache: new InMemoryCache(),
connectToDevTools: true,
})
// Install the plugin like before
// Install the vue plugin like before
Vue.use(VueApollo)
```
@@ -1236,6 +1280,14 @@ export default willPrefetch({
})
```
The second parameter is optional: it's a callback that gets the context and should return a boolean indicating if the component should be prefetched:
```js
willPrefetch({
// Component definition...
}, context => context.url === '/foo')
```
### On the server
To prefetch all the apollo queries you marked, use the `apolloProvider.prefetchAll` method. The first argument is the context object passed to the `prefetch` hooks (see above). It is recommended to pass the vue-router `currentRoute` object. The second argument is the array of component definition to include (e.g. from `router.getMatchedComponents` method). The third argument is an optional `options` object. It returns a promise resolved when all the apollo queries are loaded.
@@ -1340,7 +1392,9 @@ Here is an example:
// src/api/apollo.js
import Vue from 'vue'
import { ApolloClient, createNetworkInterface } from 'apollo-client'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
// Install the vue plugin
@@ -1348,29 +1402,32 @@ Vue.use(VueApollo)
// Create the apollo client
export function createApolloClient (ssr = false) {
let initialState
const httpLink = new HttpLink({
// You should use an absolute URL here
uri: ENDPOINT + '/graphql',
})
const cache = new InMemoryCache()
// If on the client, recover the injected state
if (!ssr && typeof window !== 'undefined') {
const state = window.__APOLLO_STATE__
if (state) {
// If you have multiple clients, use `state.<client_id>`
initialState = state.defaultClient
if (!ssr) {
// If on the client, recover the injected state
if (typeof window !== 'undefined') {
const state = window.__APOLLO_STATE__
if (state) {
// If you have multiple clients, use `state.<client_id>`
cache.restore(state.defaultClient)
}
}
}
const apolloClient = new ApolloClient({
networkInterface: createNetworkInterface({
// You should use an absolute URL here
uri: 'https://api.graph.cool/simple/v1/cj1jvw20v3n310152sv0sirl7',
transportBatching: true,
}),
link: httpLink,
cache,
...(ssr ? {
// Set this on the server to optimize queries when SSR
ssrMode: true,
} : {
// Inject the state on the client
initialState,
// This will temporary disable query force-fetching
ssrForceFetchDelay: 100,
}),
@@ -1463,6 +1520,282 @@ router.onReady(() => {
})
```
## Query components
(WIP) You can use the `ApolloQuery` (or `apollo-query`) component to make watched Apollo queries directly in your template:
```html
<ApolloQuery
:query="require('../graphql/HelloWorld.gql')"
:variables="{ name }"
>
<template slot-scope="{ result: { loading, error, data } }">
<!-- Loading -->
<div v-if="loading" class="loading apollo">Loading...</div>
<!-- Error -->
<div v-else-if="error" class="error apollo">An error occured</div>
<!-- Result -->
<div v-else-if="data" class="result apollo">{{ data.hello }}</div>
<!-- No result -->
<div v-else class="no-result apollo">No result :(</div>
</template>
</ApolloQuery>
```
Props:
- `query`: GraphQL query (transformed by `graphql-tag`)
- `variables`: Object of GraphQL variables
- `fetchPolicy`: See [apollo fetchPolicy](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-fetchPolicy)
- `pollInterval`: See [apollo pollInterval](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-pollInterval)
- `notifyOnNetworkStatusChange`: See [apollo notifyOnNetworkStatusChange](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-notifyOnNetworkStatusChange)
- `context`: See [apollo context](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-context)
- `skip`: Boolean disabling query fetching
- `clienId`: Used to resolve the Apollo Client used (defined in ApolloProvider)
- `tag`: String HTML tag name (default: `div`)
Scoped slot props:
- `result`: Apollo Query result
- `result.data`: Data returned by the query
- `result.loading`: Boolean indicating that a request is in flight
- `result.error`: Eventual error for the current result
- `result.networkStatus`: See [apollo networkStatus](https://www.apollographql.com/docs/react/basics/queries.html#graphql-query-data-networkStatus)
- `query`: Smart Query associated with the component
(WIP) You can subscribe to mode data with the `ApolloSubscribeToMore` (or `apollo-subscribe-to-more`) component:
```html
<template>
<ApolloQuery>
<ApolloSubscribeToMore
:document="require('../gql/MessageAdded.gql')"
:variables="{ channel }"
:updateQuery="onMessageAdded"
/>
</ApolloQuery>
</template>
<script>
export default {
data () {
return {
channel: 'general',
}
},
methods: {
onMessageAdded (previousResult, { subscriptionData }) {
// The previous result is immutable
const newResult = {
messages: [...previousResult.messages],
}
// Add the question to the list
newResult.messages.push(subscriptionData.data.messageAdded)
return newResult
},
},
}
</script>
```
*You can put as many of those as you want inside a `<ApolloQuery>` component.*
---
# Migration
## Migrating from vue-apollo 2.x and apollo 1.x
The main changes are related to the apollo client setup. Your components code shouldn't be affected. Apollo now uses a more flexible [apollo-link](https://github.com/apollographql/apollo-link) system that allows compositing multiple links together to add more features (like batching, offline support and more).
### Installation
#### Packages
Before:
```
npm install --save vue-apollo apollo-client
```
After:
```
npm install --save vue-apollo@next graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
```
#### Imports
Before:
```js
import Vue from 'vue'
import { ApolloClient, createBatchingNetworkInterface } from 'apollo-client'
import VueApollo from 'vue-apollo'
```
After:
```js
import Vue from 'vue'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
```
#### Plugin Setup
Before:
```js
// Create the apollo client
const apolloClient = new ApolloClient({
networkInterface: createBatchingNetworkInterface({
uri: 'http://localhost:3020/graphql',
}),
connectToDevTools: true,
})
// Install the vue plugin
Vue.use(VueApollo)
```
After:
```js
const httpLink = new HttpLink({
// You should use an absolute URL here
uri: 'http://localhost:3020/graphql',
})
// Create the apollo client
const apolloClient = new ApolloClient({
link: httpLink,
cache: new InMemoryCache(),
connectToDevTools: true,
})
// Install the vue plugin
Vue.use(VueApollo)
```
### Mutations
Query reducers have been removed. Use the `update` API to update the cache now.
### Subscriptions
#### Packages
Before:
```
npm install --save subscriptions-transport-ws
```
After:
```
npm install --save apollo-link-ws apollo-utilities
```
#### Imports
Before:
```js
import { SubscriptionClient, addGraphQLSubscriptions } from 'subscriptions-transport-ws'
```
After:
```js
import { split } from 'apollo-link'
import { WebSocketLink } from 'apollo-link-ws'
import { getMainDefinition } from 'apollo-utilities'
```
#### Apollo Setup
Before:
```js
// Create the network interface
const networkInterface = createNetworkInterface({
uri: 'http://localhost:3000/graphql',
transportBatching: true,
})
// Create the subscription websocket client
const wsClient = new SubscriptionClient('ws://localhost:3000/subscriptions', {
reconnect: true,
})
// Extend the network interface with the subscription client
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
networkInterface,
wsClient,
)
// Create the apollo client with the new network interface
const apolloClient = new ApolloClient({
networkInterface: networkInterfaceWithSubscriptions,
connectToDevTools: true,
})
// Install the plugin like before
Vue.use(VueApollo)
```
After:
```js
const httpLink = new HttpLink({
// You should use an absolute URL here
uri: 'http://localhost:3020/graphql',
})
// Create the subscription websocket link
const wsLink = new WebSocketLink({
uri: 'ws://localhost:3000/subscriptions',
options: {
reconnect: true,
},
})
// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const link = split(
// split based on operation type
({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' &&
operation === 'subscription'
},
wsLink,
httpLink
)
// Create the apollo client
const apolloClient = new ApolloClient({
link,
cache: new InMemoryCache(),
connectToDevTools: true,
})
// Install the vue plugin like before
Vue.use(VueApollo)
```
<br>
Learn more at the [official apollo documentation](https://www.apollographql.com/docs/react/2.0-migration.html).
---
# API Reference
+26
View File
@@ -0,0 +1,26 @@
import babel from 'rollup-plugin-babel'
import cjs from 'rollup-plugin-commonjs'
import replace from 'rollup-plugin-replace'
import resolve from 'rollup-plugin-node-resolve'
const config = require('../package.json')
export default {
input: 'src/index.js',
plugins: [
resolve({
jsnext: true,
main: true,
browser: true,
}),
cjs({
exclude: 'src/**',
}),
babel({
exclude: 'node_modules/**',
}),
replace({
VERSION: JSON.stringify(config.version),
}),
],
}
@@ -1,11 +1,13 @@
import base from './rollup.config.base'
import uglify from 'rollup-plugin-uglify'
import { minify } from 'uglify-js-harmony'
import { minify } from 'uglify-es'
const config = Object.assign({}, base, {
dest: 'dist/vue-apollo.min.js',
format: 'iife',
moduleName: 'VueApollo',
output: {
file: 'dist/vue-apollo.min.js',
format: 'iife',
name: 'VueApollo',
},
})
config.plugins.push(uglify({}, minify))
@@ -1,8 +1,11 @@
import base from './rollup.config.base'
const config = Object.assign({}, base, {
dest: 'dist/vue-apollo.esm.js',
format: 'es',
output: {
file: 'dist/vue-apollo.esm.js',
format: 'es',
name: 'vue-apollo',
},
})
export default config
@@ -1,8 +1,11 @@
import base from './rollup.config.base'
const config = Object.assign({}, base, {
dest: 'dist/vue-apollo.umd.js',
format: 'umd',
output: {
file: 'dist/vue-apollo.umd.js',
format: 'umd',
name: 'vue-apollo',
},
})
export default config
+426 -97
View File
@@ -1619,7 +1619,7 @@ var now = function() {
* // Cancel the trailing debounced invocation.
* jQuery(window).on('popstate', debounced.cancel);
*/
function debounce$1(func, wait, options) {
function debounce(func, wait, options) {
var lastArgs,
lastThis,
maxWait,
@@ -1785,7 +1785,7 @@ function debounce$1(func, wait, options) {
* // Cancel the trailing throttled invocation.
* jQuery(window).on('popstate', throttled.cancel);
*/
function throttle$1(func, wait, options) {
function throttle(func, wait, options) {
var leading = true,
trailing = true;
@@ -1796,7 +1796,7 @@ function throttle$1(func, wait, options) {
leading = 'leading' in options ? !!options.leading : leading;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
return debounce$1(func, wait, {
return debounce(func, wait, {
'leading': leading,
'maxWait': wait,
'trailing': trailing
@@ -1927,7 +1927,7 @@ function toNumber(value) {
: (reIsBadHex.test(value) ? NAN : +value);
}
var lodash_throttle = throttle$1;
var lodash_throttle = throttle;
/**
* lodash (Custom Build) <https://lodash.com/>
@@ -2059,7 +2059,7 @@ var now$1 = function() {
* // Cancel the trailing debounced invocation.
* jQuery(window).on('popstate', debounced.cancel);
*/
function debounce$2(func, wait, options) {
function debounce$1(func, wait, options) {
var lastArgs,
lastThis,
maxWait,
@@ -2305,7 +2305,7 @@ function toNumber$1(value) {
: (reIsBadHex$1.test(value) ? NAN$1 : +value);
}
var lodash_debounce = debounce$2;
var lodash_debounce = debounce$1;
var Globals = {};
@@ -2319,9 +2319,9 @@ function factory(action) {
};
}
var throttle = factory(lodash_throttle);
var throttle$1 = factory(lodash_throttle);
var debounce = factory(lodash_debounce);
var debounce$2 = factory(lodash_debounce);
function getMergedDefinition(def) {
return Globals.Vue.util.mergeOptions({}, def);
@@ -2334,8 +2334,6 @@ function reapply(options, context) {
return options;
}
var VUE_APOLLO_QUERY_KEYWORDS = ['variables', 'watch', 'update', 'result', 'error', 'loadingKey', 'watchLoading', 'skip', 'throttle', 'debounce', 'subscribeToMore', 'prefetch', 'manual'];
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
@@ -2510,6 +2508,7 @@ var SmartApollo = function () {
this.options = Object.assign({}, options);
this._skip = false;
this._watchers = [];
this._destroyed = false;
// Query callback
if (typeof this.options.query === 'function') {
@@ -2530,6 +2529,16 @@ var SmartApollo = function () {
}));
}
// Apollo context
if (typeof this.options.context === 'function') {
var cb = this.options.context.bind(this.vm);
this.options.context = cb();
this._watchers.push(this.vm.$watch(cb, function (context) {
_this.options.context = context;
_this.refresh();
}));
}
if (this.vm.$isServer) {
this.options.fetchPolicy = 'cache-first';
}
@@ -2575,8 +2584,8 @@ var SmartApollo = function () {
this.starting = true;
if (typeof this.options.variables === 'function') {
var cb = this.executeApollo.bind(this);
cb = this.options.throttle ? throttle(cb, this.options.throttle) : cb;
cb = this.options.debounce ? debounce(cb, this.options.debounce) : cb;
cb = this.options.throttle ? throttle$1(cb, this.options.throttle) : cb;
cb = this.options.debounce ? debounce$2(cb, this.options.debounce) : cb;
this.unwatchVariables = this.vm.$watch(function () {
return _this2.options.variables.call(_this2.vm);
}, cb, {
@@ -2676,6 +2685,9 @@ var SmartApollo = function () {
}, {
key: 'destroy',
value: function destroy() {
if (this._destroyed) return;
this._destroyed = true;
this.stop();
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
@@ -2719,6 +2731,8 @@ var SmartApollo = function () {
return SmartApollo;
}();
var VUE_APOLLO_QUERY_KEYWORDS = ['variables', 'watch', 'update', 'result', 'error', 'loadingKey', 'watchLoading', 'skip', 'throttle', 'debounce', 'subscribeToMore', 'prefetch', 'manual'];
var SmartQuery = function (_SmartApollo) {
inherits(SmartQuery, _SmartApollo);
@@ -2734,12 +2748,19 @@ var SmartQuery = function (_SmartApollo) {
};
}
var _this3 = possibleConstructorReturn(this, (SmartQuery.__proto__ || Object.getPrototypeOf(SmartQuery)).call(this, vm, key, options, autostart));
// Add reactive data related to the query
if (vm.$data.$apolloData && !vm.$data.$apolloData.queries[key]) {
vm.$set(vm.$data.$apolloData.queries, key, {
loading: false
});
}
_this3.type = 'query';
_this3.vueApolloSpecialKeys = VUE_APOLLO_QUERY_KEYWORDS;
_this3.loading = false;
return _this3;
var _this = possibleConstructorReturn(this, (SmartQuery.__proto__ || Object.getPrototypeOf(SmartQuery)).call(this, vm, key, options, autostart));
_this.type = 'query';
_this.vueApolloSpecialKeys = VUE_APOLLO_QUERY_KEYWORDS;
_this._loading = false;
return _this;
}
createClass(SmartQuery, [{
@@ -2774,7 +2795,11 @@ var SmartQuery = function (_SmartApollo) {
});
}
this.maySetLoading();
var currentResult = this.maySetLoading();
if (!currentResult.loading) {
this.nextResult(currentResult);
}
get(SmartQuery.prototype.__proto__ || Object.getPrototypeOf(SmartQuery.prototype), 'executeApollo', this).call(this, variables);
}
@@ -2790,6 +2815,7 @@ var SmartQuery = function (_SmartApollo) {
}
this.loading = true;
}
return currentResult;
}
}, {
key: 'nextResult',
@@ -2808,7 +2834,7 @@ var SmartQuery = function (_SmartApollo) {
// No result
} else if (typeof this.options.update === 'function') {
this.vm[this.key] = this.options.update.call(this.vm, data);
} else if (data[this.key] === undefined) {
} else if (data[this.key] === undefined && !this.options.manual) {
console.error('Missing ' + this.key + ' attribute on result', data);
} else if (!this.options.manual) {
this.vm[this.key] = data[this.key];
@@ -2829,15 +2855,15 @@ var SmartQuery = function (_SmartApollo) {
}, {
key: 'watchLoading',
value: function watchLoading() {
var _options$watchLoading, _vm$$apollo$watchLoad, _vm$$apollo$provider$2;
var _options$watchLoading, _vm$$apollo$watchLoad, _vm$$apollo$provider$;
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
this.options.watchLoading && (_options$watchLoading = this.options.watchLoading).call.apply(_options$watchLoading, [this.vm].concat(args));
this.vm.$apollo.watchLoading && (_vm$$apollo$watchLoad = this.vm.$apollo.watchLoading).call.apply(_vm$$apollo$watchLoad, [this.vm].concat(args));
this.vm.$apollo.provider.watchLoading && (_vm$$apollo$provider$2 = this.vm.$apollo.provider.watchLoading).call.apply(_vm$$apollo$provider$2, [this.vm].concat(args));
this.vm.$apollo.provider.watchLoading && (_vm$$apollo$provider$ = this.vm.$apollo.provider.watchLoading).call.apply(_vm$$apollo$provider$, [this.vm].concat(args));
}
}, {
key: 'applyLoadingModifier',
@@ -2860,7 +2886,7 @@ var SmartQuery = function (_SmartApollo) {
}, {
key: 'fetchMore',
value: function fetchMore() {
var _this4 = this;
var _this2 = this;
if (this.observer) {
var _observer;
@@ -2868,7 +2894,7 @@ var SmartQuery = function (_SmartApollo) {
this.maySetLoading(true);
return (_observer = this.observer).fetchMore.apply(_observer, arguments).then(function (result) {
if (!result.loading) {
_this4.loadingDone();
_this2.loadingDone();
}
return result;
});
@@ -2888,13 +2914,13 @@ var SmartQuery = function (_SmartApollo) {
}, {
key: 'refetch',
value: function refetch(variables) {
var _this5 = this;
var _this3 = this;
variables && (this.options.variables = variables);
if (this.observer) {
var result = this.observer.refetch(variables).then(function (result) {
if (!result.loading) {
_this5.loadingDone();
_this3.loadingDone();
}
return result;
});
@@ -2940,6 +2966,25 @@ var SmartQuery = function (_SmartApollo) {
return (_observer4 = this.observer).stopPolling.apply(_observer4, arguments);
}
}
}, {
key: 'client',
get: function get$$1() {
return this.vm.$apollo.getClient(this.options);
}
}, {
key: 'loading',
get: function get$$1() {
return this.vm.$data.$apolloData ? this.vm.$data.$apolloData.queries[this.key].loading : this._loading;
},
set: function set$$1(value) {
if (this._loading !== value) {
this._loading = value;
if (this.vm.$data.$apolloData) {
this.vm.$data.$apolloData.queries[this.key].loading = value;
this.vm.$data.$apolloData.loading += value ? 1 : -1;
}
}
}
}, {
key: 'loadingKey',
get: function get$$1() {
@@ -2949,21 +2994,21 @@ var SmartQuery = function (_SmartApollo) {
return SmartQuery;
}(SmartApollo);
var SmartSubscription = function (_SmartApollo2) {
inherits(SmartSubscription, _SmartApollo2);
var SmartSubscription = function (_SmartApollo) {
inherits(SmartSubscription, _SmartApollo);
function SmartSubscription() {
var _ref;
var _temp, _this6, _ret;
var _temp, _this, _ret;
classCallCheck(this, SmartSubscription);
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this6 = possibleConstructorReturn(this, (_ref = SmartSubscription.__proto__ || Object.getPrototypeOf(SmartSubscription)).call.apply(_ref, [this].concat(args))), _this6), _this6.type = 'subscription', _this6.vueApolloSpecialKeys = ['variables', 'result', 'error', 'throttle', 'debounce', 'linkedQuery'], _temp), possibleConstructorReturn(_this6, _ret);
return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = SmartSubscription.__proto__ || Object.getPrototypeOf(SmartSubscription)).call.apply(_ref, [this].concat(args))), _this), _this.type = 'subscription', _this.vueApolloSpecialKeys = ['variables', 'result', 'error', 'throttle', 'debounce', 'linkedQuery'], _temp), possibleConstructorReturn(_this, _ret);
}
createClass(SmartSubscription, [{
@@ -3029,7 +3074,9 @@ var DollarApollo = function () {
}
}, {
key: 'getClient',
value: function getClient(options) {
value: function getClient() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
if (!options || !options.client) {
if (_typeof(this.client) === 'object') {
return this.client;
@@ -3183,7 +3230,12 @@ var DollarApollo = function () {
}, {
key: 'provider',
get: function get$$1() {
return this._apolloProvider || this.vm.$root._apolloProvider;
return this.vm.$apolloProvider;
}
}, {
key: 'loading',
get: function get$$1() {
return this.vm.$data.$apolloData && this.vm.$data.$apolloData.loading !== 0;
}
}, {
key: 'skipAllQueries',
@@ -3209,7 +3261,7 @@ var DollarApollo = function () {
return DollarApollo;
}();
var ApolloProvider$1 = function () {
var ApolloProvider = function () {
function ApolloProvider(options) {
classCallCheck(this, ApolloProvider);
@@ -3226,16 +3278,23 @@ var ApolloProvider$1 = function () {
}
createClass(ApolloProvider, [{
key: 'willPrefetchQuery',
value: function willPrefetchQuery(queryOptions, client) {
key: 'provide',
value: function provide() {
var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '$apolloProvider';
return defineProperty({}, key, this);
}
}, {
key: 'addQueryToPrefetch',
value: function addQueryToPrefetch(queryOptions, client) {
this.prefetchQueries.push({
queryOptions: queryOptions,
client: client
});
}
}, {
key: 'willPrefetch',
value: function willPrefetch(component) {
key: 'prefetchComponent',
value: function prefetchComponent(component, context) {
component = getMergedDefinition(component);
var apolloOptions = component.apollo;
@@ -3247,13 +3306,13 @@ var ApolloProvider$1 = function () {
for (var key in apolloOptions) {
var options = apolloOptions[key];
if (key.charAt(0) !== '$' && (!options.query || (typeof options.ssr === 'undefined' || options.ssr) && typeof options.prefetch !== 'undefined' && options.prefetch)) {
this.willPrefetchQuery(options, options.client || componentClient);
this.addQueryToPrefetch(options, options.client || componentClient);
}
}
}
}, {
key: 'willPrefetchComponents',
value: function willPrefetchComponents(definitions) {
key: 'prefetchComponents',
value: function prefetchComponents(definitions) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
@@ -3262,7 +3321,7 @@ var ApolloProvider$1 = function () {
for (var _iterator = definitions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var def = _step.value;
this.willPrefetch(def);
this.prefetchComponent(def);
}
} catch (err) {
_didIteratorError = true;
@@ -3295,11 +3354,23 @@ var ApolloProvider$1 = function () {
}, options);
if (components) {
this.willPrefetchComponents(components);
this.prefetchComponents(components);
}
if (finalOptions.includeGlobal) {
this.willPrefetchComponents(globalPrefetchs);
this.prefetchComponents(globalPrefetchs.filter(function (_ref2) {
var component = _ref2.component,
contextCallback = _ref2.contextCallback;
var result = true;
if (typeof contextCallback === 'function') {
result = !!contextCallback(context);
}
return result;
}).map(function (_ref3) {
var component = _ref3.component;
return component;
}), context);
}
return Promise.all(this.prefetchQueries.map(function (o) {
@@ -3376,7 +3447,7 @@ var ApolloProvider$1 = function () {
var states = {};
for (var key in this.clients) {
var client = this.clients[key];
var state = defineProperty({}, client.reduxRootKey || 'apollo', client.getInitialState());
var state = client.cache.extract();
states['' + finalOptions.exportNamespace + key] = state;
}
return states;
@@ -3399,30 +3470,277 @@ var ApolloProvider$1 = function () {
var globalPrefetchs = [];
function willPrefetch(component) {
globalPrefetchs.push(component);
var contextCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
globalPrefetchs.push({ component: component, contextCallback: contextCallback });
return component;
}
// Global access for libraries
if (typeof window !== 'undefined') {
window.vueApolloWillPrefetch = willPrefetch;
} else if (typeof global !== 'undefined') {
global.vueApolloWillPrefetch = willPrefetch;
}
function isDataFilled(data) {
return Object.keys(data).length > 0;
}
var CApolloQuery = {
name: 'ApolloQuery',
provide: function provide() {
return {
getDollarApollo: this.getDollarApollo,
getApolloQuery: this.getApolloQuery
};
},
props: {
query: {
type: Object,
required: true
},
variables: {
type: Object,
default: null
},
fetchPolicy: {
type: String,
default: 'cache-first'
},
pollInterval: {
type: Number,
default: 0
},
notifyOnNetworkStatusChange: {
type: Boolean,
default: false
},
context: {
type: Object,
default: null
},
skip: {
type: Boolean,
default: false
},
clientId: {
type: String,
default: undefined
},
tag: {
type: String,
default: 'div'
}
},
data: function data() {
return {
result: {
data: null,
loading: false,
networkStatus: 7,
error: null
}
};
},
watch: {
fetchPolicy: function fetchPolicy(value) {
this.$apollo.queries.query.setOptions({
fetchPolicy: value
});
},
pollInterval: function pollInterval(value) {
this.$apollo.queries.query.setOptions({
pollInterval: value
});
},
notifyOnNetworkStatusChange: function notifyOnNetworkStatusChange(value) {
this.$apollo.queries.query.setOptions({
notifyOnNetworkStatusChange: value
});
}
},
apollo: {
$client: function $client() {
return this.clientId;
},
query: function query() {
return {
query: function query() {
return this.query;
},
variables: function variables() {
return this.variables;
},
fetchPolicy: this.fetchPolicy,
pollInterval: this.pollInterval,
notifyOnNetworkStatusChange: this.notifyOnNetworkStatusChange,
context: function context() {
return this.context;
},
skip: function skip() {
return this.skip;
},
manual: true,
result: function result(_result) {
var _result2 = _result,
errors = _result2.errors,
loading = _result2.loading,
networkStatus = _result2.networkStatus;
var _result3 = _result,
error = _result3.error;
_result = Object.assign({}, _result);
if (errors && errors.length) {
error = new Error('Apollo errors occured (' + errors.length + ')');
error.graphQLErrors = errors;
}
var data = {};
if (loading) {
Object.assign(data, this.$_previousData, _result.data);
} else if (error) {
Object.assign(data, this.$apollo.queries.query.observer.getLastResult() || {}, _result.data);
} else {
data = _result.data;
this.$_previousData = _result.data;
}
this.result = {
data: isDataFilled(data) ? data : undefined,
loading: loading,
error: error,
networkStatus: networkStatus
};
},
error: function error(_error) {
this.result.loading = false;
this.result.error = _error;
console.log(this.$apollo.queries.query.observer.currentResult());
}
};
}
},
methods: {
getDollarApollo: function getDollarApollo() {
return this.$apollo;
},
getApolloQuery: function getApolloQuery() {
return this.$apollo.queries.query;
}
},
render: function render(h) {
var result = this.$scopedSlots.default({
result: this.result,
query: this.$apollo.queries.query
});
if (Array.isArray(result)) {
result.concat(this.$slots.default);
} else {
result = [result].concat(this.$slots.default);
}
return h(this.tag, result);
}
};
var uid = 0;
var CApolloSubscribeToMore = {
name: 'ApolloSubscribeToMore',
inject: ['getDollarApollo', 'getApolloQuery'],
props: {
document: {
type: Object,
required: true
},
variables: {
type: Object,
default: null
},
updateQuery: {
type: Function,
default: null
}
},
watch: {
document: 'refresh',
variables: 'refresh'
},
created: function created() {
this.$_key = 'sub_component_' + uid++;
},
mounted: function mounted() {
this.refresh();
},
beforeDestroy: function beforeDestroy() {
this.destroy();
},
methods: {
destroy: function destroy() {
if (this.$_sub) {
this.$_sub.destroy();
}
},
refresh: function refresh() {
this.destroy();
this.$_sub = this.getDollarApollo().addSmartSubscription(this.$_key, {
document: this.document,
variables: this.variables,
updateQuery: this.updateQuery,
linkedQuery: this.getApolloQuery()
});
console.log(this.$_key, this.$_sub);
}
},
render: function render(h) {
return null;
}
};
var keywords = ['$subscribe'];
var prepare = function prepare() {
var apolloProvider = void 0;
if (this.$options.apolloProvider) {
apolloProvider = this._apolloProvider = this.$options.apolloProvider;
} else {
apolloProvider = this.$root._apolloProvider;
}
var launch = function launch() {
var apolloProvider = this.$apolloProvider;
if (this._apolloPrepared) return;
this._apolloPrepared = true;
if (this._apolloLaunched || !apolloProvider) return;
this._apolloLaunched = true;
// Prepare properties
var apollo = this.$options.apollo;
if (apollo) {
this._apolloQueries = {};
this._apolloInitData = {};
if (!apollo.$init) {
apollo.$init = true;
@@ -3432,22 +3750,6 @@ var prepare = function prepare() {
}
}
// watchQuery
for (var key in apollo) {
if (key.charAt(0) !== '$') {
this._apolloInitData[key] = null;
this._apolloQueries[key] = apollo[key];
}
}
}
};
var launch = function launch() {
if (this._apolloLaunched) return;
this._apolloLaunched = true;
var apollo = this.$options.apollo;
if (apollo) {
defineReactiveSetter(this.$apollo, 'skipAll', apollo.$skipAll);
defineReactiveSetter(this.$apollo, 'skipAllQueries', apollo.$skipAllQueries);
defineReactiveSetter(this.$apollo, 'skipAllSubscriptions', apollo.$skipAllSubscriptions);
@@ -3455,16 +3757,14 @@ var launch = function launch() {
defineReactiveSetter(this.$apollo, 'loadingKey', apollo.$loadingKey);
defineReactiveSetter(this.$apollo, 'error', apollo.$error);
defineReactiveSetter(this.$apollo, 'watchLoading', apollo.$watchLoading);
}
if (this._apolloQueries) {
// watchQuery
for (var key in this._apolloQueries) {
this.$apollo.addSmartQuery(key, this._apolloQueries[key]);
for (var key in apollo) {
if (key.charAt(0) !== '$') {
this.$apollo.addSmartQuery(key, apollo[key]);
}
}
}
if (apollo) {
if (apollo.subscribe) {
Globals.Vue.util.warn('vue-apollo -> `subscribe` option is deprecated. Use the `$subscribe` option instead.');
}
@@ -3513,7 +3813,7 @@ function install(Vue, options) {
// Lazy creation
Object.defineProperty(Vue.prototype, '$apollo', {
get: function get() {
get: function get$$1() {
if (!this._apollo) {
this._apollo = new DollarApollo(this);
}
@@ -3521,18 +3821,32 @@ function install(Vue, options) {
}
});
Vue.mixin({
var vueVersion = Vue.version.substr(0, Vue.version.indexOf('.'));
// Vue 1.x
init: prepare,
// Vue 2.x
beforeCreate: prepare,
// Better devtools support
data: function data() {
return this._apolloInitData || {};
Vue.mixin(_extends({}, vueVersion === '1' ? {
init: function init() {
var apolloProvider = void 0;
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: function data() {
return this.$options.apollo ? {
'$apolloData': {
queries: {},
loading: 0
}
} : {};
}
} : {}, {
created: launch,
@@ -3543,12 +3857,26 @@ function install(Vue, options) {
}
}
});
}));
if (vueVersion === '2') {
Vue.component('apollo-query', CApolloQuery);
Vue.component('ApolloQuery', CApolloQuery);
Vue.component('apollo-subscribe-to-more', CApolloSubscribeToMore);
Vue.component('ApolloSubscribeToMore', CApolloSubscribeToMore);
}
}
ApolloProvider$1.install = install;
ApolloProvider.install = install;
var ApolloProvider$$1 = ApolloProvider$1;
// eslint-disable-next-line no-undef
ApolloProvider.version = "3.0.0-beta.1";
// Apollo provider
var ApolloProvider$1 = ApolloProvider;
// Components
var ApolloQuery = CApolloQuery;
var ApolloSubscribeToMore = CApolloSubscribeToMore;
// Auto-install
var GlobalVue = null;
@@ -3558,7 +3886,8 @@ if (typeof window !== 'undefined') {
GlobalVue = global.Vue;
}
if (GlobalVue) {
GlobalVue.use(ApolloProvider$1);
GlobalVue.use(ApolloProvider);
}
export { install, ApolloProvider$$1 as ApolloProvider, willPrefetch };export default ApolloProvider$1;
export default ApolloProvider;
export { install, ApolloProvider$1 as ApolloProvider, ApolloQuery, ApolloSubscribeToMore, willPrefetch };
+1 -1
View File
File diff suppressed because one or more lines are too long
+429 -99
View File
@@ -1,7 +1,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global['vue-apollo'] = global['vue-apollo'] || {})));
(factory((global['vue-apollo'] = {})));
}(this, (function (exports) { 'use strict';
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -1625,7 +1625,7 @@ var now = function() {
* // Cancel the trailing debounced invocation.
* jQuery(window).on('popstate', debounced.cancel);
*/
function debounce$1(func, wait, options) {
function debounce(func, wait, options) {
var lastArgs,
lastThis,
maxWait,
@@ -1791,7 +1791,7 @@ function debounce$1(func, wait, options) {
* // Cancel the trailing throttled invocation.
* jQuery(window).on('popstate', throttled.cancel);
*/
function throttle$1(func, wait, options) {
function throttle(func, wait, options) {
var leading = true,
trailing = true;
@@ -1802,7 +1802,7 @@ function throttle$1(func, wait, options) {
leading = 'leading' in options ? !!options.leading : leading;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
return debounce$1(func, wait, {
return debounce(func, wait, {
'leading': leading,
'maxWait': wait,
'trailing': trailing
@@ -1933,7 +1933,7 @@ function toNumber(value) {
: (reIsBadHex.test(value) ? NAN : +value);
}
var lodash_throttle = throttle$1;
var lodash_throttle = throttle;
/**
* lodash (Custom Build) <https://lodash.com/>
@@ -2065,7 +2065,7 @@ var now$1 = function() {
* // Cancel the trailing debounced invocation.
* jQuery(window).on('popstate', debounced.cancel);
*/
function debounce$2(func, wait, options) {
function debounce$1(func, wait, options) {
var lastArgs,
lastThis,
maxWait,
@@ -2311,7 +2311,7 @@ function toNumber$1(value) {
: (reIsBadHex$1.test(value) ? NAN$1 : +value);
}
var lodash_debounce = debounce$2;
var lodash_debounce = debounce$1;
var Globals = {};
@@ -2325,9 +2325,9 @@ function factory(action) {
};
}
var throttle = factory(lodash_throttle);
var throttle$1 = factory(lodash_throttle);
var debounce = factory(lodash_debounce);
var debounce$2 = factory(lodash_debounce);
function getMergedDefinition(def) {
return Globals.Vue.util.mergeOptions({}, def);
@@ -2340,8 +2340,6 @@ function reapply(options, context) {
return options;
}
var VUE_APOLLO_QUERY_KEYWORDS = ['variables', 'watch', 'update', 'result', 'error', 'loadingKey', 'watchLoading', 'skip', 'throttle', 'debounce', 'subscribeToMore', 'prefetch', 'manual'];
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
@@ -2516,6 +2514,7 @@ var SmartApollo = function () {
this.options = Object.assign({}, options);
this._skip = false;
this._watchers = [];
this._destroyed = false;
// Query callback
if (typeof this.options.query === 'function') {
@@ -2536,6 +2535,16 @@ var SmartApollo = function () {
}));
}
// Apollo context
if (typeof this.options.context === 'function') {
var cb = this.options.context.bind(this.vm);
this.options.context = cb();
this._watchers.push(this.vm.$watch(cb, function (context) {
_this.options.context = context;
_this.refresh();
}));
}
if (this.vm.$isServer) {
this.options.fetchPolicy = 'cache-first';
}
@@ -2581,8 +2590,8 @@ var SmartApollo = function () {
this.starting = true;
if (typeof this.options.variables === 'function') {
var cb = this.executeApollo.bind(this);
cb = this.options.throttle ? throttle(cb, this.options.throttle) : cb;
cb = this.options.debounce ? debounce(cb, this.options.debounce) : cb;
cb = this.options.throttle ? throttle$1(cb, this.options.throttle) : cb;
cb = this.options.debounce ? debounce$2(cb, this.options.debounce) : cb;
this.unwatchVariables = this.vm.$watch(function () {
return _this2.options.variables.call(_this2.vm);
}, cb, {
@@ -2682,6 +2691,9 @@ var SmartApollo = function () {
}, {
key: 'destroy',
value: function destroy() {
if (this._destroyed) return;
this._destroyed = true;
this.stop();
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
@@ -2725,6 +2737,8 @@ var SmartApollo = function () {
return SmartApollo;
}();
var VUE_APOLLO_QUERY_KEYWORDS = ['variables', 'watch', 'update', 'result', 'error', 'loadingKey', 'watchLoading', 'skip', 'throttle', 'debounce', 'subscribeToMore', 'prefetch', 'manual'];
var SmartQuery = function (_SmartApollo) {
inherits(SmartQuery, _SmartApollo);
@@ -2740,12 +2754,19 @@ var SmartQuery = function (_SmartApollo) {
};
}
var _this3 = possibleConstructorReturn(this, (SmartQuery.__proto__ || Object.getPrototypeOf(SmartQuery)).call(this, vm, key, options, autostart));
// Add reactive data related to the query
if (vm.$data.$apolloData && !vm.$data.$apolloData.queries[key]) {
vm.$set(vm.$data.$apolloData.queries, key, {
loading: false
});
}
_this3.type = 'query';
_this3.vueApolloSpecialKeys = VUE_APOLLO_QUERY_KEYWORDS;
_this3.loading = false;
return _this3;
var _this = possibleConstructorReturn(this, (SmartQuery.__proto__ || Object.getPrototypeOf(SmartQuery)).call(this, vm, key, options, autostart));
_this.type = 'query';
_this.vueApolloSpecialKeys = VUE_APOLLO_QUERY_KEYWORDS;
_this._loading = false;
return _this;
}
createClass(SmartQuery, [{
@@ -2780,7 +2801,11 @@ var SmartQuery = function (_SmartApollo) {
});
}
this.maySetLoading();
var currentResult = this.maySetLoading();
if (!currentResult.loading) {
this.nextResult(currentResult);
}
get(SmartQuery.prototype.__proto__ || Object.getPrototypeOf(SmartQuery.prototype), 'executeApollo', this).call(this, variables);
}
@@ -2796,6 +2821,7 @@ var SmartQuery = function (_SmartApollo) {
}
this.loading = true;
}
return currentResult;
}
}, {
key: 'nextResult',
@@ -2814,7 +2840,7 @@ var SmartQuery = function (_SmartApollo) {
// No result
} else if (typeof this.options.update === 'function') {
this.vm[this.key] = this.options.update.call(this.vm, data);
} else if (data[this.key] === undefined) {
} else if (data[this.key] === undefined && !this.options.manual) {
console.error('Missing ' + this.key + ' attribute on result', data);
} else if (!this.options.manual) {
this.vm[this.key] = data[this.key];
@@ -2835,15 +2861,15 @@ var SmartQuery = function (_SmartApollo) {
}, {
key: 'watchLoading',
value: function watchLoading() {
var _options$watchLoading, _vm$$apollo$watchLoad, _vm$$apollo$provider$2;
var _options$watchLoading, _vm$$apollo$watchLoad, _vm$$apollo$provider$;
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
this.options.watchLoading && (_options$watchLoading = this.options.watchLoading).call.apply(_options$watchLoading, [this.vm].concat(args));
this.vm.$apollo.watchLoading && (_vm$$apollo$watchLoad = this.vm.$apollo.watchLoading).call.apply(_vm$$apollo$watchLoad, [this.vm].concat(args));
this.vm.$apollo.provider.watchLoading && (_vm$$apollo$provider$2 = this.vm.$apollo.provider.watchLoading).call.apply(_vm$$apollo$provider$2, [this.vm].concat(args));
this.vm.$apollo.provider.watchLoading && (_vm$$apollo$provider$ = this.vm.$apollo.provider.watchLoading).call.apply(_vm$$apollo$provider$, [this.vm].concat(args));
}
}, {
key: 'applyLoadingModifier',
@@ -2866,7 +2892,7 @@ var SmartQuery = function (_SmartApollo) {
}, {
key: 'fetchMore',
value: function fetchMore() {
var _this4 = this;
var _this2 = this;
if (this.observer) {
var _observer;
@@ -2874,7 +2900,7 @@ var SmartQuery = function (_SmartApollo) {
this.maySetLoading(true);
return (_observer = this.observer).fetchMore.apply(_observer, arguments).then(function (result) {
if (!result.loading) {
_this4.loadingDone();
_this2.loadingDone();
}
return result;
});
@@ -2894,13 +2920,13 @@ var SmartQuery = function (_SmartApollo) {
}, {
key: 'refetch',
value: function refetch(variables) {
var _this5 = this;
var _this3 = this;
variables && (this.options.variables = variables);
if (this.observer) {
var result = this.observer.refetch(variables).then(function (result) {
if (!result.loading) {
_this5.loadingDone();
_this3.loadingDone();
}
return result;
});
@@ -2946,6 +2972,25 @@ var SmartQuery = function (_SmartApollo) {
return (_observer4 = this.observer).stopPolling.apply(_observer4, arguments);
}
}
}, {
key: 'client',
get: function get$$1() {
return this.vm.$apollo.getClient(this.options);
}
}, {
key: 'loading',
get: function get$$1() {
return this.vm.$data.$apolloData ? this.vm.$data.$apolloData.queries[this.key].loading : this._loading;
},
set: function set$$1(value) {
if (this._loading !== value) {
this._loading = value;
if (this.vm.$data.$apolloData) {
this.vm.$data.$apolloData.queries[this.key].loading = value;
this.vm.$data.$apolloData.loading += value ? 1 : -1;
}
}
}
}, {
key: 'loadingKey',
get: function get$$1() {
@@ -2955,21 +3000,21 @@ var SmartQuery = function (_SmartApollo) {
return SmartQuery;
}(SmartApollo);
var SmartSubscription = function (_SmartApollo2) {
inherits(SmartSubscription, _SmartApollo2);
var SmartSubscription = function (_SmartApollo) {
inherits(SmartSubscription, _SmartApollo);
function SmartSubscription() {
var _ref;
var _temp, _this6, _ret;
var _temp, _this, _ret;
classCallCheck(this, SmartSubscription);
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this6 = possibleConstructorReturn(this, (_ref = SmartSubscription.__proto__ || Object.getPrototypeOf(SmartSubscription)).call.apply(_ref, [this].concat(args))), _this6), _this6.type = 'subscription', _this6.vueApolloSpecialKeys = ['variables', 'result', 'error', 'throttle', 'debounce', 'linkedQuery'], _temp), possibleConstructorReturn(_this6, _ret);
return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = SmartSubscription.__proto__ || Object.getPrototypeOf(SmartSubscription)).call.apply(_ref, [this].concat(args))), _this), _this.type = 'subscription', _this.vueApolloSpecialKeys = ['variables', 'result', 'error', 'throttle', 'debounce', 'linkedQuery'], _temp), possibleConstructorReturn(_this, _ret);
}
createClass(SmartSubscription, [{
@@ -3035,7 +3080,9 @@ var DollarApollo = function () {
}
}, {
key: 'getClient',
value: function getClient(options) {
value: function getClient() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
if (!options || !options.client) {
if (_typeof(this.client) === 'object') {
return this.client;
@@ -3189,7 +3236,12 @@ var DollarApollo = function () {
}, {
key: 'provider',
get: function get$$1() {
return this._apolloProvider || this.vm.$root._apolloProvider;
return this.vm.$apolloProvider;
}
}, {
key: 'loading',
get: function get$$1() {
return this.vm.$data.$apolloData && this.vm.$data.$apolloData.loading !== 0;
}
}, {
key: 'skipAllQueries',
@@ -3215,7 +3267,7 @@ var DollarApollo = function () {
return DollarApollo;
}();
var ApolloProvider$1 = function () {
var ApolloProvider = function () {
function ApolloProvider(options) {
classCallCheck(this, ApolloProvider);
@@ -3232,16 +3284,23 @@ var ApolloProvider$1 = function () {
}
createClass(ApolloProvider, [{
key: 'willPrefetchQuery',
value: function willPrefetchQuery(queryOptions, client) {
key: 'provide',
value: function provide() {
var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '$apolloProvider';
return defineProperty({}, key, this);
}
}, {
key: 'addQueryToPrefetch',
value: function addQueryToPrefetch(queryOptions, client) {
this.prefetchQueries.push({
queryOptions: queryOptions,
client: client
});
}
}, {
key: 'willPrefetch',
value: function willPrefetch(component) {
key: 'prefetchComponent',
value: function prefetchComponent(component, context) {
component = getMergedDefinition(component);
var apolloOptions = component.apollo;
@@ -3253,13 +3312,13 @@ var ApolloProvider$1 = function () {
for (var key in apolloOptions) {
var options = apolloOptions[key];
if (key.charAt(0) !== '$' && (!options.query || (typeof options.ssr === 'undefined' || options.ssr) && typeof options.prefetch !== 'undefined' && options.prefetch)) {
this.willPrefetchQuery(options, options.client || componentClient);
this.addQueryToPrefetch(options, options.client || componentClient);
}
}
}
}, {
key: 'willPrefetchComponents',
value: function willPrefetchComponents(definitions) {
key: 'prefetchComponents',
value: function prefetchComponents(definitions) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
@@ -3268,7 +3327,7 @@ var ApolloProvider$1 = function () {
for (var _iterator = definitions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var def = _step.value;
this.willPrefetch(def);
this.prefetchComponent(def);
}
} catch (err) {
_didIteratorError = true;
@@ -3301,11 +3360,23 @@ var ApolloProvider$1 = function () {
}, options);
if (components) {
this.willPrefetchComponents(components);
this.prefetchComponents(components);
}
if (finalOptions.includeGlobal) {
this.willPrefetchComponents(globalPrefetchs);
this.prefetchComponents(globalPrefetchs.filter(function (_ref2) {
var component = _ref2.component,
contextCallback = _ref2.contextCallback;
var result = true;
if (typeof contextCallback === 'function') {
result = !!contextCallback(context);
}
return result;
}).map(function (_ref3) {
var component = _ref3.component;
return component;
}), context);
}
return Promise.all(this.prefetchQueries.map(function (o) {
@@ -3382,7 +3453,7 @@ var ApolloProvider$1 = function () {
var states = {};
for (var key in this.clients) {
var client = this.clients[key];
var state = defineProperty({}, client.reduxRootKey || 'apollo', client.getInitialState());
var state = client.cache.extract();
states['' + finalOptions.exportNamespace + key] = state;
}
return states;
@@ -3405,30 +3476,277 @@ var ApolloProvider$1 = function () {
var globalPrefetchs = [];
function willPrefetch(component) {
globalPrefetchs.push(component);
var contextCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
globalPrefetchs.push({ component: component, contextCallback: contextCallback });
return component;
}
// Global access for libraries
if (typeof window !== 'undefined') {
window.vueApolloWillPrefetch = willPrefetch;
} else if (typeof global !== 'undefined') {
global.vueApolloWillPrefetch = willPrefetch;
}
function isDataFilled(data) {
return Object.keys(data).length > 0;
}
var CApolloQuery = {
name: 'ApolloQuery',
provide: function provide() {
return {
getDollarApollo: this.getDollarApollo,
getApolloQuery: this.getApolloQuery
};
},
props: {
query: {
type: Object,
required: true
},
variables: {
type: Object,
default: null
},
fetchPolicy: {
type: String,
default: 'cache-first'
},
pollInterval: {
type: Number,
default: 0
},
notifyOnNetworkStatusChange: {
type: Boolean,
default: false
},
context: {
type: Object,
default: null
},
skip: {
type: Boolean,
default: false
},
clientId: {
type: String,
default: undefined
},
tag: {
type: String,
default: 'div'
}
},
data: function data() {
return {
result: {
data: null,
loading: false,
networkStatus: 7,
error: null
}
};
},
watch: {
fetchPolicy: function fetchPolicy(value) {
this.$apollo.queries.query.setOptions({
fetchPolicy: value
});
},
pollInterval: function pollInterval(value) {
this.$apollo.queries.query.setOptions({
pollInterval: value
});
},
notifyOnNetworkStatusChange: function notifyOnNetworkStatusChange(value) {
this.$apollo.queries.query.setOptions({
notifyOnNetworkStatusChange: value
});
}
},
apollo: {
$client: function $client() {
return this.clientId;
},
query: function query() {
return {
query: function query() {
return this.query;
},
variables: function variables() {
return this.variables;
},
fetchPolicy: this.fetchPolicy,
pollInterval: this.pollInterval,
notifyOnNetworkStatusChange: this.notifyOnNetworkStatusChange,
context: function context() {
return this.context;
},
skip: function skip() {
return this.skip;
},
manual: true,
result: function result(_result) {
var _result2 = _result,
errors = _result2.errors,
loading = _result2.loading,
networkStatus = _result2.networkStatus;
var _result3 = _result,
error = _result3.error;
_result = Object.assign({}, _result);
if (errors && errors.length) {
error = new Error('Apollo errors occured (' + errors.length + ')');
error.graphQLErrors = errors;
}
var data = {};
if (loading) {
Object.assign(data, this.$_previousData, _result.data);
} else if (error) {
Object.assign(data, this.$apollo.queries.query.observer.getLastResult() || {}, _result.data);
} else {
data = _result.data;
this.$_previousData = _result.data;
}
this.result = {
data: isDataFilled(data) ? data : undefined,
loading: loading,
error: error,
networkStatus: networkStatus
};
},
error: function error(_error) {
this.result.loading = false;
this.result.error = _error;
console.log(this.$apollo.queries.query.observer.currentResult());
}
};
}
},
methods: {
getDollarApollo: function getDollarApollo() {
return this.$apollo;
},
getApolloQuery: function getApolloQuery() {
return this.$apollo.queries.query;
}
},
render: function render(h) {
var result = this.$scopedSlots.default({
result: this.result,
query: this.$apollo.queries.query
});
if (Array.isArray(result)) {
result.concat(this.$slots.default);
} else {
result = [result].concat(this.$slots.default);
}
return h(this.tag, result);
}
};
var uid = 0;
var CApolloSubscribeToMore = {
name: 'ApolloSubscribeToMore',
inject: ['getDollarApollo', 'getApolloQuery'],
props: {
document: {
type: Object,
required: true
},
variables: {
type: Object,
default: null
},
updateQuery: {
type: Function,
default: null
}
},
watch: {
document: 'refresh',
variables: 'refresh'
},
created: function created() {
this.$_key = 'sub_component_' + uid++;
},
mounted: function mounted() {
this.refresh();
},
beforeDestroy: function beforeDestroy() {
this.destroy();
},
methods: {
destroy: function destroy() {
if (this.$_sub) {
this.$_sub.destroy();
}
},
refresh: function refresh() {
this.destroy();
this.$_sub = this.getDollarApollo().addSmartSubscription(this.$_key, {
document: this.document,
variables: this.variables,
updateQuery: this.updateQuery,
linkedQuery: this.getApolloQuery()
});
console.log(this.$_key, this.$_sub);
}
},
render: function render(h) {
return null;
}
};
var keywords = ['$subscribe'];
var prepare = function prepare() {
var apolloProvider = void 0;
if (this.$options.apolloProvider) {
apolloProvider = this._apolloProvider = this.$options.apolloProvider;
} else {
apolloProvider = this.$root._apolloProvider;
}
var launch = function launch() {
var apolloProvider = this.$apolloProvider;
if (this._apolloPrepared) return;
this._apolloPrepared = true;
if (this._apolloLaunched || !apolloProvider) return;
this._apolloLaunched = true;
// Prepare properties
var apollo = this.$options.apollo;
if (apollo) {
this._apolloQueries = {};
this._apolloInitData = {};
if (!apollo.$init) {
apollo.$init = true;
@@ -3438,22 +3756,6 @@ var prepare = function prepare() {
}
}
// watchQuery
for (var key in apollo) {
if (key.charAt(0) !== '$') {
this._apolloInitData[key] = null;
this._apolloQueries[key] = apollo[key];
}
}
}
};
var launch = function launch() {
if (this._apolloLaunched) return;
this._apolloLaunched = true;
var apollo = this.$options.apollo;
if (apollo) {
defineReactiveSetter(this.$apollo, 'skipAll', apollo.$skipAll);
defineReactiveSetter(this.$apollo, 'skipAllQueries', apollo.$skipAllQueries);
defineReactiveSetter(this.$apollo, 'skipAllSubscriptions', apollo.$skipAllSubscriptions);
@@ -3461,16 +3763,14 @@ var launch = function launch() {
defineReactiveSetter(this.$apollo, 'loadingKey', apollo.$loadingKey);
defineReactiveSetter(this.$apollo, 'error', apollo.$error);
defineReactiveSetter(this.$apollo, 'watchLoading', apollo.$watchLoading);
}
if (this._apolloQueries) {
// watchQuery
for (var key in this._apolloQueries) {
this.$apollo.addSmartQuery(key, this._apolloQueries[key]);
for (var key in apollo) {
if (key.charAt(0) !== '$') {
this.$apollo.addSmartQuery(key, apollo[key]);
}
}
}
if (apollo) {
if (apollo.subscribe) {
Globals.Vue.util.warn('vue-apollo -> `subscribe` option is deprecated. Use the `$subscribe` option instead.');
}
@@ -3519,7 +3819,7 @@ function install(Vue, options) {
// Lazy creation
Object.defineProperty(Vue.prototype, '$apollo', {
get: function get() {
get: function get$$1() {
if (!this._apollo) {
this._apollo = new DollarApollo(this);
}
@@ -3527,18 +3827,32 @@ function install(Vue, options) {
}
});
Vue.mixin({
var vueVersion = Vue.version.substr(0, Vue.version.indexOf('.'));
// Vue 1.x
init: prepare,
// Vue 2.x
beforeCreate: prepare,
// Better devtools support
data: function data() {
return this._apolloInitData || {};
Vue.mixin(_extends({}, vueVersion === '1' ? {
init: function init() {
var apolloProvider = void 0;
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: function data() {
return this.$options.apollo ? {
'$apolloData': {
queries: {},
loading: 0
}
} : {};
}
} : {}, {
created: launch,
@@ -3549,12 +3863,26 @@ function install(Vue, options) {
}
}
});
}));
if (vueVersion === '2') {
Vue.component('apollo-query', CApolloQuery);
Vue.component('ApolloQuery', CApolloQuery);
Vue.component('apollo-subscribe-to-more', CApolloSubscribeToMore);
Vue.component('ApolloSubscribeToMore', CApolloSubscribeToMore);
}
}
ApolloProvider$1.install = install;
ApolloProvider.install = install;
var ApolloProvider$$1 = ApolloProvider$1;
// eslint-disable-next-line no-undef
ApolloProvider.version = "3.0.0-beta.1";
// Apollo provider
var ApolloProvider$1 = ApolloProvider;
// Components
var ApolloQuery = CApolloQuery;
var ApolloSubscribeToMore = CApolloSubscribeToMore;
// Auto-install
var GlobalVue = null;
@@ -3564,12 +3892,14 @@ if (typeof window !== 'undefined') {
GlobalVue = global.Vue;
}
if (GlobalVue) {
GlobalVue.use(ApolloProvider$1);
GlobalVue.use(ApolloProvider);
}
exports.install = install;
exports.ApolloProvider = ApolloProvider$$1;
exports['default'] = ApolloProvider$1;
exports.ApolloProvider = ApolloProvider$1;
exports.ApolloQuery = ApolloQuery;
exports.ApolloSubscribeToMore = ApolloSubscribeToMore;
exports.default = ApolloProvider;
exports.willPrefetch = willPrefetch;
Object.defineProperty(exports, '__esModule', { value: true });
+35 -22
View File
@@ -1,20 +1,21 @@
{
"name": "vue-apollo",
"version": "2.1.0-rc.8",
"version": "3.0.0-beta.1",
"description": "Vue apollo integration",
"main": "dist/vue-apollo.umd.js",
"module": "dist/vue-apollo.esm.js",
"unpkg": "dist/vue-apollo.min.js",
"typings": "types/index.d.ts",
"scripts": {
"build": "npm run build:browser && npm run build:es && npm run build:umd",
"build:browser": "rollup --config rollup.config.browser.js",
"build:es": "rollup --config rollup.config.es.js",
"build:umd": "rollup --config rollup.config.umd.js",
"prepublish": "npm run build",
"dev": "npm-watch"
},
"watch": {
"build": "src/*.js"
"build:browser": "rollup --config build/rollup.config.browser.js",
"build:es": "rollup --config build/rollup.config.es.js",
"build:umd": "rollup --config build/rollup.config.umd.js",
"prepublishOnly": "npm run test && npm run build",
"dev": "nodemon --exec 'npm run build' --watch src",
"test": "npm run test:eslint && npm run test:types",
"test:eslint": "eslint --ext .js src",
"test:types": "tsc -p types/test"
},
"repository": {
"type": "git",
@@ -32,7 +33,7 @@
},
"homepage": "https://github.com/Akryum/vue-apollo#readme",
"peerDependencies": {
"apollo-client": "^1.0.1"
"apollo-client": "^2.0.0"
},
"dependencies": {
"lodash.debounce": "^4.0.8",
@@ -40,22 +41,34 @@
"lodash.throttle": "^4.1.1"
},
"devDependencies": {
"babel-cli": "^6.14.0",
"babel-eslint": "^7.1.1",
"@types/graphql": "^0.12.3",
"apollo-cache-inmemory": "^1.1.1",
"apollo-client": "^2.0.3",
"apollo-link": "^1.0.3",
"apollo-link-http": "^1.2.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.2.1",
"babel-plugin-external-helpers": "^6.22.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-env": "^1.6.1",
"babel-preset-stage-0": "^6.24.1",
"eslint": "^3.12.1",
"eslint-config-standard": "^7.1.0",
"eslint": "^4.10.0",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-node": "^6.0.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^2.0.1",
"npm-watch": "^0.1.6",
"eslint-plugin-standard": "^3.0.1",
"graphql": "^0.12.3",
"graphql-tag": "^2.5.0",
"nodemon": "^1.14.12",
"rimraf": "^2.6.1",
"rollup": "^0.41.6",
"rollup-plugin-babel": "^2.7.1",
"rollup-plugin-commonjs": "^8.0.2",
"rollup": "^0.55.3",
"rollup-plugin-babel": "^3.0.2",
"rollup-plugin-commonjs": "^8.2.6",
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-uglify": "^1.0.2",
"uglify-js-harmony": "^2.7.7"
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-uglify": "^3.0.0",
"typescript": "^2.6.2",
"uglify-es": "^3.1.6",
"vue": "^2.5.9"
}
}
-23
View File
@@ -1,23 +0,0 @@
import commonjs from 'rollup-plugin-commonjs'
import resolve from 'rollup-plugin-node-resolve'
import babel from 'rollup-plugin-babel'
export default {
entry: 'src/index.js',
exports: 'named',
moduleName: 'vue-apollo',
plugins: [
resolve({
jsnext: true,
main: true,
browser: true,
}),
commonjs(),
babel({
exclude: 'node_modules/**',
plugins: [
'external-helpers',
],
}),
],
}
+33 -10
View File
@@ -16,14 +16,20 @@ export class ApolloProvider {
this.prefetchQueries = []
}
willPrefetchQuery (queryOptions, client) {
provide (key = '$apolloProvider') {
return {
[key]: this,
}
}
addQueryToPrefetch (queryOptions, client) {
this.prefetchQueries.push({
queryOptions,
client,
})
}
willPrefetch (component) {
prefetchComponent (component, context) {
component = getMergedDefinition(component)
const apolloOptions = component.apollo
@@ -42,14 +48,14 @@ export class ApolloProvider {
)
)
) {
this.willPrefetchQuery(options, options.client || componentClient)
this.addQueryToPrefetch(options, options.client || componentClient)
}
}
}
willPrefetchComponents (definitions) {
prefetchComponents (definitions) {
for (const def of definitions) {
this.willPrefetch(def)
this.prefetchComponent(def)
}
}
@@ -65,11 +71,21 @@ export class ApolloProvider {
}, options)
if (components) {
this.willPrefetchComponents(components)
this.prefetchComponents(components)
}
if (finalOptions.includeGlobal) {
this.willPrefetchComponents(globalPrefetchs)
this.prefetchComponents(globalPrefetchs.filter(
({ component, contextCallback }) => {
let result = true
if (typeof contextCallback === 'function') {
result = !!contextCallback(context)
}
return result
}
).map(
({ component }) => component
), context)
}
return Promise.all(this.prefetchQueries.map(
@@ -147,7 +163,7 @@ export class ApolloProvider {
const states = {}
for (const key in this.clients) {
const client = this.clients[key]
const state = { [client.reduxRootKey || 'apollo']: client.getInitialState() }
const state = client.cache.extract()
states[`${finalOptions.exportNamespace}${key}`] = state
}
return states
@@ -166,7 +182,14 @@ export class ApolloProvider {
const globalPrefetchs = []
export function willPrefetch (component) {
globalPrefetchs.push(component)
export function willPrefetch (component, contextCallback = null) {
globalPrefetchs.push({ component, contextCallback })
return component
}
// Global access for libraries
if (typeof window !== 'undefined') {
window.vueApolloWillPrefetch = willPrefetch
} else if (typeof global !== 'undefined') {
global.vueApolloWillPrefetch = willPrefetch
}
+167
View File
@@ -0,0 +1,167 @@
function isDataFilled (data) {
return Object.keys(data).length > 0
}
export default {
name: 'ApolloQuery',
provide () {
return {
getDollarApollo: this.getDollarApollo,
getApolloQuery: this.getApolloQuery,
}
},
props: {
query: {
type: Object,
required: true,
},
variables: {
type: Object,
default: null,
},
fetchPolicy: {
type: String,
default: 'cache-first',
},
pollInterval: {
type: Number,
default: 0,
},
notifyOnNetworkStatusChange: {
type: Boolean,
default: false,
},
context: {
type: Object,
default: null,
},
skip: {
type: Boolean,
default: false,
},
clientId: {
type: String,
default: undefined,
},
tag: {
type: String,
default: 'div',
},
},
data () {
return {
result: {
data: null,
loading: false,
networkStatus: 7,
error: null,
},
}
},
watch: {
fetchPolicy (value) {
this.$apollo.queries.query.setOptions({
fetchPolicy: value,
})
},
pollInterval (value) {
this.$apollo.queries.query.setOptions({
pollInterval: value,
})
},
notifyOnNetworkStatusChange (value) {
this.$apollo.queries.query.setOptions({
notifyOnNetworkStatusChange: value,
})
},
},
apollo: {
$client () {
return this.clientId
},
query () {
return {
query () { return this.query },
variables () { return this.variables },
fetchPolicy: this.fetchPolicy,
pollInterval: this.pollInterval,
notifyOnNetworkStatusChange: this.notifyOnNetworkStatusChange,
context () { return this.context },
skip () { return this.skip },
manual: true,
result (result) {
const { errors, loading, networkStatus } = result
let { error } = result
result = Object.assign({}, result)
if (errors && errors.length) {
error = new Error(`Apollo errors occured (${errors.length})`)
error.graphQLErrors = errors
}
let data = {}
if (loading) {
Object.assign(data, this.$_previousData, result.data)
} else if (error) {
Object.assign(data, this.$apollo.queries.query.observer.getLastResult() || {}, result.data)
} else {
data = result.data
this.$_previousData = result.data
}
this.result = {
data: isDataFilled(data) ? data : undefined,
loading,
error,
networkStatus,
}
},
error (error) {
this.result.loading = false
this.result.error = error
console.log(this.$apollo.queries.query.observer.currentResult())
},
}
},
},
methods: {
getDollarApollo () {
return this.$apollo
},
getApolloQuery () {
return this.$apollo.queries.query
},
},
render (h) {
let result = this.$scopedSlots.default({
result: this.result,
query: this.$apollo.queries.query,
})
if (Array.isArray(result)) {
result.concat(this.$slots.default)
} else {
result = [result].concat(this.$slots.default)
}
return h(this.tag, result)
},
}
+69
View File
@@ -0,0 +1,69 @@
let uid = 0
export default {
name: 'ApolloSubscribeToMore',
inject: [
'getDollarApollo',
'getApolloQuery',
],
props: {
document: {
type: Object,
required: true,
},
variables: {
type: Object,
default: null,
},
updateQuery: {
type: Function,
default: null,
},
},
watch: {
document: 'refresh',
variables: 'refresh',
},
created () {
this.$_key = `sub_component_${uid++}`
},
mounted () {
this.refresh()
},
beforeDestroy () {
this.destroy()
},
methods: {
destroy () {
if (this.$_sub) {
this.$_sub.destroy()
}
},
refresh () {
this.destroy()
this.$_sub = this.getDollarApollo().addSmartSubscription(this.$_key, {
document: this.document,
variables: this.variables,
updateQuery: this.updateQuery,
linkedQuery: this.getApolloQuery(),
})
console.log(this.$_key, this.$_sub)
},
},
render (h) {
return null
},
}
+8 -3
View File
@@ -1,4 +1,5 @@
import { SmartQuery, SmartSubscription } from './smart-apollo'
import SmartQuery from './smart-query'
import SmartSubscription from './smart-subscription'
import { reapply } from './utils'
export class DollarApollo {
@@ -15,14 +16,14 @@ export class DollarApollo {
}
get provider () {
return this._apolloProvider || this.vm.$root._apolloProvider
return this.vm.$apolloProvider
}
query (options) {
return this.getClient(options).query(options)
}
getClient (options) {
getClient (options = null) {
if (!options || !options.client) {
if (typeof this.client === 'object') {
return this.client
@@ -75,6 +76,10 @@ export class DollarApollo {
}
}
get loading () {
return this.vm.$data.$apolloData && this.vm.$data.$apolloData.loading !== 0
}
addSmartQuery (key, options) {
options = reapply(options, this.vm)
+51 -43
View File
@@ -1,30 +1,24 @@
import omit from 'lodash.omit'
import { DollarApollo } from './dollar-apollo'
import { ApolloProvider as apolloProvider } from './apollo-provider'
import CApolloQuery from './components/ApolloQuery'
import CApolloSubscribeToMore from './components/ApolloSubscribeToMore'
import { Globals } from './utils'
const keywords = [
'$subscribe',
]
const prepare = function prepare () {
let apolloProvider
if (this.$options.apolloProvider) {
apolloProvider = this._apolloProvider = this.$options.apolloProvider
} else {
apolloProvider = this.$root._apolloProvider
}
const launch = function launch () {
const apolloProvider = this.$apolloProvider
if (this._apolloPrepared) return
this._apolloPrepared = true
if (this._apolloLaunched || !apolloProvider) return
this._apolloLaunched = true
// Prepare properties
let apollo = this.$options.apollo
if (apollo) {
this._apolloQueries = {}
this._apolloInitData = {}
if (!apollo.$init) {
apollo.$init = true
@@ -34,22 +28,6 @@ const prepare = function prepare () {
}
}
// watchQuery
for (let key in apollo) {
if (key.charAt(0) !== '$') {
this._apolloInitData[key] = null
this._apolloQueries[key] = apollo[key]
}
}
}
}
const launch = function launch () {
if (this._apolloLaunched) return
this._apolloLaunched = true
let apollo = this.$options.apollo
if (apollo) {
defineReactiveSetter(this.$apollo, 'skipAll', apollo.$skipAll)
defineReactiveSetter(this.$apollo, 'skipAllQueries', apollo.$skipAllQueries)
defineReactiveSetter(this.$apollo, 'skipAllSubscriptions', apollo.$skipAllSubscriptions)
@@ -57,16 +35,14 @@ const launch = function launch () {
defineReactiveSetter(this.$apollo, 'loadingKey', apollo.$loadingKey)
defineReactiveSetter(this.$apollo, 'error', apollo.$error)
defineReactiveSetter(this.$apollo, 'watchLoading', apollo.$watchLoading)
}
if (this._apolloQueries) {
// watchQuery
for (let key in this._apolloQueries) {
this.$apollo.addSmartQuery(key, this._apolloQueries[key])
for (let key in apollo) {
if (key.charAt(0) !== '$') {
this.$apollo.addSmartQuery(key, apollo[key])
}
}
}
if (apollo) {
if (apollo.subscribe) {
Globals.Vue.util.warn('vue-apollo -> `subscribe` option is deprecated. Use the `$subscribe` option instead.')
}
@@ -123,17 +99,35 @@ export function install (Vue, options) {
},
})
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
},
} : {},
// Vue 1.x
init: prepare,
// Vue 2.x
beforeCreate: prepare,
...vueVersion === '2' ? {
inject: {
$apolloProvider: { default: null },
},
// Better devtools support
data () {
return this._apolloInitData || {}
},
data () {
return this.$options.apollo ? {
'$apolloData': {
queries: {},
loading: 0,
},
} : {}
},
} : {},
created: launch,
@@ -145,14 +139,28 @@ export function install (Vue, options) {
},
})
if (vueVersion === '2') {
Vue.component('apollo-query', CApolloQuery)
Vue.component('ApolloQuery', CApolloQuery)
Vue.component('apollo-subscribe-to-more', CApolloSubscribeToMore)
Vue.component('ApolloSubscribeToMore', CApolloSubscribeToMore)
}
}
apolloProvider.install = install
export const ApolloProvider = apolloProvider
// 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
// Auto-install
let GlobalVue = null
if (typeof window !== 'undefined') {
+15 -232
View File
@@ -1,8 +1,7 @@
import omit from 'lodash.omit'
import { throttle, debounce } from './utils'
import { VUE_APOLLO_QUERY_KEYWORDS } from './consts'
class SmartApollo {
export default class SmartApollo {
type = null
vueApolloSpecialKeys = []
@@ -12,6 +11,7 @@ class SmartApollo {
this.options = Object.assign({}, options)
this._skip = false
this._watchers = []
this._destroyed = false
// Query callback
if (typeof this.options.query === 'function') {
@@ -32,6 +32,16 @@ class SmartApollo {
}))
}
// Apollo context
if (typeof this.options.context === 'function') {
const cb = this.options.context.bind(this.vm)
this.options.context = cb()
this._watchers.push(this.vm.$watch(cb, context => {
this.options.context = context
this.refresh()
}))
}
if (this.vm.$isServer) {
this.options.fetchPolicy = 'cache-first'
}
@@ -146,239 +156,12 @@ class SmartApollo {
}
destroy () {
if (this._destroyed) return
this._destroyed = true
this.stop()
for (const unwatch of this._watchers) {
unwatch()
}
}
}
export class SmartQuery extends SmartApollo {
type = 'query'
vueApolloSpecialKeys = VUE_APOLLO_QUERY_KEYWORDS
loading = false
constructor (vm, key, options, autostart = true) {
// Simple query
if (!options.query) {
const query = options
options = {
query,
}
}
super(vm, key, options, autostart)
}
stop () {
super.stop()
if (this.observer) {
this.observer.stopPolling()
this.observer = null
}
}
executeApollo (variables) {
if (this.observer) {
// Update variables
// Don't use setVariables directly or it will ignore cache
this.observer.setOptions(this.generateApolloOptions(variables))
} else {
if (this.sub) {
this.sub.unsubscribe()
}
// Create observer
this.observer = this.vm.$apollo.watchQuery(this.generateApolloOptions(variables))
// Create subscription
this.sub = this.observer.subscribe({
next: this.nextResult.bind(this),
error: this.catchError.bind(this),
})
}
this.maySetLoading()
super.executeApollo(variables)
}
maySetLoading (force = false) {
const currentResult = this.observer.currentResult()
if (force || currentResult.loading) {
if (!this.loading) {
this.applyLoadingModifier(1)
}
this.loading = true
}
}
nextResult (result) {
const { data, loading } = result
if (!loading) {
this.loadingDone()
}
const hasResultCallback = typeof this.options.result === 'function'
if (typeof data === 'undefined') {
// No result
} else if (typeof this.options.update === 'function') {
this.vm[this.key] = this.options.update.call(this.vm, data)
} else if (data[this.key] === undefined) {
console.error(`Missing ${this.key} attribute on result`, data)
} else if (!this.options.manual) {
this.vm[this.key] = data[this.key]
} else if (!hasResultCallback) {
console.error(`${this.key} query must have a 'result' hook in manual mode`)
}
if (hasResultCallback) {
this.options.result.call(this.vm, result)
}
}
catchError (error) {
super.catchError(error)
this.loadingDone()
}
get loadingKey () {
return this.options.loadingKey || this.vm.$apollo.loadingKey
}
watchLoading (...args) {
this.options.watchLoading && this.options.watchLoading.call(this.vm, ...args)
this.vm.$apollo.watchLoading && this.vm.$apollo.watchLoading.call(this.vm, ...args)
this.vm.$apollo.provider.watchLoading && this.vm.$apollo.provider.watchLoading.call(this.vm, ...args)
}
applyLoadingModifier (value) {
const loadingKey = this.loadingKey
if (loadingKey && typeof this.vm[loadingKey] === 'number') {
this.vm[loadingKey] += value
}
this.watchLoading(value === 1, value)
}
loadingDone () {
if (this.loading) {
this.applyLoadingModifier(-1)
}
this.loading = false
}
fetchMore (...args) {
if (this.observer) {
this.maySetLoading(true)
return this.observer.fetchMore(...args).then(result => {
if (!result.loading) {
this.loadingDone()
}
return result
})
}
}
subscribeToMore (...args) {
if (this.observer) {
return {
unsubscribe: this.observer.subscribeToMore(...args),
}
}
}
refetch (variables) {
variables && (this.options.variables = variables)
if (this.observer) {
const result = this.observer.refetch(variables).then((result) => {
if (!result.loading) {
this.loadingDone()
}
return result
})
this.maySetLoading()
return result
}
}
setVariables (variables, tryFetch) {
this.options.variables = variables
if (this.observer) {
const result = this.observer.setVariables(variables, tryFetch)
this.maySetLoading()
return result
}
}
setOptions (options) {
Object.assign(this.options, options)
if (this.observer) {
const result = this.observer.setOptions(options)
this.maySetLoading()
return result
}
}
startPolling (...args) {
if (this.observer) {
return this.observer.startPolling(...args)
}
}
stopPolling (...args) {
if (this.observer) {
return this.observer.stopPolling(...args)
}
}
}
export class SmartSubscription extends SmartApollo {
type = 'subscription'
vueApolloSpecialKeys = [
'variables',
'result',
'error',
'throttle',
'debounce',
'linkedQuery',
]
executeApollo (variables) {
const variablesJson = JSON.stringify(variables)
if (this.sub) {
// do nothing if subscription is already running using exactly the same variables
if (variablesJson === this.previousVariablesJson) {
return
}
this.sub.unsubscribe()
}
this.previousVariablesJson = variablesJson
const apolloOptions = this.generateApolloOptions(variables)
if (this.options.linkedQuery) {
this.sub = this.options.linkedQuery.subscribeToMore(apolloOptions)
} else {
// Create observer
this.observer = this.vm.$apollo.subscribe(apolloOptions)
// Create subscription
this.sub = this.observer.subscribe({
next: this.nextResult.bind(this),
error: this.catchError.bind(this),
})
}
super.executeApollo(variables)
}
nextResult (data) {
if (typeof this.options.result === 'function') {
this.options.result.call(this.vm, data)
}
}
}
+215
View File
@@ -0,0 +1,215 @@
import SmartApollo from './smart-apollo'
import { VUE_APOLLO_QUERY_KEYWORDS } from './consts'
export default class SmartQuery extends SmartApollo {
type = 'query'
vueApolloSpecialKeys = VUE_APOLLO_QUERY_KEYWORDS
_loading = false
constructor (vm, key, options, autostart = true) {
// Simple query
if (!options.query) {
const query = options
options = {
query,
}
}
// Add reactive data related to the query
if (vm.$data.$apolloData && !vm.$data.$apolloData.queries[key]) {
vm.$set(vm.$data.$apolloData.queries, key, {
loading: false,
})
}
super(vm, key, options, autostart)
}
get client () {
return this.vm.$apollo.getClient(this.options)
}
get loading () {
return this.vm.$data.$apolloData ? this.vm.$data.$apolloData.queries[this.key].loading : this._loading
}
set loading (value) {
if (this._loading !== value) {
this._loading = value
if (this.vm.$data.$apolloData) {
this.vm.$data.$apolloData.queries[this.key].loading = value
this.vm.$data.$apolloData.loading += value ? 1 : -1
}
}
}
stop () {
super.stop()
if (this.observer) {
this.observer.stopPolling()
this.observer = null
}
}
executeApollo (variables) {
if (this.observer) {
// Update variables
// Don't use setVariables directly or it will ignore cache
this.observer.setOptions(this.generateApolloOptions(variables))
} else {
if (this.sub) {
this.sub.unsubscribe()
}
// Create observer
this.observer = this.vm.$apollo.watchQuery(this.generateApolloOptions(variables))
// Create subscription
this.sub = this.observer.subscribe({
next: this.nextResult.bind(this),
error: this.catchError.bind(this),
})
}
const currentResult = this.maySetLoading()
if (!currentResult.loading) {
this.nextResult(currentResult)
}
super.executeApollo(variables)
}
maySetLoading (force = false) {
const currentResult = this.observer.currentResult()
if (force || currentResult.loading) {
if (!this.loading) {
this.applyLoadingModifier(1)
}
this.loading = true
}
return currentResult
}
nextResult (result) {
const { data, loading } = result
if (!loading) {
this.loadingDone()
}
const hasResultCallback = typeof this.options.result === 'function'
if (typeof data === 'undefined') {
// No result
} else if (typeof this.options.update === 'function') {
this.vm[this.key] = this.options.update.call(this.vm, data)
} else if (data[this.key] === undefined && !this.options.manual) {
console.error(`Missing ${this.key} attribute on result`, data)
} else if (!this.options.manual) {
this.vm[this.key] = data[this.key]
} else if (!hasResultCallback) {
console.error(`${this.key} query must have a 'result' hook in manual mode`)
}
if (hasResultCallback) {
this.options.result.call(this.vm, result)
}
}
catchError (error) {
super.catchError(error)
this.loadingDone()
}
get loadingKey () {
return this.options.loadingKey || this.vm.$apollo.loadingKey
}
watchLoading (...args) {
this.options.watchLoading && this.options.watchLoading.call(this.vm, ...args)
this.vm.$apollo.watchLoading && this.vm.$apollo.watchLoading.call(this.vm, ...args)
this.vm.$apollo.provider.watchLoading && this.vm.$apollo.provider.watchLoading.call(this.vm, ...args)
}
applyLoadingModifier (value) {
const loadingKey = this.loadingKey
if (loadingKey && typeof this.vm[loadingKey] === 'number') {
this.vm[loadingKey] += value
}
this.watchLoading(value === 1, value)
}
loadingDone () {
if (this.loading) {
this.applyLoadingModifier(-1)
}
this.loading = false
}
fetchMore (...args) {
if (this.observer) {
this.maySetLoading(true)
return this.observer.fetchMore(...args).then(result => {
if (!result.loading) {
this.loadingDone()
}
return result
})
}
}
subscribeToMore (...args) {
if (this.observer) {
return {
unsubscribe: this.observer.subscribeToMore(...args),
}
}
}
refetch (variables) {
variables && (this.options.variables = variables)
if (this.observer) {
const result = this.observer.refetch(variables).then((result) => {
if (!result.loading) {
this.loadingDone()
}
return result
})
this.maySetLoading()
return result
}
}
setVariables (variables, tryFetch) {
this.options.variables = variables
if (this.observer) {
const result = this.observer.setVariables(variables, tryFetch)
this.maySetLoading()
return result
}
}
setOptions (options) {
Object.assign(this.options, options)
if (this.observer) {
const result = this.observer.setOptions(options)
this.maySetLoading()
return result
}
}
startPolling (...args) {
if (this.observer) {
return this.observer.startPolling(...args)
}
}
stopPolling (...args) {
if (this.observer) {
return this.observer.stopPolling(...args)
}
}
}
+48
View File
@@ -0,0 +1,48 @@
import SmartApollo from './smart-apollo'
export default class SmartSubscription extends SmartApollo {
type = 'subscription'
vueApolloSpecialKeys = [
'variables',
'result',
'error',
'throttle',
'debounce',
'linkedQuery',
]
executeApollo (variables) {
const variablesJson = JSON.stringify(variables)
if (this.sub) {
// do nothing if subscription is already running using exactly the same variables
if (variablesJson === this.previousVariablesJson) {
return
}
this.sub.unsubscribe()
}
this.previousVariablesJson = variablesJson
const apolloOptions = this.generateApolloOptions(variables)
if (this.options.linkedQuery) {
this.sub = this.options.linkedQuery.subscribeToMore(apolloOptions)
} else {
// Create observer
this.observer = this.vm.$apollo.subscribe(apolloOptions)
// Create subscription
this.sub = this.observer.subscribe({
next: this.nextResult.bind(this),
error: this.catchError.bind(this),
})
}
super.executeApollo(variables)
}
nextResult (data) {
if (typeof this.options.result === 'function') {
this.options.result.call(this.vm, data)
}
}
}
+4
View File
@@ -0,0 +1,4 @@
import './vue'
import { VueApollo } from './vue-apollo';
export default VueApollo;
+194
View File
@@ -0,0 +1,194 @@
// this example src is https://github.com/Akryum/vue-apollo-example
import gql from 'graphql-tag';
import Vue from 'vue';
const pageSize = 10;
const SUB_QUERY = gql`subscription tags($type: String!) {
tagAdded(type: $type) {
id
label
type
}
}`;
export default Vue.extend({
data () {
return {
newTag: null,
updateCount: 0,
type: 'City',
skipQuery: false,
loading: 0,
tagsLoading: 0,
tagsPageLoading: 0,
showTag: 'random',
showMoreEnabled: true,
page: 0,
_type: ''
}
},
apollo: {
$client: 'a',
$loadingKey: 'loading',
tags() {
return {
query: gql`query tagList ($type: String!) {
tags(type: $type) {
id
label
}
}`,
// Reactive variables
variables () {
return {
type: this.type,
};
},
manual: true,
pollInterval: 300,
result (result) {
this.updateCount ++;
},
skip () {
return this.skipQuery
},
fetchPolicy: 'cache-and-network',
subscribeToMore: [{
document: SUB_QUERY,
variables () {
return { type: this.type, }
},
updateQuery: (previousResult, { subscriptionData }) => {
console.log('new tag', subscriptionData.data.tagAdded)
if (previousResult.tags.find((tag: any) => tag.id === subscriptionData.data.tagAdded.id)) {
return previousResult
}
return {
tags: [
...previousResult.tags,
subscriptionData.data.tagAdded,
],
}
},
}],
}
},
randomTag: {
query () {
if (this.showTag === 'random') {
return gql`{
randomTag {
id
label
type
}
}`
} else if (this.showTag === 'last') {
return gql`{
randomTag: lastTag {
id
label
type
}
}`
}
},
},
tagsPage: {
// GraphQL Query
query: gql`query tagsPage ($page: Int!, $pageSize: Int!) {
tagsPage(page: $page, size: $pageSize) {
tags {
id
label
type
}
hasMore
}
}`,
variables: {
page: 0,
pageSize,
},
},
},
methods: {
addTag() {
const newTag = this.newTag;
this.$apollo.mutate({
mutation: gql`mutation ($type: String!, $label: String!) {
addTag(type: $type, label: $label) {
id
label
}
}`,
variables: { type: this.type, label: newTag, },
updateQueries: {
tagList: (previousResult, { mutationResult }) => {
const { data } = mutationResult;
if (!data) { return previousResult }
if (previousResult.tags.find((tag: any) => tag.id === data.addTag.id)) {
return previousResult
}
return { tags: [ ...previousResult.tags, data.addTag ] };
},
},
optimisticResponse: {
__typename: 'Mutation',
addTag: {
__typename: 'Tag',
id: -1,
label: newTag,
type: this.type,
},
},
}).then((data) => {
console.log(data);
}).catch((error) => {
console.error(error);
this.newTag = newTag;
});
},
showMore() {
this.page ++;
this.$apollo.queries.tagsPage.fetchMore({
variables: {
page: this.page,
pageSize,
},
// Mutate the previous result
updateQuery: (previousResult: any, result: { fetchMoreResult: any }) => {
const { fetchMoreResult } = result;
const newTags = fetchMoreResult.tagsPage.tags;
const hasMore = fetchMoreResult.tagsPage.hasMore;
this.showMoreEnabled = hasMore;
return {
tagsPage: {
__typename: previousResult.tagsPage.__typename,
tags: [
...previousResult.tagsPage.tags,
// Add the new tags
...newTags,
],
hasMore,
},
};
},
});
},
refetchTags () {
this.$apollo.queries.tags.refetch()
},
},
mounted() {
const observer = this.$apollo.subscribe({
query: SUB_QUERY,
variables: {
type: 'Companies',
},
});
observer.subscribe({
next(data) {
console.log('this.$apollo.subscribe', data);
},
});
},
});
+19
View File
@@ -0,0 +1,19 @@
import Vue from 'vue'
import 'isomorphic-fetch'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { ApolloLink, split } from 'apollo-link'
import { getMainDefinition } from 'apollo-utilities'
import VueApollo from '../index'
import App from './App'
const httpLink = new HttpLink({ uri: 'https://dummy.test.com' })
const cache: any = 'dummy cache';
const apolloClient = new ApolloClient({ link: httpLink, cache, connectToDevTools: true })
const apolloProvider = new VueApollo({ defaultClient: apolloClient })
Vue.use(VueApollo)
new Vue({ el: '#app', apolloProvider, render: h => h(App), })
+28
View File
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"es5",
"es6",
"dom",
"es2015.core",
"es2015.collection",
"es2015.generator",
"es2015.iterable",
"es2015.promise",
"es2015.proxy",
"es2015.reflect",
"es2015.symbol",
"es2015.symbol.wellknown",
"esnext.asynciterable"
],
"module": "es2015",
"moduleResolution": "node",
"experimentalDecorators": true,
"strict": true
},
"include": [
"*.ts",
"../*.d.ts"
]
}
+84
View File
@@ -0,0 +1,84 @@
import Vue, { PluginObject, PluginFunction } from 'vue';
import { DocumentNode } from 'graphql';
import { ApolloClient } from 'apollo-client';
import { WatchQueryOptions, MutationOptions, SubscriptionOptions, SubscribeToMoreOptions, ObservableQuery, NetworkStatus } from 'apollo-client'
import { DataProxy } from 'apollo-cache';
import { subscribe } from 'graphql/subscription/subscribe';
// include Omit type from https://github.com/Microsoft/TypeScript/issues/12215
type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = { [P in Diff<keyof T, K>]?: T[P] };
type VueApolloOptions = {
$skip?: boolean,
$skipAllQueries?: boolean,
$skipAllSubscriptions?: boolean,
$client?: string,
$loadingKey?: string,
$error?: Function
}
export class VueApollo implements PluginObject<{}> {
[key: string]: any;
install: PluginFunction<{}>;
constructor (options: { defaultClient: ApolloClient<{}>, defaultOptions?: VueApolloOptions, clients?: { [key: string]: ApolloClient<{}> } });
static install(pVue: typeof Vue, options?:{} | undefined): void;
}
type ApolloVueThisType<V> = V & { [key: string]: any };
type VariableFn<V> = ((this: ApolloVueThisType<V>) => Object) | Object;
type ApolloVueUpdateQueryFn<V> = (this: ApolloVueThisType<V>, previousQueryResult: { [key: string]: any }, options: {
error: any,
subscriptionData: { data: any; };
variables?: { [key: string]: any; };
}) => Object;
interface ApolloVueSubscribeToMoreOptions<V> {
document: DocumentNode;
variables?: VariableFn<V>;
updateQuery?: ApolloVueUpdateQueryFn<V>;
onError?: (error: Error) => void;
}
type _WatchQueryOptions = Omit<WatchQueryOptions, 'query'>; // exclude query prop because it causes type incorrectly error
export interface VueApolloQueryOptions<V, R> extends _WatchQueryOptions {
query: ((this: ApolloVueThisType<V>) => DocumentNode) | DocumentNode;
variables?: VariableFn<V>;
update?: (this: ApolloVueThisType<V>, data: R) => any;
result?: (this: ApolloVueThisType<V>, data: R, loader: any, netWorkStatus: NetworkStatus) => void;
error?: (this: ApolloVueThisType<V>, error: any) => void;
loadingKey?: string;
watchLoading?: (isLoading: boolean, countModifier: number) => void;
skip?: (this: ApolloVueThisType<V>) => boolean | boolean;
manual?: boolean;
subscribeToMore?: ApolloVueSubscribeToMoreOptions<V> | ApolloVueSubscribeToMoreOptions<V>[];
}
export interface VueApolloMutationOptions<V, R> extends MutationOptions<R> {
mutation: DocumentNode;
variables?: VariableFn<V>;
optimisticResponse?: ((this: ApolloVueThisType<V>) => any) | Object;
}
export interface VueApolloSubscriptionOptions<V, R> extends SubscriptionOptions {
query: DocumentNode;
variables?: VariableFn<V>;
result?: (this: V, data: R) => void;
}
type Query<V> = (key: string, options: VueApolloQueryOptions<V, any>) => void;
type Mutate<V, R=any> = <R=any>(params: VueApolloMutationOptions<V, R>) => Promise<R>;
type Subscribe<R=any> = <R=any>(params: SubscriptionOptions) => ObservableQuery<R>;
export interface ApolloProperty<V> {
[key: string]: Query<V> | Mutate<V> | Subscribe; // smart query
queries: any;
mutate: Mutate<V>;
subscribe: Subscribe;
}
type QueryComponentProperty<V> = ((this: ApolloVueThisType<V>) => VueApolloQueryOptions<V, any>) | VueApolloQueryOptions<V, any>
type SubscribeComponentProperty<V> = VueApolloSubscriptionOptions<V, any> | { [key: string]: VueApolloSubscriptionOptions<V, any> }
export interface VueApolloComponentOption<V> extends VueApolloOptions {
[key: string]: QueryComponentProperty<V> | SubscribeComponentProperty<V> | string | boolean | Function | undefined;
$subscribe?: SubscribeComponentProperty<V>;
}
+15
View File
@@ -0,0 +1,15 @@
import Vue from "vue";
import { VueApollo, VueApolloComponentOption, ApolloProperty } from './vue-apollo';
declare module "vue/types/options" {
interface ComponentOptions<V extends Vue> {
apolloProvider?: VueApollo;
apollo?: VueApolloComponentOption<V>;
}
}
declare module "vue/types/vue" {
interface Vue {
$apollo: ApolloProperty<any>;
}
}
+1612 -797
View File
File diff suppressed because it is too large Load Diff