From f5e64af37df2eb460c89d89fa3c8924fb34970ed Mon Sep 17 00:00:00 2001 From: Mitchell Hamilton Date: Wed, 28 Jul 2021 11:49:20 +1000 Subject: [PATCH] Unique where inputs in deletes (#6206) --- .changeset/wise-pianos-flash.md | 8 ++++++ examples-staging/assets-cloud/schema.graphql | 8 +++--- examples-staging/assets-local/schema.graphql | 8 +++--- examples-staging/auth/schema.graphql | 4 +-- examples-staging/basic/schema.graphql | 12 ++++---- .../ecommerce/mutations/checkout.ts | 2 +- examples-staging/ecommerce/schema.graphql | 28 +++++++++---------- .../embedded-nextjs/schema.graphql | 4 +-- .../graphql-api-endpoint/schema.graphql | 12 ++++---- examples-staging/playground/schema.graphql | 4 +-- examples-staging/roles/schema.graphql | 12 ++++---- examples-staging/sandbox/schema.graphql | 8 +++--- examples/blog/schema.graphql | 8 +++--- examples/custom-admin-ui-logo/schema.graphql | 8 +++--- examples/custom-field-view/schema.graphql | 8 +++--- examples/custom-field/schema.graphql | 8 +++--- examples/default-values/schema.graphql | 8 +++--- examples/document-field/schema.graphql | 8 +++--- examples/extend-graphql-schema/schema.graphql | 8 +++--- examples/json/schema.graphql | 8 +++--- examples/task-manager/schema.graphql | 8 +++--- examples/testing/schema.graphql | 8 +++--- examples/virtual-field/schema.graphql | 8 +++--- examples/with-auth/schema.graphql | 8 +++--- .../admin-ui/pages/ItemPage/index.tsx | 2 +- .../admin-ui/pages/ListPage/index.tsx | 6 ++-- .../keystone/src/lib/core/mutations/index.ts | 21 +++++++------- .../fixtures/basic-project/schema.graphql | 4 +-- packages/types/src/context.ts | 16 ++++++++--- tests/api-tests/access-control/authed.test.ts | 22 ++++++++------- .../mutations-list-declarative.test.ts | 13 +++++---- .../mutations-list-static.test.ts | 10 ++++--- .../access-control/not-authed.test.ts | 4 +-- tests/api-tests/fields/crud.test.ts | 10 +++++-- tests/api-tests/fields/types/document.test.ts | 2 +- tests/api-tests/hooks/validation.test.ts | 10 ++++--- tests/api-tests/queries/cache-hints.test.ts | 2 +- .../many-to-many-one-sided.test.ts | 2 +- .../crud-self-ref/many-to-many.test.ts | 2 +- .../one-to-many-one-sided.test.ts | 6 ++-- .../crud-self-ref/one-to-many.test.ts | 2 +- .../crud-self-ref/one-to-one.test.ts | 2 +- .../crud/many-to-many-one-sided.test.ts | 2 +- .../relationships/crud/many-to-many.test.ts | 2 +- .../crud/one-to-many-one-sided.test.ts | 6 ++-- .../relationships/crud/one-to-many.test.ts | 2 +- .../relationships/crud/one-to-one.test.ts | 4 +-- .../two-way-backreference/to-many.test.ts | 2 +- tests/test-projects/basic/schema.graphql | 8 +++--- 49 files changed, 199 insertions(+), 169 deletions(-) create mode 100644 .changeset/wise-pianos-flash.md diff --git a/.changeset/wise-pianos-flash.md b/.changeset/wise-pianos-flash.md new file mode 100644 index 00000000000..9a6d732caf1 --- /dev/null +++ b/.changeset/wise-pianos-flash.md @@ -0,0 +1,8 @@ +--- +'@keystone-next/keystone': major +'@keystone-next/types': major +--- + +The delete mutations now accept `where` unique inputs instead of only an `id`. + +If you have a list called `Item`, `deleteItem` now looks like `deleteItem(where: ItemWhereUniqueInput!): Item` and `deleteItems` now looks like `deleteItems(where: [ItemWhereUniqueInput!]!): [Item]` diff --git a/examples-staging/assets-cloud/schema.graphql b/examples-staging/assets-cloud/schema.graphql index db4ef456b16..7ef44fff5d7 100644 --- a/examples-staging/assets-cloud/schema.graphql +++ b/examples-staging/assets-cloud/schema.graphql @@ -255,14 +255,14 @@ type Mutation { createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] createAuthor(data: AuthorCreateInput): Author createAuthors(data: [AuthorsCreateInput]): [Author] updateAuthor(id: ID!, data: AuthorUpdateInput): Author updateAuthors(data: [AuthorUpdateArgs]): [Author] - deleteAuthor(id: ID!): Author - deleteAuthors(ids: [ID!]): [Author] + deleteAuthor(where: AuthorWhereUniqueInput!): Author + deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] } type Query { diff --git a/examples-staging/assets-local/schema.graphql b/examples-staging/assets-local/schema.graphql index 1f17857bb60..0aca326a079 100644 --- a/examples-staging/assets-local/schema.graphql +++ b/examples-staging/assets-local/schema.graphql @@ -233,14 +233,14 @@ type Mutation { createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] createAuthor(data: AuthorCreateInput): Author createAuthors(data: [AuthorsCreateInput]): [Author] updateAuthor(id: ID!, data: AuthorUpdateInput): Author updateAuthors(data: [AuthorUpdateArgs]): [Author] - deleteAuthor(id: ID!): Author - deleteAuthors(ids: [ID!]): [Author] + deleteAuthor(where: AuthorWhereUniqueInput!): Author + deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] } type Query { diff --git a/examples-staging/auth/schema.graphql b/examples-staging/auth/schema.graphql index 27a91b43f07..8737df31952 100644 --- a/examples-staging/auth/schema.graphql +++ b/examples-staging/auth/schema.graphql @@ -91,8 +91,8 @@ type Mutation { createUsers(data: [UsersCreateInput]): [User] updateUser(id: ID!, data: UserUpdateInput): User updateUsers(data: [UserUpdateArgs]): [User] - deleteUser(id: ID!): User - deleteUsers(ids: [ID!]): [User] + deleteUser(where: UserWhereUniqueInput!): User + deleteUsers(where: [UserWhereUniqueInput!]!): [User] authenticateUserWithPassword( email: String! password: String! diff --git a/examples-staging/basic/schema.graphql b/examples-staging/basic/schema.graphql index fd95da5072b..f10a7eaf32c 100644 --- a/examples-staging/basic/schema.graphql +++ b/examples-staging/basic/schema.graphql @@ -355,20 +355,20 @@ type Mutation { createUsers(data: [UsersCreateInput]): [User] updateUser(id: ID!, data: UserUpdateInput): User updateUsers(data: [UserUpdateArgs]): [User] - deleteUser(id: ID!): User - deleteUsers(ids: [ID!]): [User] + deleteUser(where: UserWhereUniqueInput!): User + deleteUsers(where: [UserWhereUniqueInput!]!): [User] createPhoneNumber(data: PhoneNumberCreateInput): PhoneNumber createPhoneNumbers(data: [PhoneNumbersCreateInput]): [PhoneNumber] updatePhoneNumber(id: ID!, data: PhoneNumberUpdateInput): PhoneNumber updatePhoneNumbers(data: [PhoneNumberUpdateArgs]): [PhoneNumber] - deletePhoneNumber(id: ID!): PhoneNumber - deletePhoneNumbers(ids: [ID!]): [PhoneNumber] + deletePhoneNumber(where: PhoneNumberWhereUniqueInput!): PhoneNumber + deletePhoneNumbers(where: [PhoneNumberWhereUniqueInput!]!): [PhoneNumber] createPost(data: PostCreateInput): Post createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] authenticateUserWithPassword( email: String! password: String! diff --git a/examples-staging/ecommerce/mutations/checkout.ts b/examples-staging/ecommerce/mutations/checkout.ts index 09cd142d597..78645966d40 100644 --- a/examples-staging/ecommerce/mutations/checkout.ts +++ b/examples-staging/ecommerce/mutations/checkout.ts @@ -88,7 +88,7 @@ async function checkout(root: any, { token }: Arguments, context: KeystoneContex const cartItemIds = user.cart.map((cartItem: any) => cartItem.id); console.log('gonna create delete cartItems'); await context.lists.CartItem.deleteMany({ - ids: cartItemIds, + where: cartItemIds.map((id: string) => ({ id })), }); return order; } diff --git a/examples-staging/ecommerce/schema.graphql b/examples-staging/ecommerce/schema.graphql index f599403b371..384e512eb27 100644 --- a/examples-staging/ecommerce/schema.graphql +++ b/examples-staging/ecommerce/schema.graphql @@ -764,44 +764,44 @@ type Mutation { createUsers(data: [UsersCreateInput]): [User] updateUser(id: ID!, data: UserUpdateInput): User updateUsers(data: [UserUpdateArgs]): [User] - deleteUser(id: ID!): User - deleteUsers(ids: [ID!]): [User] + deleteUser(where: UserWhereUniqueInput!): User + deleteUsers(where: [UserWhereUniqueInput!]!): [User] createProduct(data: ProductCreateInput): Product createProducts(data: [ProductsCreateInput]): [Product] updateProduct(id: ID!, data: ProductUpdateInput): Product updateProducts(data: [ProductUpdateArgs]): [Product] - deleteProduct(id: ID!): Product - deleteProducts(ids: [ID!]): [Product] + deleteProduct(where: ProductWhereUniqueInput!): Product + deleteProducts(where: [ProductWhereUniqueInput!]!): [Product] createProductImage(data: ProductImageCreateInput): ProductImage createProductImages(data: [ProductImagesCreateInput]): [ProductImage] updateProductImage(id: ID!, data: ProductImageUpdateInput): ProductImage updateProductImages(data: [ProductImageUpdateArgs]): [ProductImage] - deleteProductImage(id: ID!): ProductImage - deleteProductImages(ids: [ID!]): [ProductImage] + deleteProductImage(where: ProductImageWhereUniqueInput!): ProductImage + deleteProductImages(where: [ProductImageWhereUniqueInput!]!): [ProductImage] createCartItem(data: CartItemCreateInput): CartItem createCartItems(data: [CartItemsCreateInput]): [CartItem] updateCartItem(id: ID!, data: CartItemUpdateInput): CartItem updateCartItems(data: [CartItemUpdateArgs]): [CartItem] - deleteCartItem(id: ID!): CartItem - deleteCartItems(ids: [ID!]): [CartItem] + deleteCartItem(where: CartItemWhereUniqueInput!): CartItem + deleteCartItems(where: [CartItemWhereUniqueInput!]!): [CartItem] createOrderItem(data: OrderItemCreateInput): OrderItem createOrderItems(data: [OrderItemsCreateInput]): [OrderItem] updateOrderItem(id: ID!, data: OrderItemUpdateInput): OrderItem updateOrderItems(data: [OrderItemUpdateArgs]): [OrderItem] - deleteOrderItem(id: ID!): OrderItem - deleteOrderItems(ids: [ID!]): [OrderItem] + deleteOrderItem(where: OrderItemWhereUniqueInput!): OrderItem + deleteOrderItems(where: [OrderItemWhereUniqueInput!]!): [OrderItem] createOrder(data: OrderCreateInput): Order createOrders(data: [OrdersCreateInput]): [Order] updateOrder(id: ID!, data: OrderUpdateInput): Order updateOrders(data: [OrderUpdateArgs]): [Order] - deleteOrder(id: ID!): Order - deleteOrders(ids: [ID!]): [Order] + deleteOrder(where: OrderWhereUniqueInput!): Order + deleteOrders(where: [OrderWhereUniqueInput!]!): [Order] createRole(data: RoleCreateInput): Role createRoles(data: [RolesCreateInput]): [Role] updateRole(id: ID!, data: RoleUpdateInput): Role updateRoles(data: [RoleUpdateArgs]): [Role] - deleteRole(id: ID!): Role - deleteRoles(ids: [ID!]): [Role] + deleteRole(where: RoleWhereUniqueInput!): Role + deleteRoles(where: [RoleWhereUniqueInput!]!): [Role] authenticateUserWithPassword( email: String! password: String! diff --git a/examples-staging/embedded-nextjs/schema.graphql b/examples-staging/embedded-nextjs/schema.graphql index 20a2063b387..3c4655fed16 100644 --- a/examples-staging/embedded-nextjs/schema.graphql +++ b/examples-staging/embedded-nextjs/schema.graphql @@ -86,8 +86,8 @@ type Mutation { createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] } type Query { diff --git a/examples-staging/graphql-api-endpoint/schema.graphql b/examples-staging/graphql-api-endpoint/schema.graphql index 095423692b2..13bc9dd812d 100644 --- a/examples-staging/graphql-api-endpoint/schema.graphql +++ b/examples-staging/graphql-api-endpoint/schema.graphql @@ -322,20 +322,20 @@ type Mutation { createUsers(data: [UsersCreateInput]): [User] updateUser(id: ID!, data: UserUpdateInput): User updateUsers(data: [UserUpdateArgs]): [User] - deleteUser(id: ID!): User - deleteUsers(ids: [ID!]): [User] + deleteUser(where: UserWhereUniqueInput!): User + deleteUsers(where: [UserWhereUniqueInput!]!): [User] createPost(data: PostCreateInput): Post createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] createTag(data: TagCreateInput): Tag createTags(data: [TagsCreateInput]): [Tag] updateTag(id: ID!, data: TagUpdateInput): Tag updateTags(data: [TagUpdateArgs]): [Tag] - deleteTag(id: ID!): Tag - deleteTags(ids: [ID!]): [Tag] + deleteTag(where: TagWhereUniqueInput!): Tag + deleteTags(where: [TagWhereUniqueInput!]!): [Tag] authenticateUserWithPassword( email: String! password: String! diff --git a/examples-staging/playground/schema.graphql b/examples-staging/playground/schema.graphql index 987ce514026..2a19209f604 100644 --- a/examples-staging/playground/schema.graphql +++ b/examples-staging/playground/schema.graphql @@ -66,8 +66,8 @@ type Mutation { createNotes(data: [NotesCreateInput]): [Note] updateNote(id: ID!, data: NoteUpdateInput): Note updateNotes(data: [NoteUpdateArgs]): [Note] - deleteNote(id: ID!): Note - deleteNotes(ids: [ID!]): [Note] + deleteNote(where: NoteWhereUniqueInput!): Note + deleteNotes(where: [NoteWhereUniqueInput!]!): [Note] } type Query { diff --git a/examples-staging/roles/schema.graphql b/examples-staging/roles/schema.graphql index b6fab947220..1ffe8df5daa 100644 --- a/examples-staging/roles/schema.graphql +++ b/examples-staging/roles/schema.graphql @@ -295,20 +295,20 @@ type Mutation { createTodos(data: [TodosCreateInput]): [Todo] updateTodo(id: ID!, data: TodoUpdateInput): Todo updateTodos(data: [TodoUpdateArgs]): [Todo] - deleteTodo(id: ID!): Todo - deleteTodos(ids: [ID!]): [Todo] + deleteTodo(where: TodoWhereUniqueInput!): Todo + deleteTodos(where: [TodoWhereUniqueInput!]!): [Todo] createPerson(data: PersonCreateInput): Person createPeople(data: [PeopleCreateInput]): [Person] updatePerson(id: ID!, data: PersonUpdateInput): Person updatePeople(data: [PersonUpdateArgs]): [Person] - deletePerson(id: ID!): Person - deletePeople(ids: [ID!]): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] createRole(data: RoleCreateInput): Role createRoles(data: [RolesCreateInput]): [Role] updateRole(id: ID!, data: RoleUpdateInput): Role updateRoles(data: [RoleUpdateArgs]): [Role] - deleteRole(id: ID!): Role - deleteRoles(ids: [ID!]): [Role] + deleteRole(where: RoleWhereUniqueInput!): Role + deleteRoles(where: [RoleWhereUniqueInput!]!): [Role] authenticatePersonWithPassword( email: String! password: String! diff --git a/examples-staging/sandbox/schema.graphql b/examples-staging/sandbox/schema.graphql index 2cfd8a8081c..f7f6030e250 100644 --- a/examples-staging/sandbox/schema.graphql +++ b/examples-staging/sandbox/schema.graphql @@ -223,14 +223,14 @@ type Mutation { createTodos(data: [TodosCreateInput]): [Todo] updateTodo(id: ID!, data: TodoUpdateInput): Todo updateTodos(data: [TodoUpdateArgs]): [Todo] - deleteTodo(id: ID!): Todo - deleteTodos(ids: [ID!]): [Todo] + deleteTodo(where: TodoWhereUniqueInput!): Todo + deleteTodos(where: [TodoWhereUniqueInput!]!): [Todo] createUser(data: UserCreateInput): User createUsers(data: [UsersCreateInput]): [User] updateUser(id: ID!, data: UserUpdateInput): User updateUsers(data: [UserUpdateArgs]): [User] - deleteUser(id: ID!): User - deleteUsers(ids: [ID!]): [User] + deleteUser(where: UserWhereUniqueInput!): User + deleteUsers(where: [UserWhereUniqueInput!]!): [User] } type Query { diff --git a/examples/blog/schema.graphql b/examples/blog/schema.graphql index e89ebea716b..5ddc9da6ad0 100644 --- a/examples/blog/schema.graphql +++ b/examples/blog/schema.graphql @@ -193,14 +193,14 @@ type Mutation { createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] createAuthor(data: AuthorCreateInput): Author createAuthors(data: [AuthorsCreateInput]): [Author] updateAuthor(id: ID!, data: AuthorUpdateInput): Author updateAuthors(data: [AuthorUpdateArgs]): [Author] - deleteAuthor(id: ID!): Author - deleteAuthors(ids: [ID!]): [Author] + deleteAuthor(where: AuthorWhereUniqueInput!): Author + deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] } type Query { diff --git a/examples/custom-admin-ui-logo/schema.graphql b/examples/custom-admin-ui-logo/schema.graphql index 55380b7c1d2..30beff9bc69 100644 --- a/examples/custom-admin-ui-logo/schema.graphql +++ b/examples/custom-admin-ui-logo/schema.graphql @@ -179,14 +179,14 @@ type Mutation { createTasks(data: [TasksCreateInput]): [Task] updateTask(id: ID!, data: TaskUpdateInput): Task updateTasks(data: [TaskUpdateArgs]): [Task] - deleteTask(id: ID!): Task - deleteTasks(ids: [ID!]): [Task] + deleteTask(where: TaskWhereUniqueInput!): Task + deleteTasks(where: [TaskWhereUniqueInput!]!): [Task] createPerson(data: PersonCreateInput): Person createPeople(data: [PeopleCreateInput]): [Person] updatePerson(id: ID!, data: PersonUpdateInput): Person updatePeople(data: [PersonUpdateArgs]): [Person] - deletePerson(id: ID!): Person - deletePeople(ids: [ID!]): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] } type Query { diff --git a/examples/custom-field-view/schema.graphql b/examples/custom-field-view/schema.graphql index 633316ca9e5..64ed5a1fcfd 100644 --- a/examples/custom-field-view/schema.graphql +++ b/examples/custom-field-view/schema.graphql @@ -182,14 +182,14 @@ type Mutation { createTasks(data: [TasksCreateInput]): [Task] updateTask(id: ID!, data: TaskUpdateInput): Task updateTasks(data: [TaskUpdateArgs]): [Task] - deleteTask(id: ID!): Task - deleteTasks(ids: [ID!]): [Task] + deleteTask(where: TaskWhereUniqueInput!): Task + deleteTasks(where: [TaskWhereUniqueInput!]!): [Task] createPerson(data: PersonCreateInput): Person createPeople(data: [PeopleCreateInput]): [Person] updatePerson(id: ID!, data: PersonUpdateInput): Person updatePeople(data: [PersonUpdateArgs]): [Person] - deletePerson(id: ID!): Person - deletePeople(ids: [ID!]): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] } type Query { diff --git a/examples/custom-field/schema.graphql b/examples/custom-field/schema.graphql index 491ee9da0e4..0cdc565f96f 100644 --- a/examples/custom-field/schema.graphql +++ b/examples/custom-field/schema.graphql @@ -205,14 +205,14 @@ type Mutation { createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] createAuthor(data: AuthorCreateInput): Author createAuthors(data: [AuthorsCreateInput]): [Author] updateAuthor(id: ID!, data: AuthorUpdateInput): Author updateAuthors(data: [AuthorUpdateArgs]): [Author] - deleteAuthor(id: ID!): Author - deleteAuthors(ids: [ID!]): [Author] + deleteAuthor(where: AuthorWhereUniqueInput!): Author + deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] } type Query { diff --git a/examples/default-values/schema.graphql b/examples/default-values/schema.graphql index 55380b7c1d2..30beff9bc69 100644 --- a/examples/default-values/schema.graphql +++ b/examples/default-values/schema.graphql @@ -179,14 +179,14 @@ type Mutation { createTasks(data: [TasksCreateInput]): [Task] updateTask(id: ID!, data: TaskUpdateInput): Task updateTasks(data: [TaskUpdateArgs]): [Task] - deleteTask(id: ID!): Task - deleteTasks(ids: [ID!]): [Task] + deleteTask(where: TaskWhereUniqueInput!): Task + deleteTasks(where: [TaskWhereUniqueInput!]!): [Task] createPerson(data: PersonCreateInput): Person createPeople(data: [PeopleCreateInput]): [Person] updatePerson(id: ID!, data: PersonUpdateInput): Person updatePeople(data: [PersonUpdateArgs]): [Person] - deletePerson(id: ID!): Person - deletePeople(ids: [ID!]): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] } type Query { diff --git a/examples/document-field/schema.graphql b/examples/document-field/schema.graphql index f59e850e4c3..0ad49bbde1a 100644 --- a/examples/document-field/schema.graphql +++ b/examples/document-field/schema.graphql @@ -208,14 +208,14 @@ type Mutation { createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] createAuthor(data: AuthorCreateInput): Author createAuthors(data: [AuthorsCreateInput]): [Author] updateAuthor(id: ID!, data: AuthorUpdateInput): Author updateAuthors(data: [AuthorUpdateArgs]): [Author] - deleteAuthor(id: ID!): Author - deleteAuthors(ids: [ID!]): [Author] + deleteAuthor(where: AuthorWhereUniqueInput!): Author + deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] } type Query { diff --git a/examples/extend-graphql-schema/schema.graphql b/examples/extend-graphql-schema/schema.graphql index ac8ce899eb7..bfba3284e41 100644 --- a/examples/extend-graphql-schema/schema.graphql +++ b/examples/extend-graphql-schema/schema.graphql @@ -193,14 +193,14 @@ type Mutation { createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] createAuthor(data: AuthorCreateInput): Author createAuthors(data: [AuthorsCreateInput]): [Author] updateAuthor(id: ID!, data: AuthorUpdateInput): Author updateAuthors(data: [AuthorUpdateArgs]): [Author] - deleteAuthor(id: ID!): Author - deleteAuthors(ids: [ID!]): [Author] + deleteAuthor(where: AuthorWhereUniqueInput!): Author + deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] """ Publish a post diff --git a/examples/json/schema.graphql b/examples/json/schema.graphql index 414c056db57..9aa15bc7ad4 100644 --- a/examples/json/schema.graphql +++ b/examples/json/schema.graphql @@ -156,14 +156,14 @@ type Mutation { createPackages(data: [PackagesCreateInput]): [Package] updatePackage(id: ID!, data: PackageUpdateInput): Package updatePackages(data: [PackageUpdateArgs]): [Package] - deletePackage(id: ID!): Package - deletePackages(ids: [ID!]): [Package] + deletePackage(where: PackageWhereUniqueInput!): Package + deletePackages(where: [PackageWhereUniqueInput!]!): [Package] createPerson(data: PersonCreateInput): Person createPeople(data: [PeopleCreateInput]): [Person] updatePerson(id: ID!, data: PersonUpdateInput): Person updatePeople(data: [PersonUpdateArgs]): [Person] - deletePerson(id: ID!): Person - deletePeople(ids: [ID!]): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] } type Query { diff --git a/examples/task-manager/schema.graphql b/examples/task-manager/schema.graphql index 55380b7c1d2..30beff9bc69 100644 --- a/examples/task-manager/schema.graphql +++ b/examples/task-manager/schema.graphql @@ -179,14 +179,14 @@ type Mutation { createTasks(data: [TasksCreateInput]): [Task] updateTask(id: ID!, data: TaskUpdateInput): Task updateTasks(data: [TaskUpdateArgs]): [Task] - deleteTask(id: ID!): Task - deleteTasks(ids: [ID!]): [Task] + deleteTask(where: TaskWhereUniqueInput!): Task + deleteTasks(where: [TaskWhereUniqueInput!]!): [Task] createPerson(data: PersonCreateInput): Person createPeople(data: [PeopleCreateInput]): [Person] updatePerson(id: ID!, data: PersonUpdateInput): Person updatePeople(data: [PersonUpdateArgs]): [Person] - deletePerson(id: ID!): Person - deletePeople(ids: [ID!]): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] } type Query { diff --git a/examples/testing/schema.graphql b/examples/testing/schema.graphql index 488720aca4f..02d9950b51c 100644 --- a/examples/testing/schema.graphql +++ b/examples/testing/schema.graphql @@ -198,14 +198,14 @@ type Mutation { createTasks(data: [TasksCreateInput]): [Task] updateTask(id: ID!, data: TaskUpdateInput): Task updateTasks(data: [TaskUpdateArgs]): [Task] - deleteTask(id: ID!): Task - deleteTasks(ids: [ID!]): [Task] + deleteTask(where: TaskWhereUniqueInput!): Task + deleteTasks(where: [TaskWhereUniqueInput!]!): [Task] createPerson(data: PersonCreateInput): Person createPeople(data: [PeopleCreateInput]): [Person] updatePerson(id: ID!, data: PersonUpdateInput): Person updatePeople(data: [PersonUpdateArgs]): [Person] - deletePerson(id: ID!): Person - deletePeople(ids: [ID!]): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] authenticatePersonWithPassword( email: String! password: String! diff --git a/examples/virtual-field/schema.graphql b/examples/virtual-field/schema.graphql index 265e49a5433..e3a8d3b511c 100644 --- a/examples/virtual-field/schema.graphql +++ b/examples/virtual-field/schema.graphql @@ -204,14 +204,14 @@ type Mutation { createPosts(data: [PostsCreateInput]): [Post] updatePost(id: ID!, data: PostUpdateInput): Post updatePosts(data: [PostUpdateArgs]): [Post] - deletePost(id: ID!): Post - deletePosts(ids: [ID!]): [Post] + deletePost(where: PostWhereUniqueInput!): Post + deletePosts(where: [PostWhereUniqueInput!]!): [Post] createAuthor(data: AuthorCreateInput): Author createAuthors(data: [AuthorsCreateInput]): [Author] updateAuthor(id: ID!, data: AuthorUpdateInput): Author updateAuthors(data: [AuthorUpdateArgs]): [Author] - deleteAuthor(id: ID!): Author - deleteAuthors(ids: [ID!]): [Author] + deleteAuthor(where: AuthorWhereUniqueInput!): Author + deleteAuthors(where: [AuthorWhereUniqueInput!]!): [Author] } type Query { diff --git a/examples/with-auth/schema.graphql b/examples/with-auth/schema.graphql index 488720aca4f..02d9950b51c 100644 --- a/examples/with-auth/schema.graphql +++ b/examples/with-auth/schema.graphql @@ -198,14 +198,14 @@ type Mutation { createTasks(data: [TasksCreateInput]): [Task] updateTask(id: ID!, data: TaskUpdateInput): Task updateTasks(data: [TaskUpdateArgs]): [Task] - deleteTask(id: ID!): Task - deleteTasks(ids: [ID!]): [Task] + deleteTask(where: TaskWhereUniqueInput!): Task + deleteTasks(where: [TaskWhereUniqueInput!]!): [Task] createPerson(data: PersonCreateInput): Person createPeople(data: [PeopleCreateInput]): [Person] updatePerson(id: ID!, data: PersonUpdateInput): Person updatePeople(data: [PersonUpdateArgs]): [Person] - deletePerson(id: ID!): Person - deletePeople(ids: [ID!]): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] authenticatePersonWithPassword( email: String! password: String! diff --git a/packages/keystone/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/index.tsx b/packages/keystone/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/index.tsx index 3e8ad8caef1..ad78a20b81c 100644 --- a/packages/keystone/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/index.tsx +++ b/packages/keystone/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/index.tsx @@ -225,7 +225,7 @@ function DeleteButton({ const toasts = useToasts(); const [deleteItem, { loading }] = useMutation( gql`mutation ($id: ID!) { - ${list.gqlNames.deleteMutationName}(id: $id) { + ${list.gqlNames.deleteMutationName}(where: { id: $id }) { id } }`, diff --git a/packages/keystone/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/index.tsx b/packages/keystone/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/index.tsx index 177dff1c384..e3b977c8737 100644 --- a/packages/keystone/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/index.tsx +++ b/packages/keystone/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/index.tsx @@ -436,8 +436,8 @@ function DeleteManyButton({ useMemo( () => gql` - mutation($ids: [ID!]!) { - ${list.gqlNames.deleteManyMutationName}(ids: $ids) { + mutation($where: [${list.gqlNames.whereUniqueInputName}!]!) { + ${list.gqlNames.deleteManyMutationName}(where: $where) { id } } @@ -468,7 +468,7 @@ function DeleteManyButton({ label: 'Delete', action: async () => { await deleteItems({ - variables: { ids: [...selectedItems] }, + variables: { where: [...selectedItems].map(id => ({ id })) }, }).catch(err => { toasts.addToast({ title: 'Failed to delete items', diff --git a/packages/keystone/src/lib/core/mutations/index.ts b/packages/keystone/src/lib/core/mutations/index.ts index 4c9229393de..c88d92d22f4 100644 --- a/packages/keystone/src/lib/core/mutations/index.ts +++ b/packages/keystone/src/lib/core/mutations/index.ts @@ -88,23 +88,22 @@ export function getMutationsForList(list: InitialisedList, provider: DatabasePro const deleteOne = schema.field({ type: list.types.output, - args: { id: schema.arg({ type: schema.nonNull(schema.ID) }) }, - resolve(rootVal, { id }, context) { - return deletes.deleteOne({ id }, list, context); + args: { where: schema.arg({ type: schema.nonNull(list.types.uniqueWhere) }) }, + resolve(rootVal, { where }, context) { + return deletes.deleteOne(where, list, context); }, }); const deleteMany = schema.field({ type: schema.list(list.types.output), - args: { ids: schema.arg({ type: schema.list(schema.nonNull(schema.ID)) }) }, - resolve(rootVal, { ids }, context) { + args: { + where: schema.arg({ + type: schema.nonNull(schema.list(schema.nonNull(list.types.uniqueWhere))), + }), + }, + resolve(rootVal, { where }, context) { return promisesButSettledWhenAllSettledAndInOrder( - deletes.deleteMany( - (ids || []).map(id => ({ id })), - list, - context, - provider - ) + deletes.deleteMany(where, list, context, provider) ); }, }); diff --git a/packages/keystone/src/scripts/tests/fixtures/basic-project/schema.graphql b/packages/keystone/src/scripts/tests/fixtures/basic-project/schema.graphql index 52fcac3e65e..9b0505c4968 100644 --- a/packages/keystone/src/scripts/tests/fixtures/basic-project/schema.graphql +++ b/packages/keystone/src/scripts/tests/fixtures/basic-project/schema.graphql @@ -66,8 +66,8 @@ type Mutation { createTodos(data: [TodosCreateInput]): [Todo] updateTodo(id: ID!, data: TodoUpdateInput): Todo updateTodos(data: [TodoUpdateArgs]): [Todo] - deleteTodo(id: ID!): Todo - deleteTodos(ids: [ID!]): [Todo] + deleteTodo(where: TodoWhereUniqueInput!): Todo + deleteTodos(where: [TodoWhereUniqueInput!]!): [Todo] } type Query { diff --git a/packages/types/src/context.ts b/packages/types/src/context.ts index 89c77a518d3..b19cd9cdf37 100644 --- a/packages/types/src/context.ts +++ b/packages/types/src/context.ts @@ -65,9 +65,15 @@ export type KeystoneListsAPI[]>; - deleteOne(args: { readonly id: string } & ResolveFields): Promise | null>; + deleteOne( + args: { + readonly where: KeystoneListsTypeInfo[Key]['inputs']['uniqueWhere']; + } & ResolveFields + ): Promise | null>; deleteMany( - args: { readonly ids: readonly string[] } & ResolveFields + args: { + readonly where: readonly KeystoneListsTypeInfo[Key]['inputs']['uniqueWhere'][]; + } & ResolveFields ): Promise[]>; }; }; @@ -113,9 +119,11 @@ export type KeystoneDbAPI; - deleteOne(args: { readonly id: string }): Promise; + deleteOne(args: { + readonly where: KeystoneListsTypeInfo[Key]['inputs']['uniqueWhere']; + }): Promise; deleteMany(args: { - readonly ids: readonly string[]; + readonly where: readonly KeystoneListsTypeInfo[Key]['inputs']['uniqueWhere'][]; }): Promise; }; }; diff --git a/tests/api-tests/access-control/authed.test.ts b/tests/api-tests/access-control/authed.test.ts index 8ef4eb30b57..d8ebf3f782d 100644 --- a/tests/api-tests/access-control/authed.test.ts +++ b/tests/api-tests/access-control/authed.test.ts @@ -99,7 +99,7 @@ describe('Authed', () => { const item = await context.lists[listKey].createOne({ data }); expect(item).not.toBe(null); expect(item.id).not.toBe(null); - await context.sudo().lists[listKey].deleteOne({ id: item.id }); + await context.sudo().lists[listKey].deleteOne({ where: { id: item.id } }); }); }); }); @@ -124,7 +124,7 @@ describe('Authed', () => { } else { expect(item[fieldName]).toBe(undefined); } - await context.sudo().lists[listKey].deleteOne({ id: item.id }); + await context.sudo().lists[listKey].deleteOne({ where: { id: item.id } }); }); }); }); @@ -143,7 +143,7 @@ describe('Authed', () => { }); expect(item).not.toBe(null); expect(item.id).not.toBe(null); - await context.sudo().lists[listKey].deleteOne({ id: item.id }); + await context.sudo().lists[listKey].deleteOne({ where: { id: item.id } }); }); }); }); @@ -395,7 +395,9 @@ describe('Authed', () => { test(`single allowed: ${JSON.stringify(access)}`, async () => { const { id } = await create({ name: 'Hello' }); - const deleted = await context.lists[nameFn[mode](access)].deleteOne({ id }); + const deleted = await context.lists[nameFn[mode](access)].deleteOne({ + where: { id }, + }); expect(deleted).not.toBe(null); expect(deleted!.id).toEqual(id); }); @@ -403,7 +405,7 @@ describe('Authed', () => { test(`single denies: ${JSON.stringify(access)}`, async () => { const { id: invalidId } = await create({ name: 'hi' }); const deleteMutationName = `delete${nameFn[mode](access)}`; - const query = `mutation { ${deleteMutationName}(id: "${invalidId}") { id } }`; + const query = `mutation { ${deleteMutationName}(where: { id: "${invalidId}" }) { id } }`; const { data, errors } = await context.graphql.raw({ query }); if (mode === 'imperative') { expect(errors).toBe(undefined); @@ -416,7 +418,7 @@ describe('Authed', () => { test(`single denies missing: ${JSON.stringify(access)}`, async () => { const deleteMutationName = `delete${nameFn[mode](access)}`; - const query = `mutation { ${deleteMutationName}(id: "${FAKE_ID[provider]}") { id } }`; + const query = `mutation { ${deleteMutationName}(where: { id: "${FAKE_ID[provider]}" }) { id } }`; const { data, errors } = await context.graphql.raw({ query }); expectNoAccess(data, errors, deleteMutationName); }); @@ -425,7 +427,7 @@ describe('Authed', () => { const { id: validId1 } = await create({ name: 'Hello' }); const { id: validId2 } = await create({ name: 'Hello' }); const multiDeleteMutationName = `delete${nameFn[mode](access)}s`; - const query = `mutation { ${multiDeleteMutationName}(ids: ["${validId1}", "${validId2}"]) { id } }`; + const query = `mutation { ${multiDeleteMutationName}(where: [{ id: "${validId1}" }, { id: "${validId2}" }]) { id } }`; const { data, errors } = await context.graphql.raw({ query }); expectNamedArray(data, errors, multiDeleteMutationName, [validId1, validId2]); }); @@ -434,7 +436,7 @@ describe('Authed', () => { const { id: validId1 } = await create({ name: 'hi' }); const { id: validId2 } = await create({ name: 'hi' }); const multiDeleteMutationName = `delete${nameFn[mode](access)}s`; - const query = `mutation { ${multiDeleteMutationName}(ids: ["${validId1}", "${validId2}"]) { id } }`; + const query = `mutation { ${multiDeleteMutationName}(where: [{ id: "${validId1}" }, { id: "${validId2}" }]) { id } }`; const { data, errors } = await context.graphql.raw({ query }); if (mode === 'imperative') { expectNamedArray(data, errors, multiDeleteMutationName, [validId1, validId2]); @@ -451,7 +453,7 @@ describe('Authed', () => { const { id: validId1 } = await create({ name: 'Hello' }); const { id: invalidId } = await create({ name: 'hi' }); const multiDeleteMutationName = `delete${nameFn[mode](access)}s`; - const query = `mutation { ${multiDeleteMutationName}(ids: ["${validId1}", "${invalidId}"]) { id } }`; + const query = `mutation { ${multiDeleteMutationName}(where: [{ id: "${validId1}" }, { id: "${invalidId}" }]) { id } }`; const { data, errors } = await context.graphql.raw({ query }); if (mode === 'imperative') { expectNamedArray(data, errors, multiDeleteMutationName, [validId1, invalidId]); @@ -463,7 +465,7 @@ describe('Authed', () => { test(`multi denies missing: ${JSON.stringify(access)}`, async () => { const multiDeleteMutationName = `delete${nameFn[mode](access)}s`; - const query = `mutation { ${multiDeleteMutationName}(ids: ["${FAKE_ID[provider]}", "${FAKE_ID_2[provider]}"]) { id } }`; + const query = `mutation { ${multiDeleteMutationName}(where: [{ id: "${FAKE_ID[provider]}" }, { id: "${FAKE_ID_2[provider]}" }]) { id } }`; const { data, errors } = await context.graphql.raw({ query }); expectAccessDenied(errors, [ { path: [multiDeleteMutationName, 0] }, diff --git a/tests/api-tests/access-control/mutations-list-declarative.test.ts b/tests/api-tests/access-control/mutations-list-declarative.test.ts index d191a1a54fd..7f7c43ed52e 100644 --- a/tests/api-tests/access-control/mutations-list-declarative.test.ts +++ b/tests/api-tests/access-control/mutations-list-declarative.test.ts @@ -55,11 +55,11 @@ describe('Access control - Imperative => declarative', () => { // Valid names should pass const user1 = await context.lists.User.createOne({ data: { name: 'good' } }); const user2 = await context.lists.User.createOne({ data: { name: 'no delete' } }); - await context.lists.User.deleteOne({ id: user1.id }); + await context.lists.User.deleteOne({ where: { id: user1.id } }); // Invalid name const { data, errors } = await context.graphql.raw({ - query: `mutation ($id: ID!) { deleteUser(id: $id) { id } }`, + query: `mutation ($id: ID!) { deleteUser(where: { id: $id }) { id } }`, variables: { id: user2.id }, }); @@ -155,10 +155,14 @@ describe('Access control - Imperative => declarative', () => { // Mix of good and bad names const { data, errors } = await context.graphql.raw({ - query: `mutation ($ids: [ID!]) { deleteUsers(ids: $ids) { id name } }`, - variables: { ids: [users[0].id, users[1].id, users[2].id, users[3].id] }, + query: `mutation ($where: [UserWhereUniqueInput!]!) { deleteUsers(where: $where) { id name } }`, + variables: { + where: [users[0].id, users[1].id, users[2].id, users[3].id].map(id => ({ id })), + }, }); + expectAccessDenied(errors, [{ path: ['deleteUsers', 1] }, { path: ['deleteUsers', 3] }]); + // Valid users are returned, invalid come back as null // The invalid deletes should have errors which point to the nulls in their path expect(data).toEqual({ @@ -169,7 +173,6 @@ describe('Access control - Imperative => declarative', () => { null, ], }); - expectAccessDenied(errors, [{ path: ['deleteUsers', 1] }, { path: ['deleteUsers', 3] }]); // Three users should still exist in the database const _users = await context.lists.User.findMany({ diff --git a/tests/api-tests/access-control/mutations-list-static.test.ts b/tests/api-tests/access-control/mutations-list-static.test.ts index c6dd438bfbe..3ce9600cacc 100644 --- a/tests/api-tests/access-control/mutations-list-static.test.ts +++ b/tests/api-tests/access-control/mutations-list-static.test.ts @@ -85,11 +85,11 @@ describe('Access control - Imperative => static', () => { // Valid names should pass const user1 = await context.lists.User.createOne({ data: { name: 'good' } }); const user2 = await context.lists.User.createOne({ data: { name: 'no delete' } }); - await context.lists.User.deleteOne({ id: user1.id }); + await context.lists.User.deleteOne({ where: { id: user1.id } }); // Invalid name const { data, errors } = await context.graphql.raw({ - query: `mutation ($id: ID!) { deleteUser(id: $id) { id } }`, + query: `mutation ($id: ID!) { deleteUser(where: { id: $id }) { id } }`, variables: { id: user2.id }, }); @@ -217,8 +217,10 @@ describe('Access control - Imperative => static', () => { // Mix of good and bad names const { data, errors } = await context.graphql.raw({ - query: `mutation ($ids: [ID!]) { deleteUsers(ids: $ids) { id name } }`, - variables: { ids: [users[0].id, users[1].id, users[2].id, users[3].id] }, + query: `mutation ($where: [UserWhereUniqueInput!]!) { deleteUsers(where: $where) { id name } }`, + variables: { + where: [users[0].id, users[1].id, users[2].id, users[3].id].map(id => ({ id })), + }, }); // Valid users are returned, invalid come back as null diff --git a/tests/api-tests/access-control/not-authed.test.ts b/tests/api-tests/access-control/not-authed.test.ts index b8dbe1c8898..752b0a93cf6 100644 --- a/tests/api-tests/access-control/not-authed.test.ts +++ b/tests/api-tests/access-control/not-authed.test.ts @@ -362,14 +362,14 @@ describe(`Not authed`, () => { .forEach(access => { test(`single denied: ${JSON.stringify(access)}`, async () => { const deleteMutationName = `delete${nameFn[mode](access)}`; - const query = `mutation { ${deleteMutationName}(id: "${FAKE_ID[provider]}") { id } }`; + const query = `mutation { ${deleteMutationName}(where: {id: "${FAKE_ID[provider]}" }) { id } }`; const { data, errors } = await context.graphql.raw({ query }); expectNoAccess(data, errors, deleteMutationName); }); test(`multi denied: ${JSON.stringify(access)}`, async () => { const multiDeleteMutationName = `delete${nameFn[mode](access)}s`; - const query = `mutation { ${multiDeleteMutationName}(ids: ["${FAKE_ID[provider]}"]) { id } }`; + const query = `mutation { ${multiDeleteMutationName}(where: [{ id: "${FAKE_ID[provider]}" }]) { id } }`; const { data, errors } = await context.graphql.raw({ query }); expect(data).toEqual({ [multiDeleteMutationName]: [null] }); diff --git a/tests/api-tests/fields/crud.test.ts b/tests/api-tests/fields/crud.test.ts index 3805287ba43..2d492c1cc89 100644 --- a/tests/api-tests/fields/crud.test.ts +++ b/tests/api-tests/fields/crud.test.ts @@ -101,7 +101,13 @@ testModules ? `id name ${readFieldName || fieldName} { ${subfieldName} }` : `id name ${readFieldName || fieldName}`; - const withHelpers = (wrappedFn: (args: any) => void | Promise) => { + const withHelpers = ( + wrappedFn: (args: { + context: KeystoneContext; + listKey: string; + items: readonly Record[]; + }) => void | Promise + ) => { return async ({ context, listKey }: { context: KeystoneContext; listKey: string }) => { const items = await context.lists[listKey].findMany({ orderBy: { name: 'asc' }, @@ -213,7 +219,7 @@ testModules keystoneTestWrapper( withHelpers(async ({ context, items, listKey }) => { const data = await context.lists[listKey].deleteOne({ - id: items[0].id, + where: { id: items[0].id }, query, }); expect(data).not.toBe(null); diff --git a/tests/api-tests/fields/types/document.test.ts b/tests/api-tests/fields/types/document.test.ts index 82f68d69e53..c3df3699ba4 100644 --- a/tests/api-tests/fields/types/document.test.ts +++ b/tests/api-tests/fields/types/document.test.ts @@ -215,7 +215,7 @@ describe('Document field type', () => { 'hydrateRelationships: true - dangling reference', runner(async ({ context }) => { const { alice, bob, charlie, post, content } = await initData({ context }); - await context.lists.Author.deleteOne({ id: bob.id }); + await context.lists.Author.deleteOne({ where: { id: bob.id } }); const _post = await context.lists.Post.findOne({ where: { id: post.id }, query: 'content { document(hydrateRelationships: true) }', diff --git a/tests/api-tests/hooks/validation.test.ts b/tests/api-tests/hooks/validation.test.ts index 730b94cca99..23fa581706f 100644 --- a/tests/api-tests/hooks/validation.test.ts +++ b/tests/api-tests/hooks/validation.test.ts @@ -77,11 +77,11 @@ describe('List Hooks: #validateInput()', () => { // Valid names should pass const user1 = await context.lists.User.createOne({ data: { name: 'good' } }); const user2 = await context.lists.User.createOne({ data: { name: 'no delete' } }); - await context.lists.User.deleteOne({ id: user1.id }); + await context.lists.User.deleteOne({ where: { id: user1.id } }); // Invalid name const { data, errors } = await context.graphql.raw({ - query: `mutation ($id: ID!) { deleteUser(id: $id) { id } }`, + query: `mutation ($id: ID!) { deleteUser(where: { id: $id }) { id } }`, variables: { id: user2.id }, }); @@ -206,8 +206,10 @@ describe('List Hooks: #validateInput()', () => { // Mix of good and bad names const { data, errors } = await context.graphql.raw({ - query: `mutation ($ids: [ID!]) { deleteUsers(ids: $ids) { id name } }`, - variables: { ids: [users[0].id, users[1].id, users[2].id, users[3].id] }, + query: `mutation ($where: [UserWhereUniqueInput!]!) { deleteUsers(where: $where) { id name } }`, + variables: { + where: [users[0].id, users[1].id, users[2].id, users[3].id].map(id => ({ id })), + }, }); // Valid users are returned, invalid come back as null diff --git a/tests/api-tests/queries/cache-hints.test.ts b/tests/api-tests/queries/cache-hints.test.ts index fe0e12d54bb..c9fe7518e6c 100644 --- a/tests/api-tests/queries/cache-hints.test.ts +++ b/tests/api-tests/queries/cache-hints.test.ts @@ -303,7 +303,7 @@ describe('cache hints', () => { const { body } = await graphQLRequest({ query: ` mutation { - deletePost(id: "${posts[0].id}") { + deletePost(where: { id: "${posts[0].id}" }) { id } } diff --git a/tests/api-tests/relationships/crud-self-ref/many-to-many-one-sided.test.ts b/tests/api-tests/relationships/crud-self-ref/many-to-many-one-sided.test.ts index eb01e96b2d6..62956e1d6ba 100644 --- a/tests/api-tests/relationships/crud-self-ref/many-to-many-one-sided.test.ts +++ b/tests/api-tests/relationships/crud-self-ref/many-to-many-one-sided.test.ts @@ -324,7 +324,7 @@ describe(`Many-to-many relationships`, () => { const { user, friend } = await createUserAndFriend(context); // Run the query to disconnect the location from company - const _user = await context.lists.User.deleteOne({ id: user.id }); + const _user = await context.lists.User.deleteOne({ where: { id: user.id } }); expect(_user?.id).toBe(user.id); // Check the link has been broken diff --git a/tests/api-tests/relationships/crud-self-ref/many-to-many.test.ts b/tests/api-tests/relationships/crud-self-ref/many-to-many.test.ts index a8d854a71a7..8a77b6401b3 100644 --- a/tests/api-tests/relationships/crud-self-ref/many-to-many.test.ts +++ b/tests/api-tests/relationships/crud-self-ref/many-to-many.test.ts @@ -410,7 +410,7 @@ describe(`Many-to-many relationships`, () => { const { user, friend } = await createUserAndFriend(context); // Run the query to disconnect the location from company - const _user = await context.lists.User.deleteOne({ id: user.id }); + const _user = await context.lists.User.deleteOne({ where: { id: user.id } }); expect(_user?.id).toBe(user.id); // Check the link has been broken diff --git a/tests/api-tests/relationships/crud-self-ref/one-to-many-one-sided.test.ts b/tests/api-tests/relationships/crud-self-ref/one-to-many-one-sided.test.ts index 22378b6610e..9b18346a8f7 100644 --- a/tests/api-tests/relationships/crud-self-ref/one-to-many-one-sided.test.ts +++ b/tests/api-tests/relationships/crud-self-ref/one-to-many-one-sided.test.ts @@ -305,7 +305,7 @@ describe(`One-to-many relationships`, () => { const { friend, user } = await createUserAndFriend(context); // Run the query to disconnect the location from company - const _user = await context.lists.User.deleteOne({ id: user.id }); + const _user = await context.lists.User.deleteOne({ where: { id: user.id } }); expect(_user?.id).toBe(user.id); // Check the link has been broken @@ -323,7 +323,7 @@ describe(`One-to-many relationships`, () => { // Delete company {name} const id = users.find(company => company.name === name)?.id; - const _user = await context.lists.User.deleteOne({ id }); + const _user = await context.lists.User.deleteOne({ where: { id } }); expect(_user?.id).toBe(id); // Check all the companies look how we expect @@ -380,7 +380,7 @@ describe(`One-to-many relationships`, () => { // Delete friend {name} const id = users.find(user => user.name === name)?.id; - const _user = await context.lists.User.deleteOne({ id }); + const _user = await context.lists.User.deleteOne({ where: { id } }); expect(_user?.id).toBe(id); // Check all the companies look how we expect diff --git a/tests/api-tests/relationships/crud-self-ref/one-to-many.test.ts b/tests/api-tests/relationships/crud-self-ref/one-to-many.test.ts index 3ae5b55b0b6..57239b8b6ed 100644 --- a/tests/api-tests/relationships/crud-self-ref/one-to-many.test.ts +++ b/tests/api-tests/relationships/crud-self-ref/one-to-many.test.ts @@ -443,7 +443,7 @@ describe(`One-to-many relationships`, () => { const { user, friend } = await createUserAndFriend(context); // Run the query to disconnect the location from company - const _user = await context.lists.User.deleteOne({ id: user.id }); + const _user = await context.lists.User.deleteOne({ where: { id: user.id } }); expect(_user?.id).toBe(user.id); // Check the link has been broken diff --git a/tests/api-tests/relationships/crud-self-ref/one-to-one.test.ts b/tests/api-tests/relationships/crud-self-ref/one-to-one.test.ts index c5b189effb3..ac2b9d4da59 100644 --- a/tests/api-tests/relationships/crud-self-ref/one-to-one.test.ts +++ b/tests/api-tests/relationships/crud-self-ref/one-to-one.test.ts @@ -427,7 +427,7 @@ describe(`One-to-one relationships`, () => { const { user, friend } = await createUserAndFriend(context); // Run the query to disconnect the location from company - const _user = await context.lists.User.deleteOne({ id: user.id }); + const _user = await context.lists.User.deleteOne({ where: { id: user.id } }); expect(_user?.id).toBe(user.id); // Check the link has been broken diff --git a/tests/api-tests/relationships/crud/many-to-many-one-sided.test.ts b/tests/api-tests/relationships/crud/many-to-many-one-sided.test.ts index 0e745c77018..1439f2ba07f 100644 --- a/tests/api-tests/relationships/crud/many-to-many-one-sided.test.ts +++ b/tests/api-tests/relationships/crud/many-to-many-one-sided.test.ts @@ -399,7 +399,7 @@ describe(`Many-to-many relationships`, () => { const { location, company } = await createCompanyAndLocation(context); // Run the query to disconnect the location from company - const _company = await context.lists.Company.deleteOne({ id: company.id }); + const _company = await context.lists.Company.deleteOne({ where: { id: company.id } }); expect(_company?.id).toBe(company.id); // Check the link has been broken diff --git a/tests/api-tests/relationships/crud/many-to-many.test.ts b/tests/api-tests/relationships/crud/many-to-many.test.ts index dfeca71811e..23762204047 100644 --- a/tests/api-tests/relationships/crud/many-to-many.test.ts +++ b/tests/api-tests/relationships/crud/many-to-many.test.ts @@ -507,7 +507,7 @@ describe(`Many-to-many relationships`, () => { const { location, company } = await createCompanyAndLocation(context); // Run the query to disconnect the location from company - const _company = await context.lists.Company.deleteOne({ id: company.id }); + const _company = await context.lists.Company.deleteOne({ where: { id: company.id } }); expect(_company?.id).toBe(company.id); // Check the link has been broken diff --git a/tests/api-tests/relationships/crud/one-to-many-one-sided.test.ts b/tests/api-tests/relationships/crud/one-to-many-one-sided.test.ts index 1a46a7a70ba..d4485f8b213 100644 --- a/tests/api-tests/relationships/crud/one-to-many-one-sided.test.ts +++ b/tests/api-tests/relationships/crud/one-to-many-one-sided.test.ts @@ -340,7 +340,7 @@ describe(`One-to-many relationships`, () => { const { location, company } = await createCompanyAndLocation(context); // Run the query to disconnect the location from company - const _company = await context.lists.Company.deleteOne({ id: company.id }); + const _company = await context.lists.Company.deleteOne({ where: { id: company.id } }); expect(_company?.id).toBe(company.id); // Check the link has been broken @@ -358,7 +358,7 @@ describe(`One-to-many relationships`, () => { // Delete company {name} const id = companies.find(company => company.name === name)?.id; - const _company = await context.lists.Company.deleteOne({ id }); + const _company = await context.lists.Company.deleteOne({ where: { id } }); expect(_company?.id).toBe(id); // Check all the companies look how we expect @@ -413,7 +413,7 @@ describe(`One-to-many relationships`, () => { // Delete location {name} const id = locations.find(location => location.name === name)?.id; - const deleted = await context.lists.Location.deleteOne({ id }); + const deleted = await context.lists.Location.deleteOne({ where: { id } }); expect(deleted).not.toBe(null); expect(deleted!.id).toBe(id); diff --git a/tests/api-tests/relationships/crud/one-to-many.test.ts b/tests/api-tests/relationships/crud/one-to-many.test.ts index 434aa544188..2cd15ee43be 100644 --- a/tests/api-tests/relationships/crud/one-to-many.test.ts +++ b/tests/api-tests/relationships/crud/one-to-many.test.ts @@ -477,7 +477,7 @@ describe(`One-to-many relationships`, () => { const { location, company } = await createCompanyAndLocation(context); // Run the query to disconnect the location from company - const _company = await context.lists.Company.deleteOne({ id: company.id }); + const _company = await context.lists.Company.deleteOne({ where: { id: company.id } }); expect(_company?.id).toBe(company.id); // Check the link has been broken diff --git a/tests/api-tests/relationships/crud/one-to-one.test.ts b/tests/api-tests/relationships/crud/one-to-one.test.ts index b3b42239d03..b5ca174b3b5 100644 --- a/tests/api-tests/relationships/crud/one-to-one.test.ts +++ b/tests/api-tests/relationships/crud/one-to-one.test.ts @@ -922,7 +922,7 @@ describe(`One-to-one relationships`, () => { const { location, company } = await createCompanyAndLocation(context); // Run the query to disconnect the location from company - const _company = await context.lists.Company.deleteOne({ id: company.id }); + const _company = await context.lists.Company.deleteOne({ where: { id: company.id } }); expect(_company?.id).toBe(company.id); // Check the link has been broken @@ -939,7 +939,7 @@ describe(`One-to-one relationships`, () => { const { location, company } = await createLocationAndCompany(context); // Run the query to disconnect the location from company - const _location = await context.lists.Location.deleteOne({ id: location.id }); + const _location = await context.lists.Location.deleteOne({ where: { id: location.id } }); expect(_location?.id).toBe(location.id); // Check the link has been broken diff --git a/tests/api-tests/relationships/nested-mutations/two-way-backreference/to-many.test.ts b/tests/api-tests/relationships/nested-mutations/two-way-backreference/to-many.test.ts index aa4a0b9b164..5dd19d2855e 100644 --- a/tests/api-tests/relationships/nested-mutations/two-way-backreference/to-many.test.ts +++ b/tests/api-tests/relationships/nested-mutations/two-way-backreference/to-many.test.ts @@ -351,7 +351,7 @@ test( compareIds(teacher2.students, [student1, student2]); // Run the query to delete the student - await context.lists.Student.deleteOne({ id: student1.id }); + await context.lists.Student.deleteOne({ where: { id: student1.id } }); teacher1 = await getTeacher(context, teacher1.id); teacher2 = await getTeacher(context, teacher2.id); student1 = await getStudent(context, student1.id); diff --git a/tests/test-projects/basic/schema.graphql b/tests/test-projects/basic/schema.graphql index 55380b7c1d2..30beff9bc69 100644 --- a/tests/test-projects/basic/schema.graphql +++ b/tests/test-projects/basic/schema.graphql @@ -179,14 +179,14 @@ type Mutation { createTasks(data: [TasksCreateInput]): [Task] updateTask(id: ID!, data: TaskUpdateInput): Task updateTasks(data: [TaskUpdateArgs]): [Task] - deleteTask(id: ID!): Task - deleteTasks(ids: [ID!]): [Task] + deleteTask(where: TaskWhereUniqueInput!): Task + deleteTasks(where: [TaskWhereUniqueInput!]!): [Task] createPerson(data: PersonCreateInput): Person createPeople(data: [PeopleCreateInput]): [Person] updatePerson(id: ID!, data: PersonUpdateInput): Person updatePeople(data: [PersonUpdateArgs]): [Person] - deletePerson(id: ID!): Person - deletePeople(ids: [ID!]): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] } type Query {