diff --git a/packages/core/src/types/config/hooks.ts b/packages/core/src/types/config/hooks.ts index ef3e30bc18d..0bcdfc52ad2 100644 --- a/packages/core/src/types/config/hooks.ts +++ b/packages/core/src/types/config/hooks.ts @@ -1,4 +1,4 @@ -import type { KeystoneContextFromListTypeInfo } from '..'; +import type { KeystoneContextFromListTypeInfo, MaybePromise } from '..'; import { BaseListTypeInfo } from '../type-info'; type CommonArgs = { @@ -32,45 +32,6 @@ export type ListHooks = { afterOperation?: AfterOperationHook; }; -// TODO: probably maybe don't do this and write it out manually -// (this is also incorrect because the return value is wrong for many of them) -type AddFieldPathToObj any> = T extends (args: infer Args) => infer Result - ? (args: Args & { fieldKey: string }) => Result - : never; - -type AddFieldPathArgToAllPropsOnObj any>> = { - [Key in keyof T]: AddFieldPathToObj; -}; - -type FieldKeysForList = - keyof ListTypeInfo['inputs']['update']; // TODO: uh - -export type FieldHooks< - ListTypeInfo extends BaseListTypeInfo, - FieldKey extends FieldKeysForList = FieldKeysForList -> = AddFieldPathArgToAllPropsOnObj<{ - /** - * Used to **modify the input** for create and update operations after default values and access control have been applied - */ - resolveInput?: ResolveInputFieldHook; - /** - * Used to **validate the input** for create and update operations once all resolveInput hooks resolved - */ - validateInput?: ValidateInputHook; - /** - * Used to **validate** that a delete operation can happen after access control has occurred - */ - validateDelete?: ValidateDeleteHook; - /** - * Used to **cause side effects** before a create, update, or delete operation once all validateInput hooks have resolved - */ - beforeOperation?: BeforeOperationHook; - /** - * Used to **cause side effects** after a create, update, or delete operation operation has occurred - */ - afterOperation?: AfterOperationHook; -}>; - type ArgsForCreateOrUpdateOperation = | { operation: 'create'; @@ -104,9 +65,7 @@ type ArgsForCreateOrUpdateOperation = type ResolveInputListHook = ( args: ArgsForCreateOrUpdateOperation & CommonArgs ) => - | Promise - | ListTypeInfo['inputs']['create'] - | ListTypeInfo['inputs']['update'] + | MaybePromise // TODO: These were here to support field hooks before we created a separate type // (see ResolveInputFieldHook), check whether they're safe to remove now | Record @@ -115,17 +74,6 @@ type ResolveInputListHook = ( | boolean | null; -type ResolveInputFieldHook< - ListTypeInfo extends BaseListTypeInfo, - FieldKey extends FieldKeysForList -> = ( - args: ArgsForCreateOrUpdateOperation & CommonArgs -) => - | Promise - | ListTypeInfo['inputs']['create'][FieldKey] - | ListTypeInfo['inputs']['update'][FieldKey] - | undefined; // undefined represents 'don't do anything' - type ValidateInputHook = ( args: ArgsForCreateOrUpdateOperation & { addValidationError: (error: string) => void; @@ -178,3 +126,119 @@ type AfterOperationHook = ( ) & CommonArgs ) => Promise | void; + +// Field Hooks +type FieldKeysForList = + keyof ListTypeInfo['inputs']['update']; // TODO: uh + +type CommonFieldArgs> = { + context: KeystoneContextFromListTypeInfo; + /** + * The key of the list that the operation is occurring on + */ + listKey: string; + + /** + * The key of the field that the operation is occurring on + */ + fieldKey: FieldKey; +}; + +type ResolveInputFieldHook< + ListTypeInfo extends BaseListTypeInfo, + FieldKey extends FieldKeysForList +> = ( + args: ArgsForCreateOrUpdateOperation & CommonFieldArgs +) => + | MaybePromise + | undefined; // undefined represents 'don't do anything' + +type ValidateInputFieldHook< + ListTypeInfo extends BaseListTypeInfo, + FieldKey extends FieldKeysForList +> = ( + args: ArgsForCreateOrUpdateOperation & { + addValidationError: (error: string) => void; + } & CommonFieldArgs +) => Promise | void; + +type ValidateDeleteFieldHook< + ListTypeInfo extends BaseListTypeInfo, + FieldKey extends FieldKeysForList +> = ( + args: { + operation: 'delete'; + item: ListTypeInfo['item']; + addValidationError: (error: string) => void; + } & CommonFieldArgs +) => Promise | void; + +type BeforeOperationFieldHook< + ListTypeInfo extends BaseListTypeInfo, + FieldKey extends FieldKeysForList +> = ( + args: ( + | ArgsForCreateOrUpdateOperation + | { + operation: 'delete'; + item: ListTypeInfo['item']; + inputData: undefined; + resolvedData: undefined; + } + ) & CommonFieldArgs +) => Promise | void; + +type AfterOperationFieldHook< + ListTypeInfo extends BaseListTypeInfo, + FieldKey extends FieldKeysForList +> = ( + args: ( + | ArgsForCreateOrUpdateOperation + | { + operation: 'delete'; + // technically this will never actually exist for a delete + // but making it optional rather than not here + // makes for a better experience + // because then people will see the right type even if they haven't refined the type of operation to 'delete' + item: undefined; + inputData: undefined; + resolvedData: undefined; + } + ) & + ({ operation: 'delete' } | { operation: 'create' | 'update'; item: ListTypeInfo['item'] }) & + ( + | // technically this will never actually exist for a create + // but making it optional rather than not here + // makes for a better experience + // because then people will see the right type even if they haven't refined the type of operation to 'create' + { operation: 'create'; originalItem: undefined } + | { operation: 'delete' | 'update'; originalItem: ListTypeInfo['item'] } + ) & + CommonFieldArgs +) => Promise | void; + +export type FieldHooks< + ListTypeInfo extends BaseListTypeInfo, + FieldKey extends FieldKeysForList = FieldKeysForList +> = { + /** + * Used to **modify the input** for create and update operations after default values and access control have been applied + */ + resolveInput?: ResolveInputFieldHook; + /** + * Used to **validate the input** for create and update operations once all resolveInput hooks resolved + */ + validateInput?: ValidateInputFieldHook; + /** + * Used to **validate** that a delete operation can happen after access control has occurred + */ + validateDelete?: ValidateDeleteFieldHook; + /** + * Used to **cause side effects** before a create, update, or delete operation once all validateInput hooks have resolved + */ + beforeOperation?: BeforeOperationFieldHook; + /** + * Used to **cause side effects** after a create, update, or delete operation operation has occurred + */ + afterOperation?: AfterOperationFieldHook; +};