Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/
types/test/*.js
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
src/
types/test/
15 changes: 13 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
"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 build/rollup.config.browser.js",
"build:es": "rollup --config build/rollup.config.es.js",
"build:umd": "rollup --config build/rollup.config.umd.js",
"prepublish": "npm run build",
"dev": "npm-watch"
"dev": "npm-watch",
"test:types": "tsc -p types/test"
},
"watch": {
"build": "src/*.js"
Expand Down Expand Up @@ -40,6 +42,11 @@
"lodash.throttle": "^4.1.1"
},
"devDependencies": {
"@types/graphql": "^0.11.7",
"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": "^7.1.1",
"babel-plugin-external-helpers": "^6.22.0",
Expand All @@ -51,6 +58,8 @@
"eslint-plugin-node": "^5.2.1",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"graphql": "^0.11.7",
"graphql-tag": "^2.5.0",
"npm-watch": "^0.3.0",
"rimraf": "^2.6.1",
"rollup": "^0.50.0",
Expand All @@ -59,6 +68,8 @@
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-uglify": "^2.0.1",
"uglify-es": "^3.1.6"
"typescript": "^2.6.2",
"uglify-es": "^3.1.6",
"vue": "^2.5.9"
}
}
4 changes: 4 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import './vue'
import { VueApollo } from './vue-apollo';

export default VueApollo;
194 changes: 194 additions & 0 deletions types/test/App.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 19 additions & 0 deletions types/test/index.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 28 additions & 0 deletions types/test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -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 changes: 84 additions & 0 deletions types/vue-apollo.d.ts
Original file line number Diff line number Diff line change
@@ -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 });
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>;
}
Loading