Skip to content

Commit 86aec87

Browse files
committed
Docs
1 parent 8a3d152 commit 86aec87

File tree

2 files changed

+78
-47
lines changed

2 files changed

+78
-47
lines changed

src/queryBuilder.ts

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,21 @@ import gql from 'graphql-tag';
88

99
const inflection = require('inflection');
1010

11+
/**
12+
* Contains all logic to build GraphQL queries and transform variables between the format Vuex-ORM requires and the
13+
* format of the GraphQL API.
14+
*/
1115
export default class QueryBuilder {
16+
/**
17+
* Logger, is injected into the constructor.
18+
*/
1219
private readonly logger: Logger;
20+
21+
/**
22+
* Helper method to get the model by name
23+
* @param {Model|string} name
24+
* @returns {Model}
25+
*/
1326
private readonly getModel: (name: Model | string) => Model;
1427

1528
/**
@@ -23,7 +36,7 @@ export default class QueryBuilder {
2336
}
2437

2538
/**
26-
* Takes a string with a graphql query and formats it
39+
* Takes a string with a graphql query and formats it. Useful for debug output and the tests.
2740
* @param {string} query
2841
* @returns {string}
2942
*/
@@ -34,13 +47,17 @@ export default class QueryBuilder {
3447
/**
3548
* Builds a field for the GraphQL query and a specific model
3649
*
37-
* @param {Model|string} model
38-
* @param {boolean} multiple
39-
* @param {Arguments} args
40-
* @param {Model} rootModel
41-
* @param {string} name
42-
* @param allowIdFields
50+
* @param {Model|string} model The model to use
51+
* @param {boolean} multiple Determines whether plural/nodes syntax or singular syntax is used.
52+
* @param {Arguments} args The args that will be passed to the query field ( user(role: $role) )
53+
* @param {Model} rootModel The model of the root query field. Used to avoid endless recursion
54+
* @param {string} name Optional name of the field. If not provided, this will be the model name
55+
* @param {boolean} allowIdFields Optional. Determines if id fields will be ignored for the argument generation.
56+
* See buildArguments
4357
* @returns {string}
58+
*
59+
* @todo Do we need the allowIdFields param?
60+
* @todo There could be a endless recursion even with rootModel correctly set. We should track an array of models here probably?
4461
*/
4562
public buildField (model: Model | string,
4663
multiple: boolean = true,
@@ -74,17 +91,30 @@ export default class QueryBuilder {
7491
}
7592
}
7693

94+
/**
95+
* Generates a query.
96+
* Currently only one root field for the query is possible.
97+
* @param {string} type 'mutation' or 'query'
98+
* @param {Model | string} model The model this query or mutation affects. This mainly determines the query fields.
99+
* @param {string} name Optional name of the query/mutation. Will overwrite the name from the model.
100+
* @param {Arguments} args Arguments for the query
101+
* @param {boolean} multiple Determines if the root query field is a connection or not (will be passed to buildField)
102+
* @returns {any}
103+
*/
77104
public buildQuery (type: string, model: Model | string, name?: string, args?: Arguments, multiple?: boolean) {
105+
// model
78106
model = this.getModel(model);
79-
if (!model) throw new Error("No model provided to build the query!");
107+
if (!model) throw new Error('No model provided to build the query!');
80108

109+
// args
81110
args = args ? JSON.parse(JSON.stringify(args)) : {};
82111
if (!args) throw new Error('args is undefined');
83112

84113
if (args[model.singularName] && typeof args[model.singularName] === 'object') {
85114
args[model.singularName] = { __type: upcaseFirstLetter(model.singularName) };
86115
}
87116

117+
// multiple
88118
multiple = multiple === undefined ? !args['id'] : multiple;
89119

90120
// name
@@ -185,7 +215,7 @@ export default class QueryBuilder {
185215
* 2) Signatures with object types (signature = true, args = { user: { __type: 'User' }})
186216
* mutation createUser($user: UserInput!)
187217
*
188-
* 3) Fields with variables (signature = false, valuesAsVariables = true)
218+
* 3) Fields with variables (signature = false)
189219
* query user(id: $id)
190220
*
191221
* @param {Arguments | undefined} args

src/vuex-orm-apollo.ts

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export default class VuexORMApollo {
8383
}
8484

8585
/**
86-
* This method will setup following Vuex action: fetch, persist, push, destroy
86+
* This method will setup following Vuex action: fetch, persist, push, destroy, mutate
8787
*/
8888
private setupMethods () {
8989
this.components.subActions.fetch = this.fetch.bind(this);
@@ -98,12 +98,12 @@ export default class VuexORMApollo {
9898
/**
9999
* Will be called, when dispatch('entities/something/fetch') is called.
100100
*
101-
* @param {Arguments} args
102-
* @param {any} state
103-
* @param {any} dispatch
101+
* @param {any} state The Vuex State from Vuex-ORM
102+
* @param {DispatchFunction} dispatch Vuex Dispatch method for the model
103+
* @param {ActionParams} filter Filter params for the query
104104
* @returns {Promise<void>}
105105
*/
106-
private async fetch ({ state, dispatch }: ActionParams, filter: ActionParams) {
106+
private async fetch ({ state, dispatch }: ActionParams, filter: ActionParams): Promise<void> {
107107
// When the filter contains an id, we query in singular mode
108108
const multiple: boolean = !(filter && filter['id']);
109109
const model: Model = this.getModel(state.$name);
@@ -120,12 +120,12 @@ export default class VuexORMApollo {
120120
/**
121121
* Will be called, when dispatch('entities/something/persist') is called.
122122
*
123-
* @param {any} state
124-
* @param {any} dispatch
125-
* @param {any} id
123+
* @param {any} state The Vuex State from Vuex-ORM
124+
* @param {DispatchFunction} dispatch Vuex Dispatch method for the model
125+
* @param {string} id ID of the record to persist
126126
* @returns {Promise<void>}
127127
*/
128-
private async persist ({ state, dispatch }: ActionParams, { id }: ActionParams) {
128+
private async persist ({ state, dispatch }: ActionParams, { id }: ActionParams): Promise<any> {
129129
if (id) {
130130
const model = this.getModel(state.$name);
131131
const data = model.baseModel.getters('find')(id);
@@ -145,26 +145,25 @@ export default class VuexORMApollo {
145145
/**
146146
* Will be called, when dispatch('entities/something/mutate') is called.
147147
* For custom mutations.
148-
*
149-
* @param {any} state
150-
* @param {any} dispatch
151-
* @param {Data} data
152-
* @returns {Promise<Data | {}>}
148+
* @param {any} state The Vuex State from Vuex-ORM
149+
* @param {DispatchFunction} dispatch Vuex Dispatch method for the model
150+
* @param {Arguments} args Arguments for the mutation. Must contain a 'mutation' field.
151+
* @returns {Promise<any>}
153152
*/
154-
private async customMutation ({ state, dispatch }: ActionParams, args: Arguments) {
153+
private async customMutation ({ state, dispatch }: ActionParams, args: Arguments): Promise<any> {
155154
const name: string = args['mutation'];
156155
delete args['mutation'];
157156

158157
const model = this.getModel(state.$name);
159158

160-
return await this.mutate(name, args, dispatch, model);
159+
return this.mutate(name, args, dispatch, model);
161160
}
162161

163162
/**
164163
* Will be called, when dispatch('entities/something/push') is called.
165-
* @param {any} state
166-
* @param {any} dispatch
167-
* @param {Data} data
164+
* @param {any} state The Vuex State from Vuex-ORM
165+
* @param {DispatchFunction} dispatch Vuex Dispatch method for the model
166+
* @param {Arguments} data New data to save
168167
* @returns {Promise<Data | {}>}
169168
*/
170169
private async push ({ state, dispatch }: ActionParams, { data }: ActionParams) {
@@ -187,32 +186,33 @@ export default class VuexORMApollo {
187186
/**
188187
* Will be called, when dispatch('entities/something/destroy') is called.
189188
*
190-
* @param {any} state
191-
* @param {any} dispatch
192-
* @param {Data} id
189+
* @param {any} state The Vuex State from Vuex-ORM
190+
* @param {DispatchFunction} dispatch Vuex Dispatch method for the model
191+
* @param {string} id ID of the record to delete
193192
* @returns {Promise<void>}
194193
*/
195194
private async destroy ({ state, dispatch }: ActionParams, { id }: ActionParams): Promise<any> {
196195
if (id) {
197196
const model = this.getModel(state.$name);
198197
const mutationName = `delete${upcaseFirstLetter(model.singularName)}`;
199-
return await this.mutate(mutationName, { id }, dispatch, model, false);
198+
return this.mutate(mutationName, { id }, dispatch, model, false);
200199
}
201200
}
202201

203202
/**
204-
* Contains the logic to save (persist or push) data.
203+
* Sends a mutation.
205204
*
206-
* @param {string} action
207-
* @param {Data | undefined} data
208-
* @param {Function} dispatch
209-
* @param {Model} model
205+
* @param {string} name Name of the mutation like 'createUser'
206+
* @param {Data | undefined} variables Variables to send with the mutation
207+
* @param {Function} dispatch Vuex Dispatch method for the model
208+
* @param {Model} model The model this mutation affects.
209+
* @param {boolean} multiple See QueryBuilder.buildQuery()
210210
* @returns {Promise<any>}
211211
*/
212-
private async mutate (action: string, variables: Data | undefined, dispatch: DispatchFunction, model: Model, multiple?: boolean): Promise<any> {
212+
private async mutate (name: string, variables: Data | undefined, dispatch: DispatchFunction, model: Model, multiple?: boolean): Promise<any> {
213213
if (variables) {
214214
const id = variables.id ? variables.id : undefined;
215-
const query = this.queryBuilder.buildQuery('mutation', model, action, variables, multiple);
215+
const query = this.queryBuilder.buildQuery('mutation', model, name, variables, multiple);
216216

217217
// Send GraphQL Mutation
218218
const newData = await this.apolloRequest(query, variables, true);
@@ -224,16 +224,18 @@ export default class VuexORMApollo {
224224

225225
/**
226226
* Sends a request to the GraphQL API via apollo
227-
* @param query
227+
* @param {any} query The query to send (result from gql())
228+
* @param {Arguments} variables Optional. The variables to send with the query
229+
* @param {boolean} mutation Optional. If this is a mutation (true) or a query (false, default)
228230
* @returns {Promise<Data>}
229231
*/
230232
private async apolloRequest (query: any, variables?: Arguments, mutation: boolean = false): Promise<Data> {
231233
let response;
232234

233235
if (mutation) {
234-
response = await (this.apolloClient).mutate({ mutation: query, variables });
236+
response = await this.apolloClient.mutate({ mutation: query, variables });
235237
} else {
236-
response = await (this.apolloClient).query({ query, variables });
238+
response = await this.apolloClient.query({ query, variables });
237239
}
238240

239241
// Transform incoming data into something useful
@@ -243,9 +245,8 @@ export default class VuexORMApollo {
243245
/**
244246
* Inserts incoming data into the store.
245247
*
246-
* @param {Data} data
247-
* @param {Function} dispatch
248-
* @param {boolean} update
248+
* @param {Data} data New data to insert/update
249+
* @param {Function} dispatch Vuex Dispatch method for the model
249250
*/
250251
private async insertData (data: Data, dispatch: DispatchFunction) {
251252
Object.keys(data).forEach(async (key) => {
@@ -257,8 +258,8 @@ export default class VuexORMApollo {
257258
* Updates an existing record in the store with new data. This method can only update one single record, so
258259
* it takes the first record of the first field from the data object!
259260
* @param {Data} data
260-
* @param {Function} dispatch
261-
* @param id
261+
* @param {Function} dispatch Vuex Dispatch method for the model
262+
* @param {string|number} id ID of the record to update
262263
*/
263264
private async updateData (data: Data, dispatch: DispatchFunction, id: number | string) {
264265
// We only take the first field!

0 commit comments

Comments
 (0)