TypeScript support (#160)

* TypeScript support

* set defaultOptions key to VueApollo constructor
This commit is contained in:
joe-re
2017-12-22 22:38:05 +09:00
committed by Guillaume Chau
parent c9c3ce4224
commit 8dcdb9299f
10 changed files with 455 additions and 2 deletions
+1
View File
@@ -1 +1,2 @@
node_modules/
types/test/*.js
+1
View File
@@ -1 +1,2 @@
src/
types/test/
+13 -2
View File
@@ -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"
@@ -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",
@@ -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",
@@ -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
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 });
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>;
}
}
+96
View File
@@ -2,6 +2,18 @@
# yarn lockfile v1
"@types/async@2.0.45":
version "2.0.45"
resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.45.tgz#0cfe971d7ed5542695740338e0455c91078a0e83"
"@types/graphql@^0.11.7":
version "0.11.7"
resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.11.7.tgz#da39a2f7c74e793e32e2bb7b3b68da1691532dd5"
"@types/zen-observable@0.5.3", "@types/zen-observable@^0.5.3":
version "0.5.3"
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.5.3.tgz#91b728599544efbb7386d8b6633693a3c2e7ade5"
abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
@@ -75,6 +87,54 @@ anymatch@^1.3.0:
micromatch "^2.1.5"
normalize-path "^2.0.0"
apollo-cache-inmemory@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.1.1.tgz#1511f00eb845da88504abf867f408c3026a909ba"
dependencies:
apollo-cache "^1.0.1"
apollo-utilities "^1.0.2"
graphql-anywhere "^4.0.1"
apollo-cache@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.0.1.tgz#66c16141173bc752d3ad3dce990310c10dfc4076"
dependencies:
apollo-utilities "^1.0.2"
apollo-client@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.0.3.tgz#f99f32e2c851bbd52da1e1b113ce8f6a0cf94945"
dependencies:
"@types/zen-observable" "^0.5.3"
apollo-cache "^1.0.1"
apollo-link "^1.0.0"
apollo-link-dedup "^1.0.0"
apollo-utilities "^1.0.2"
symbol-observable "^1.0.2"
zen-observable "^0.6.0"
optionalDependencies:
"@types/async" "2.0.45"
apollo-link-dedup@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.2.tgz#bab659dde41f8dd627839142d4dad90e55251110"
apollo-link-http@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.2.0.tgz#48464c2ebfa6474f7a89908696827d66b2deb5cc"
apollo-link@^1.0.0, apollo-link@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.0.3.tgz#759c36abeeb99e227eca45f919ee07fb8fee911e"
dependencies:
"@types/zen-observable" "0.5.3"
apollo-utilities "^1.0.0"
zen-observable "^0.6.0"
apollo-utilities@^1.0.0, apollo-utilities@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.2.tgz#bcf348a7e613e82e2624ddb5be2b9f6bf1259c6d"
aproba@^1.0.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -1530,6 +1590,22 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
graphql-anywhere@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.0.1.tgz#eb53ed5c56ef42e21d34dc22951e3da38f88a342"
dependencies:
apollo-utilities "^1.0.2"
graphql-tag@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.5.0.tgz#b43bfd8b5babcd2c205ad680c03e98b238934e0f"
graphql@^0.11.7:
version "0.11.7"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.7.tgz#e5abaa9cb7b7cccb84e9f0836bf4370d268750c6"
dependencies:
iterall "1.1.3"
har-schema@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
@@ -1812,6 +1888,10 @@ isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
iterall@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.3.tgz#1cbbff96204056dde6656e2ed2e2226d0e6d72c9"
js-tokens@^3.0.0, js-tokens@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
@@ -2819,6 +2899,10 @@ supports-color@^4.0.0:
dependencies:
has-flag "^2.0.0"
symbol-observable@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.1.0.tgz#5c68fd8d54115d9dfb72a84720549222e8db9b32"
table@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36"
@@ -2926,6 +3010,10 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4"
uglify-es@^3.1.6:
version "3.1.6"
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.6.tgz#b0f818c055a7e9538abc2286e70c743f2938311f"
@@ -3005,6 +3093,10 @@ vlq@^0.2.1:
version "0.2.3"
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
vue@^2.5.9:
version "2.5.9"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.9.tgz#b2380cd040915dca69881dafd121d760952e65f7"
which@^1.2.9:
version "1.3.0"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
@@ -3056,3 +3148,7 @@ xtend@~4.0.1:
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
zen-observable@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.6.0.tgz#8a6157ed15348d185d948cfc4a59d90a2c0f70ee"