Skip to content

Commit 9f0107e

Browse files
author
Kamil Kisiela
committed
feat(Apollo): reactive mutations
1 parent 2ce38e8 commit 9f0107e

File tree

1 file changed

+41
-32
lines changed

1 file changed

+41
-32
lines changed

src/apolloDecorator.ts

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
import ApolloClient from 'apollo-client';
44

5+
import {
6+
GraphQLResult,
7+
} from 'graphql';
8+
59
import {
610
isEqual,
711
noop,
@@ -27,11 +31,7 @@ export function Apollo({
2731
queries,
2832
mutations,
2933
}: ApolloOptions) {
30-
if (!(client instanceof ApolloClient)) {
31-
throw new Error('Client must be a ApolloClient instance');
32-
}
33-
34-
const { watchQuery } = client;
34+
const { watchQuery, mutate } = client;
3535

3636
// noop by default
3737
queries = queries || noop;
@@ -51,24 +51,17 @@ export function Apollo({
5151
*/
5252
ngOnInit() {
5353
// use component's context
54-
const component = this;
55-
handleQueries(component, (key, { query, variables }) => {
56-
assign(component, key, { query, variables });
57-
});
54+
handleQueries(this);
55+
handleMutations(this);
5856
},
5957
/**
6058
* Detect and act upon changes that Angular can or won't detect on its own.
6159
* Called every change detection run.
6260
*/
6361
ngDoCheck() {
6462
// use component's context
65-
const component = this;
66-
handleQueries(component, (queryName, { query, variables }) => {
67-
// check if query needs to be rerun
68-
if (!equalVariablesOf(queryName, variables)) {
69-
assign(component, queryName, { query, variables });
70-
}
71-
});
63+
handleQueries(this);
64+
handleMutations(this);
7265
},
7366
};
7467

@@ -77,35 +70,51 @@ export function Apollo({
7770
wrapPrototype(name, hook);
7871
});
7972

80-
/**
81-
* Gets the result of the `queries` method
82-
* from decorator's options with component's context to compile variables.
83-
*
84-
* Then goes through all defined queries and calls a `touch` function.
85-
*
86-
* @param {any} component Component's context
87-
* @param {Function} touch Receives name and options
88-
*/
89-
function handleQueries(component: any, touch: Function) {
90-
forIn(queries(component), (opts: any, queryName: string) => {
91-
touch(queryName, opts);
73+
function handleQueries(component: any) {
74+
forIn(queries(component), ({ query, variables }, queryName: string) => {
75+
if (!equalVariablesOf(queryName, variables)) {
76+
createQuery(component, queryName, { query, variables });
77+
}
78+
});
79+
}
80+
81+
function handleMutations(component: any) {
82+
forIn(mutations(component), (method: Function, mutationName: string) => {
83+
createMutation(component, mutationName, method);
9284
});
9385
}
9486

9587
/**
96-
* Assings WatchQueryHandle to component
88+
* Assings WatchQueryHandle to the component
9789
*
9890
* @param {any} component Component's context
9991
* @param {string} queryName Query's name
10092
* @param {Object} options Query's options
10193
*/
102-
function assign(component: any, queryName: string, { query, variables }) {
94+
function createQuery(component: any, queryName: string, { query, variables }) {
10395
// save variables so they can be used in futher comparasion
10496
lastQueryVariables[queryName] = variables;
10597
// assign to component's context
10698
component[queryName] = watchQuery({ query, variables });
10799
}
108100

101+
/**
102+
* Assings wrapper of mutation to the component
103+
*
104+
* @param {any} component Component's context
105+
* @param {string} mutationName Mutation's name
106+
* @param {Function} method Method returning mutation options
107+
* @return {Promise} Mutation result
108+
*/
109+
function createMutation(component: any, mutationName: string, method: Function) {
110+
// assign to component's context
111+
component[mutationName] = (...args): Promise<GraphQLResult> => {
112+
const { mutation, variables } = method.apply(client, args);
113+
114+
return mutate({ mutation, variables });
115+
};
116+
}
117+
109118
/**
110119
* Compares current variables with previous ones.
111120
*
@@ -121,8 +130,8 @@ export function Apollo({
121130
* Creates a new prototype method which is a wrapper function
122131
* that calls new function before old one.
123132
*
124-
* @param {string} name [description]
125-
* @param {Function} func [description]
133+
* @param {string} name
134+
* @param {Function} func
126135
*/
127136
function wrapPrototype(name: string, func: Function) {
128137
oldHooks[name] = sourceTarget.prototype[name];

0 commit comments

Comments
 (0)