TypeScript support (#160)
* TypeScript support * set defaultOptions key to VueApollo constructor
This commit is contained in:
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import './vue'
|
||||
import { VueApollo } from './vue-apollo';
|
||||
|
||||
export default VueApollo;
|
||||
@@ -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);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -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), })
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
Vendored
+84
@@ -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>;
|
||||
}
|
||||
Vendored
+15
@@ -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>;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user