Skip to content

Commit

Permalink
Add listKey argument to hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
timleslie committed Aug 19, 2020
1 parent d29a348 commit 574f112
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/big-jeans-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystonejs/keystone': minor
---

Added `listKey` as an argument to all hooks.
26 changes: 26 additions & 0 deletions docs/api/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ The result is passed to [the next function in the execution order](/docs/guides/
| `originalInput` | `Object` | The data received by the GraphQL mutation |
| `resolvedData` | `Object` | The data received by the GraphQL mutation plus defaults values |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/data/data/#context-argument) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -168,6 +169,7 @@ const resolveInput = ({
originalInput,
resolvedData,
context,
listKey,
}) => {
// Input resolution logic. Object returned is used in place of `resolvedData`.
return resolvedData;
Expand All @@ -194,6 +196,7 @@ Return values are ignored.
| `resolvedData` | `Object` | The data received by the GraphQL mutation plus defaults values |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/data/data/#context-argument) for this request |
| `addFieldValidationError` | `Function` | Used to set a field validation error; accepts a `String` |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -206,6 +209,7 @@ const validateInput = ({
resolvedData,
context,
addFieldValidationError,
listKey,
}) => {
// Throw error objects or register validation errors with addFieldValidationError(<String>)
// Return values ignored
Expand All @@ -231,6 +235,7 @@ Return values are ignored.
| `originalInput` | `Object` | The data received by the GraphQL mutation |
| `resolvedData` | `Object` | The data received by the GraphQL mutation plus defaults values |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/data/data/#context-argument) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -242,6 +247,7 @@ const beforeChange = ({
originalInput,
resolvedData,
context,
listKey,
}) => {
// Perform side effects
// Return values ignored
Expand Down Expand Up @@ -271,6 +277,7 @@ Return values are ignored.
| `originalInput` | `Object` | The data received by the GraphQL mutation |
| `updatedItem` | `Object` | The new/currently stored item |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/data/data/#context-argument) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -282,6 +289,7 @@ const afterChange = ({
originalInput,
updatedItem,
context,
listKey,
}) => {
// Perform side effects
// Return values ignored
Expand All @@ -305,6 +313,7 @@ Should throw or register errors with `addFieldValidationError(<String>)` if the
| `existingItem` | `Object` | The current stored item |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/data/data/#context-argument) for this request |
| `addFieldValidationError` | `Function` | Used to set a field validation error; accepts a `String` |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -315,6 +324,7 @@ const validateDelete = ({
existingItem,
context,
addFieldValidationError,
listKey,
}) => {
// Throw error objects or register validation errors with addFieldValidationError(<String>)
// Return values ignored
Expand All @@ -338,6 +348,7 @@ Return values are ignored.
| `operation` | `String` | The operation being performed (`delete` in this case) |
| `existingItem` | `Object` | The current stored item |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/data/data/#context-argument) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -347,6 +358,7 @@ const beforeDelete = ({
operation,
existingItem,
context,
listKey,
}) => {
// Perform side effects
// Return values ignored
Expand All @@ -372,6 +384,7 @@ Return values are ignored.
| `operation` | `String` | The operation being performed (`delete` in this case) |
| `existingItem` | `Object` | The previously stored item, now deleted |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/data/data/#context-argument) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -381,6 +394,7 @@ const afterDelete = ({
operation,
existingItem,
context,
listKey,
}) => {
// Perform side effects
// Return values ignored
Expand All @@ -405,6 +419,7 @@ The result is passed to [the next function in the execution order](/docs/guides/
| `operation` | `String` | The operation being performed (`authenticate` in this case) |
| `originalInput` | `Object` | The data received by the GraphQL mutation |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/essentials/data.html#context) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -414,6 +429,7 @@ const resolveAuthInput = ({
operation,
originalInput,
context,
listKey,
}) => {
// Input resolution logic
// Object returned is used in place of resolvedData
Expand All @@ -440,6 +456,7 @@ Return values are ignored.
| `resolvedData` | `Object` | The data received by the GraphQL mutation or returned by `resolveAuthInput`, if defined |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/essentials/data.html#context) for this request |
| `addValidationError` | `Function` | Used to set a validation error; accepts a message `String` |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -451,6 +468,7 @@ const validateAuthInput = ({
resolvedData,
context,
addFieldValidationError,
listKey,
}) => {
// Throw error objects or register validation errors with addValidationError(<String>)
// Return values ignored
Expand All @@ -475,6 +493,7 @@ Return values are ignored.
| `originalInput` | `Object` | The data received by the GraphQL mutation |
| `resolvedData` | `Object` | The data received by the GraphQL mutation or returned by `resolveAuthInput`, if defined |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/essentials/data.html#context) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -485,6 +504,7 @@ const beforeAuth = ({
originalInput,
resolvedData,
context,
listKey,
}) => {
// Perform side effects
// Return values ignored
Expand Down Expand Up @@ -515,6 +535,7 @@ Return values are ignored.
| `originalInput` | `Object` | The data received by the GraphQL mutation |
| `resolvedData` | `Object` | The data received by the GraphQL mutation or returned by `resolveAuthInput`, if defined |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/essentials/data.html#context) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -529,6 +550,7 @@ const afterAuth = ({
originalInput,
resolvedData,
context,
listKey,
}) => {
// Perform side effects
// Return values ignored
Expand All @@ -551,6 +573,7 @@ Return values are ignored.
| :---------- | :--------------- | :---------------------------------------------------------------------------------------------------------------------------- |
| `operation` | `String` | The operation being performed (`authenticate` in this case) |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/essentials/data.html#context) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -559,6 +582,7 @@ Return values are ignored.
const beforeUnauth = ({
operation,
context,
listKey,
}) => {
// Perform side effects
// Return values ignored
Expand Down Expand Up @@ -586,6 +610,7 @@ Return values are ignored.
| `listKey` | `String` | The list key of the unauthenticated user (if there was one) |
| `itemid` | `String` | The item ID of the unauthenticated user (if there was one) |
| `context` | `Apollo Context` | The [Apollo `context` object](https://www.apollographql.com/docs/apollo-server/essentials/data.html#context) for this request |
| `listKey` | `String` | The key for the list being operated on |

#### Usage

Expand All @@ -600,6 +625,7 @@ const afterAuth = ({
originalInput,
resolvedData,
context,
listKey,
}) => {
// Perform side effects
// Return values ignored
Expand Down
21 changes: 14 additions & 7 deletions packages/keystone/lib/ListTypes/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class HookManager {
}

async resolveInput({ resolvedData, existingItem, context, operation, originalInput }) {
const args = { resolvedData, existingItem, context, originalInput, operation };
const { listKey } = this;
const args = { resolvedData, existingItem, context, originalInput, operation, listKey };

// First we run the field type hooks
// NOTE: resolveInput is run on _every_ field, regardless if it has a value
Expand Down Expand Up @@ -70,7 +71,8 @@ class HookManager {
}

async validateInput({ resolvedData, existingItem, context, operation, originalInput }) {
const args = { resolvedData, existingItem, context, originalInput, operation };
const { listKey } = this;
const args = { resolvedData, existingItem, context, originalInput, operation, listKey };
// Check for isRequired
const fieldValidationErrors = this.fields
.filter(
Expand All @@ -97,7 +99,8 @@ class HookManager {
}

async validateDelete({ existingItem, context, operation }) {
const args = { existingItem, context, operation };
const { listKey } = this;
const args = { existingItem, context, operation, listKey };
const fields = this.fields;
await this._validateHook({ args, fields, operation, hookName: 'validateDelete' });
}
Expand Down Expand Up @@ -131,22 +134,26 @@ class HookManager {
}

async beforeChange({ resolvedData, existingItem, context, operation, originalInput }) {
const args = { resolvedData, existingItem, context, originalInput, operation };
const { listKey } = this;
const args = { resolvedData, existingItem, context, originalInput, operation, listKey };
await this._runHook({ args, fieldObject: resolvedData, hookName: 'beforeChange' });
}

async beforeDelete({ existingItem, context, operation }) {
const args = { existingItem, context, operation };
const { listKey } = this;
const args = { existingItem, context, operation, listKey };
await this._runHook({ args, fieldObject: existingItem, hookName: 'beforeDelete' });
}

async afterChange({ updatedItem, existingItem, context, operation, originalInput }) {
const args = { updatedItem, originalInput, existingItem, context, operation };
const { listKey } = this;
const args = { updatedItem, originalInput, existingItem, context, operation, listKey };
await this._runHook({ args, fieldObject: updatedItem, hookName: 'afterChange' });
}

async afterDelete({ existingItem, context, operation }) {
const args = { existingItem, context, operation };
const { listKey } = this;
const args = { existingItem, context, operation, listKey };
await this._runHook({ args, fieldObject: existingItem, hookName: 'afterDelete' });
}

Expand Down
35 changes: 28 additions & 7 deletions packages/keystone/lib/providers/listAuth.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@ const { throwAccessDenied, ValidationFailureError } = require('../ListTypes/grap
const graphqlLogger = logger('graphql');

class HookManager {
constructor({ name, hooks = {} }) {
constructor({ name, listKey, hooks = {} }) {
this.name = name;
this.hooks = hooks;
this.listKey = listKey;
}

async resolveAuthInput({ context, operation, originalInput }) {
const { listKey } = this;
let resolvedData = originalInput;

if (this.hooks.resolveAuthInput) {
const args = { context, originalInput, operation, listKey };
// And run any list-level hook
resolvedData = await this.hooks.resolveAuthInput({ context, originalInput, operation });
resolvedData = await this.hooks.resolveAuthInput(args);
if (typeof resolvedData !== 'object') {
const method = `${this.name}.hooks.resolveAuthInput()`;
throw new Error(
Expand All @@ -29,7 +32,8 @@ class HookManager {
}

async validateAuthInput({ resolvedData, context, operation, originalInput }) {
const args = { resolvedData, context, originalInput, operation };
const { listKey } = this;
const args = { resolvedData, context, originalInput, operation, listKey };

if (this.hooks['validateAuthInput']) {
const listValidationErrors = [];
Expand All @@ -55,7 +59,8 @@ class HookManager {
}

async beforeAuth({ resolvedData, context, operation, originalInput }) {
const args = { resolvedData, context, originalInput, operation };
const { listKey } = this;
const args = { resolvedData, context, originalInput, operation, listKey };
if (this.hooks.beforeAuth) await this.hooks.beforeAuth(args);
}

Expand All @@ -69,12 +74,24 @@ class HookManager {
resolvedData,
context,
}) {
const args = { resolvedData, context, operation, originalInput, item, success, message, token };
const { listKey } = this;
const args = {
resolvedData,
context,
operation,
originalInput,
item,
success,
message,
token,
listKey,
};
if (this.hooks.afterAuth) await this.hooks.afterAuth(args);
}

async beforeUnauth({ operation, context }) {
const args = { context, operation };
const { listKey } = this;
const args = { context, operation, listKey };
if (this.hooks.beforeUnauth) await this.hooks.beforeUnauth(args);
}

Expand All @@ -99,7 +116,11 @@ class ListAuthProvider {
unauthenticateOutputName: `unauthenticate${itemQueryName}Output`,
updateAuthenticatedMutationName: `updateAuthenticated${itemQueryName}`,
};
this.hookManager = new HookManager({ name: authStrategy.constructor.name, hooks });
this.hookManager = new HookManager({
name: authStrategy.constructor.name,
hooks,
listKey: list.key,
});
// Record GQL names in the strategy
authStrategy.gqlNames = this.gqlNames;
}
Expand Down

0 comments on commit 574f112

Please sign in to comment.