Skip to content

Commit e110818

Browse files
committed
feat: update to more fit the format of a guide
Signed-off-by: Brent Hoover <[email protected]>
1 parent 9f7600b commit e110818

File tree

1 file changed

+52
-48
lines changed

1 file changed

+52
-48
lines changed

guides/create-graphql-query.md

+52-48
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
## At a glance
22

3-
In this guide, we’ll guide you through the steps you need to create a successful query in GraphQL
3+
You're working on a new implementation for Leader of the Pack, an outdoor equipment retailer. Let's say that you don't ship Kayaks to every location because of the logistical challenges of shipping something that large. So you need to add
4+
a query that will show you if a particular product can be shipped to a particular zip code. Once you have that data in the system you need to have a way to make it available to the client. This is usually done by creating a GraphQL query. In this guide, we’ll walk you through the steps you need to create a query in GraphQL and have it recognized by the system.
45

5-
## Identify which plugin owns the query
6+
## What you need
67

7-
The complete Reaction Commerce GraphQL API is created by stitching together domain-specific APIs from all of the API plugins. So when adding a new query, the first step is to decide which plugin should own it. This is usually obvious, but not always. You should think about whether any other plugins or services will need to call your query. If the query is fundamental to the system, then it may need to go in the "core" plugin, if no better alternative exists.
8+
You should already have an understanding of what fields/data you wish to share with the client and what GraphQL type each field is. Consult the [GraphQL Reference](https://graphql.org/learn/schema/) for more info on GraphQL types.
89

9-
## Understand the difference between a plugin query function and a GraphQL query resolver
10+
## Identify which plugin owns the query
1011

11-
See [Resolver mutations and queries vs. plugin mutations and queries in the GraphQL concepts docs](../docs/graphql-concepts.md)
12+
The complete Open Commerce GraphQL API is created by stitching together domain-specific APIs from all the API plugins. So when adding a new query, the first step is to decide which plugin should own it. This is usually obvious, but not always. You should think about whether any other plugins or services will need to call your query.
13+
Typically, if you are adding data your new query will exist in your custom plugin.
1214

1315
## Name the query
1416

@@ -23,53 +25,53 @@ When choosing a name for the query, there are a few rules to follow:
2325
- If it doesn't already exist, create `schema.graphql` in `schemas` in the plugin.
2426
- Import the GraphQL file into `index.js` and default export it in an array:
2527

26-
```js
27-
import importAsString from "@reactioncommerce/api-utils/importAsString.js";
28+
```js
29+
import importAsString from "@reactioncommerce/api-utils/importAsString.js";
2830

29-
const schema = importAsString("./schema.graphql");
31+
const schema = importAsString("./schema.graphql");
3032

31-
export default [schema];
32-
```
33+
export default [schema];
34+
```
3335

34-
> NOTE: For large plugins, you can split to multiple `.graphql` files and export a multi-item array.
36+
> NOTE: For large plugins, you can split to multiple `.graphql` files and export a multi-item array.
3537
3638
- In the `.graphql` file, add your query within `extend type Query { }`. Add an `extend type Query` section near the top if the file doesn't have it yet.
3739
- If your query returns multiple documents, it should return a Relay-compatible Connection and accept standard connection arguments. This is true of any `fields` on any types you create as well.
3840

3941
Example: `groups(after: ConnectionCursor, before: ConnectionCursor, first: ConnectionLimitInt, last: ConnectionLimitInt, sortOrder: SortOrder = asc, sortBy: GroupSortByField = createdAt): GroupConnection`
4042

41-
- Document your query, the new types, and all fields in those types using string literals. See [Documenting a GraphQL Schema](../guides/developers-guide/core/developing-graphql.md#documenting-a-graphql-schema).
43+
- Document your query, the new types, and all fields in those types using string literals. <!-- TODO: See [Documenting a GraphQL Schema](../guides/developers-guide/core/developing-graphql.md#documenting-a-graphql-schema) -->.
4244
- If not already done, register your schemas in the plugin's `index.js` file:
4345

44-
```js
45-
import schemas from "./schemas";
46+
```js
47+
import schemas from "./schemas";
4648

47-
export default async function register(app) {
48-
await app.registerPlugin({
49-
graphQL: {
50-
schemas
51-
},
52-
// other props
53-
});
54-
}
55-
```
49+
export default async function register(app) {
50+
await app.registerPlugin({
51+
graphQL: {
52+
schemas
53+
},
54+
// other props
55+
});
56+
}
57+
```
5658

5759
## Create the plugin query file
5860

5961
- If it doesn't already exist, create `queries` folder in the plugin, and add an `index.js` file there.
60-
- In `queries`, create a file for the query, e.g. `widgets.js` for the `widgets` query. The file should look something like this:
62+
- In `queries`, create a file for the query, e.g. `isAvailableToShip.js` for the `isAvailableToShip` query. The file should look something like this:
6163

6264
```js
6365
import Logger from "@reactioncommerce/logger";
6466

6567
/**
66-
* @method widgets
68+
* @method isAvailableToShip
6769
* @summary TODO
6870
* @param {Object} context - an object containing the per-request state
6971
* @return {Promise<Object>} TODO
7072
*/
71-
export default async function widgets(context) {
72-
Logger.info("widgets query is not yet implemented");
73+
export default async function isAvailableToShip(context) {
74+
Logger.info("isAvailableToShip query is not yet implemented");
7375
return null;
7476
}
7577
```
@@ -79,10 +81,10 @@ export default async function widgets(context) {
7981
In `queries/index.js` in the plugin, import your query and add it to the default export object. Example:
8082

8183
```js
82-
import widgets from "./widgets"
84+
import isAvailableToShip from "./isAvailableToShip.js"
8385

8486
export default {
85-
widgets
87+
isAvailableToShip
8688
};
8789
```
8890

@@ -99,20 +101,20 @@ export default async function register(app) {
99101
}
100102
```
101103

102-
Your plugin query function is now available in the GraphQL context as `context.queries.widgets`.
104+
Your plugin query function is now available in the GraphQL context as `context.queries.isAvailableToShip`.
103105

104106
> NOTE: The queries objects from all plugins are merged, so be sure that another plugin does not have a query with the same name. The last one registered with that name will win, and plugins are generally registered in alphabetical order by plugin name. Tip: You can use this to your advantage if you want to override the query function of a core plugin without modifying core code.
105107
106108
## Add a test file for your query
107109

108-
If your query is in a file named `widgets.js`, your Jest tests should be in a file named `widgets.test.js` in the same folder. Initially you can copy and paste the following test:
110+
If your query is in a file named `isAvailableToShip.js`, your Jest tests should be in a file named `isAvailableToShip.test.js` in the same folder. Initially you can copy and paste the following test:
109111

110112
```js
111113
import mockContext from "/imports/test-utils/helpers/mockContext";
112-
import widgets from "./widgets";
114+
import isAvailableToShip from "./isAvailableToShip.js";
113115

114116
test("expect to return a Promise that resolves to null", async () => {
115-
const result = await widgets(mockContext);
117+
const result = await isAvailableToShip(mockContext);
116118
expect(result).toEqual(null);
117119
});
118120
```
@@ -121,24 +123,26 @@ This of course should be updated with tests that are appropriate for whatever yo
121123

122124
## Create the GraphQL query resolver file
123125

126+
> Note: All of these elements are required for your query to work and if missing often will not throw an error. If your query is not showing or not returning any data up you probably need to recheck that all of these pieces are here and have the correct name and format.
127+
124128
- If it doesn't already exist, create `resolvers` folder in the plugin, and add an `index.js` file there.
125129
- If it doesn't already exist, create `resolvers/Query` folder in the plugin, and add an `index.js` file there. "Query" must be capitalized.
126-
- In `resolvers/Query`, create a file for the query resolver, e.g. `widgets.js` for the `widgets` query. The file should look something like this initially:
130+
- In `resolvers/Query`, create a file for the query resolver, e.g. `isAvailableToShip.js` for the `isAvailableToShip` query. The file should look something like this initially:
127131

128132
```js
129133
/**
130-
* @name "Query.widgets"
134+
* @name "Query.isAvailableToShip"
131135
* @method
132136
* @memberof MyPlugin/GraphQL
133-
* @summary resolver for the widgets GraphQL query
137+
* @summary resolver for the isAvailableToShip GraphQL query
134138
* @param {Object} parentResult - unused
135139
* @param {Object} args - an object of all arguments that were sent by the client
136140
* @param {Object} context - an object containing the per-request state
137141
* @return {Promise<Object>} TODO
138142
*/
139-
export default async function widgets(parentResult, args, context) {
143+
export default async function isAvailableToShip(parentResult, args, context) {
140144
// TODO: decode incoming IDs here
141-
return context.queries.widgets(context);
145+
return context.queries.isAvailableToShip(context);
142146
}
143147
```
144148

@@ -152,10 +156,10 @@ Make adjustments to the resolver function so that it reads and passes along the
152156
In `resolvers/Query/index.js` in the plugin, import your query resolver and add it to the default export object. Example:
153157

154158
```js
155-
import widgets from "./widgets"
159+
import isAvailableToShip from "./isAvailableToShip.js"
156160

157161
export default {
158-
widgets
162+
isAvailableToShip
159163
};
160164
```
161165

@@ -202,17 +206,17 @@ Calling your query with GraphQL should now work.
202206

203207
## Add a test file for your query resolver
204208

205-
If your query resolver is in a file named `widgets.js`, your Jest tests should be in a file named `widgets.test.js` in the same folder. Initially you can copy and paste the following test:
209+
If your query resolver is in a file named `isAvailableToShip.js`, your Jest tests should be in a file named `isAvailableToShip.test.js` in the same folder. Initially you can copy and paste the following test:
206210

207211
```js
208-
import widgets from "./widgets";
212+
import isAvailableToShip from "./isAvailableToShip.js";
209213

210-
test("calls queries.widgets and returns the result", async () => {
214+
test("calls queries.isAvailableToShip and returns the result", async () => {
211215
const mockResponse = "MOCK_RESPONSE";
212-
const mockQuery = jest.fn().mockName("queries.widgets").mockReturnValueOnce(Promise.resolve(mockResponse));
216+
const mockQuery = jest.fn().mockName("queries.isAvailableToShip").mockReturnValueOnce(Promise.resolve(mockResponse));
213217

214-
const result = await widgets(null, { /* TODO */ }, {
215-
queries: { widgets: mockQuery },
218+
const result = await isAvailableToShip(null, { /* TODO */ }, {
219+
queries: { isAvailableToShip: mockQuery },
216220
userId: "123"
217221
});
218222

@@ -229,8 +233,8 @@ Adjust the query function and the query resolver function until they work as exp
229233

230234
## Update the JSDoc comments
231235

232-
Write/update jsdoc comments for the plugin query function, the query resolver, and any util functions. The resolver function must have `@memberof <PluginName>/GraphQL` in the jsdoc, and the `@name` must be the full GraphQL schema path in quotation marks, e.g., "Query.widgets". (The quotation marks are necessary for the output API documentation to be correct due to the periods.)
236+
Write/update jsdoc comments for the plugin query function, the query resolver, and any util functions. The resolver function must have `@memberof <PluginName>/GraphQL` in the jsdoc, and the `@name` must be the full GraphQL schema path in quotation marks, e.g., "Query.isAvailableToShip". (The quotation marks are necessary for the output API documentation to be correct due to the periods.)
233237

234238
## More resources
235239

236-
[Build an API plugin guide](https://mailchimp.com/developer/open-commerce/guides/build-api-plugin/)
240+
[Build an API plugin guide](https://mailchimp.com/developer/open-commerce/guides/build-api-plugin/)

0 commit comments

Comments
 (0)