Skip to content

Commit

Permalink
Make keystone optional for ssgc functions (#3355)
Browse files Browse the repository at this point in the history
  • Loading branch information
singhArmani committed Aug 7, 2020
1 parent f8d4b17 commit 1a89bbd
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 31 deletions.
7 changes: 7 additions & 0 deletions .changeset/famous-ties-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@keystonejs/server-side-graphql-client': minor
'@keystonejs/keystone': patch
---

- Added a function `gqlNames(listKey)` to the `context` object created by `keystone.createContext` This allows extracting graphQL query and mutation names from the `context` object.
- Made the `keystone` argument optional when a `context` value is provided in any of the utility functions in `server-side-graphql-client` package.
1 change: 1 addition & 0 deletions packages/keystone/lib/Keystone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ module.exports = class Keystone {
}) => this.createContext({ schemaName, authentication, skipAccessControl });
context.executeGraphQL = ({ context = defaults.context, query, variables }) =>
this.executeGraphQL({ context, query, variables });
context.gqlNames = listKey => this.lists[listKey].gqlNames;
return context;
}

Expand Down
2 changes: 2 additions & 0 deletions packages/server-side-graphql-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ The following config options are common to all server-side graphQL functions.
| `returnFields` | `String` | `id` | A graphQL fragment of fields to return. Must match the graphQL return type. |
| `context` | `Object` | N/A | An Apollo [`context` object](https://www.apollographql.com/docs/apollo-server/data/resolvers/#the-context-argument). See the [server side graphQL docs](/docs/discussions/server-side-graphql.md) for more details. |

> NOTE: If `context` argument is provided then the `keystone` argument is not required.
### `createItem`

Create a single item.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
const runQuery = async ({ keystone, query, variables, context }) => {
const { data, errors } = await keystone.executeGraphQL({
context:
context ||
keystone.createContext({ schemaName: 'public', authentication: {}, skipAccessControl: true }),
const getContext = keystone =>
keystone.createContext({
schemaName: 'public',
authentication: {},
skipAccessControl: true,
});

const runQuery = async ({ keystone, query, variables, context = getContext(keystone) }) => {
const { data, errors } = await context.executeGraphQL({
query,
variables,
});

if (errors) throw errors[0];
return data;
};

const _runChunkedMutation = async ({ keystone, query, gqlName, pageSize, items, context }) => {
const _runChunkedMutation = async ({ query, gqlName, pageSize, items, context }) => {
if (pageSize <= 0) pageSize = 1;

const chunks = items.reduce((accum, item, index) => {
Expand All @@ -27,7 +31,7 @@ const _runChunkedMutation = async ({ keystone, query, gqlName, pageSize, items,
}, []);

const result = await Promise.all(
chunks.map(chunk => runQuery({ query, variables: { items: chunk }, keystone, context }))
chunks.map(chunk => runQuery({ query, variables: { items: chunk }, context }))
);

/*
Expand All @@ -38,8 +42,14 @@ const _runChunkedMutation = async ({ keystone, query, gqlName, pageSize, items,
return [].concat(...result.map(item => item[gqlName]));
};

const createItem = async ({ keystone, listKey, item, returnFields = `id`, context }) => {
const { createMutationName, createInputName } = keystone.lists[listKey].gqlNames;
const createItem = async ({
keystone,
listKey,
item,
returnFields = `id`,
context = getContext(keystone),
}) => {
const { createMutationName, createInputName } = context.gqlNames(listKey);

const query = `mutation ($item: ${createInputName}){
${createMutationName}(data: $item) { ${returnFields} }
Expand All @@ -55,16 +65,15 @@ const createItems = async ({
items,
pageSize = 500,
returnFields = `id`,
context,
context = getContext(keystone),
}) => {
const { createManyMutationName, createManyInputName } = keystone.lists[listKey].gqlNames;
const { createManyMutationName, createManyInputName } = context.gqlNames(listKey);

const query = `mutation ($items: [${createManyInputName}]){
${createManyMutationName}(data: $items) { ${returnFields} }
}`;

return _runChunkedMutation({
keystone,
query,
items,
pageSize,
Expand All @@ -73,11 +82,17 @@ const createItems = async ({
});
};

const getItem = async ({ keystone, listKey, itemId, returnFields = `id`, context }) => {
const { itemQueryName } = keystone.lists[listKey].gqlNames;
const getItem = async ({
keystone,
listKey,
itemId,
returnFields = `id`,
context = getContext(keystone),
}) => {
const { itemQueryName } = context.gqlNames(listKey);

const query = `query ($id: ID!) { ${itemQueryName}(where: { id: $id }) { ${returnFields} } }`;
const result = await runQuery({ keystone, query, variables: { id: itemId }, context });
const result = await runQuery({ query, variables: { id: itemId }, context });
return result[itemQueryName];
};

Expand All @@ -90,9 +105,9 @@ const getItems = async ({
skip,
pageSize = 500,
returnFields = `id`,
context,
context = getContext(keystone),
}) => {
const { listQueryName, whereInputName, listSortName } = keystone.lists[listKey].gqlNames;
const { listQueryName, whereInputName, listSortName } = context.gqlNames(listKey);

let query;
if (sortBy) {
Expand All @@ -113,7 +128,6 @@ const getItems = async ({
_first = first - allItems.length;
}
const response = await runQuery({
keystone,
query,
context,
variables: { first: _first, skip: _skip, sortBy, where },
Expand All @@ -129,15 +143,20 @@ const getItems = async ({
return allItems;
};

const updateItem = async ({ keystone, listKey, item, returnFields = `id`, context }) => {
const { updateMutationName, updateInputName } = keystone.lists[listKey].gqlNames;
const updateItem = async ({
keystone,
listKey,
item,
returnFields = `id`,
context = getContext(keystone),
}) => {
const { updateMutationName, updateInputName } = context.gqlNames(listKey);

const query = `mutation ($id: ID!, $data: ${updateInputName}){
${updateMutationName}(id: $id, data: $data) { ${returnFields} }
}`;

const result = await runQuery({
keystone,
query,
variables: { id: item.id, data: item.data },
context,
Expand All @@ -152,15 +171,14 @@ const updateItems = async ({
items,
pageSize = 500,
returnFields = `id`,
context,
context = getContext(keystone),
}) => {
const { updateManyMutationName, updateManyInputName } = keystone.lists[listKey].gqlNames;
const { updateManyMutationName, updateManyInputName } = context.gqlNames(listKey);

const query = `mutation ($items: [${updateManyInputName}]){
${updateManyMutationName}(data: $items) { ${returnFields} }
}`;
return _runChunkedMutation({
keystone,
query,
items,
pageSize,
Expand All @@ -169,14 +187,20 @@ const updateItems = async ({
});
};

const deleteItem = async ({ keystone, listKey, itemId, returnFields = `id`, context }) => {
const { deleteMutationName } = keystone.lists[listKey].gqlNames;
const deleteItem = async ({
keystone,
listKey,
itemId,
returnFields = `id`,
context = getContext(keystone),
}) => {
const { deleteMutationName } = context.gqlNames(listKey);

const query = `mutation ($id: ID!){
${deleteMutationName}(id: $id) { ${returnFields} }
}`;

const result = await runQuery({ keystone, query, variables: { id: itemId }, context });
const result = await runQuery({ query, variables: { id: itemId }, context });
return result[deleteMutationName];
};

Expand All @@ -186,9 +210,9 @@ const deleteItems = async ({
items,
pageSize = 500,
returnFields = `id`,
context,
context = getContext(keystone),
}) => {
const { deleteManyMutationName } = keystone.lists[listKey].gqlNames;
const { deleteManyMutationName } = context.gqlNames(listKey);

const query = `mutation ($items: [ID!]){
${deleteManyMutationName}(ids: $items) {
Expand All @@ -197,7 +221,6 @@ const deleteItems = async ({
}`;

return _runChunkedMutation({
keystone,
query,
items,
pageSize,
Expand Down
41 changes: 40 additions & 1 deletion packages/server-side-graphql-client/tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,18 @@ multiAdapterRunners().map(({ runner, adapterName }) =>
test(
'createItem: Should create and get single item',
runner(setupKeystone, async ({ keystone }) => {
const testContext = keystone.createContext({
schemaName: 'public',
authentication: {},
skipAccessControl: true,
});
// Seed the db
const item = await createItem({ keystone, listKey: 'Test', item: testData[0].data });
const item = await createItem({
keystone,
context: testContext,
listKey: 'Test',
item: testData[0].data,
});
expect(typeof item.id).toBe('string');

// Get single item from db
Expand Down Expand Up @@ -258,5 +268,34 @@ multiAdapterRunners().map(({ runner, adapterName }) =>
})
);
});
describe('context', () => {
test(
'Should make keystone optional when context is present',
runner(setupKeystone, async ({ keystone }) => {
const testContext = keystone.createContext({
schemaName: 'public',
authentication: {},
skipAccessControl: true,
});
// Seed the db
const item = await createItem({
context: testContext,
listKey: 'Test',
item: testData[0].data,
});
expect(typeof item.id).toBe('string');

// Get single item from db
const singleItem = await getItem({
context: testContext,
listKey: 'Test',
returnFields: 'name, age',
itemId: item.id,
});

expect(singleItem).toEqual(testData[0].data);
})
);
});
})
);

0 comments on commit 1a89bbd

Please sign in to comment.