Skip to content

Commit

Permalink
Add directives @createMany, @updateMany and @upsertMany to muta…
Browse files Browse the repository at this point in the history
…te multiple models at once
  • Loading branch information
spawnia committed Jul 2, 2024
1 parent f84b5a2 commit 29b99f7
Show file tree
Hide file tree
Showing 26 changed files with 1,126 additions and 113 deletions.
12 changes: 4 additions & 8 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,8 @@ jobs:

strategy:
matrix:
php-version:
- "8.3"
laravel-version:
- "^10"
php-version: ["8.3"]
laravel-version: ["^11"]

services:
mysql:
Expand Down Expand Up @@ -208,10 +206,8 @@ jobs:

strategy:
matrix:
php-version:
- "8.3"
laravel-version:
- "^10"
php-version: ["8.3"]
laravel-version: ["^11"]

steps:
- uses: actions/checkout@v4
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ You can find and compare releases at the [GitHub release page](https://github.co

## Unreleased

## v6.39.0

### Added

- Add directives `@createMany`, `@updateMany` and `@upsertMany` to mutate multiple models at once https://github.com/nuwave/lighthouse/pull/2578

### Changed

- Split `MutationExecutorDirective` into `OneModelMutationDirective` and `ManyModelMutationDirective` https://github.com/nuwave/lighthouse/pull/2578

## v6.38.1

### Fixed
Expand Down
140 changes: 122 additions & 18 deletions docs/6/api-reference/directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,7 @@ Use it on a root mutation field that returns an instance of the Model.
```graphql
type Mutation {
createPost(title: String!): Post @create
createPost(title: String!): Post! @create
}
```
Expand All @@ -1028,7 +1028,7 @@ to spread out the nested values before applying it to the resolver.
```graphql
type Mutation {
createPost(input: CreatePostInput! @spread): Post @create
createPost(input: CreatePostInput! @spread): Post! @create
}
input CreatePostInput {
Expand All @@ -1041,12 +1041,46 @@ or is located in a non-default namespace, set it with the `model` argument.
```graphql
type Mutation {
createPost(title: String!): Post @create(model: "Foo\\Bar\\MyPost")
createPost(title: String!): Post! @create(model: "Foo\\Bar\\MyPost")
}
```
This directive can also be used as a [nested arg resolver](../concepts/arg-resolvers.md).
## @createMany
```graphql
"""
Create multiple new Eloquent models with the given arguments.
"""
directive @createMany(
"""
Specify the class name of the model to use.
This is only needed when the default model detection does not work.
"""
model: String
"""
Specify the name of the relation on the parent model.
This is only needed when using this directive as a nested arg
resolver and if the name of the relation is not the arg name.
"""
relation: String
) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
```
When used on a field, it must have exactly one argument where the type is a non-null list of input objects.
```graphql
type Mutation {
createPosts(inputs: [CreatePostInput!]!): [Post!]! @createMany
}
input CreatePostInput {
title: String!
}
```
## @delete
```graphql
Expand Down Expand Up @@ -1172,7 +1206,7 @@ type User {
}
type Mutation {
createUser(email: String!, foo: String @drop): User @create
createUser(email: String!, foo: String @drop): User! @create
}
```
Expand Down Expand Up @@ -1242,7 +1276,7 @@ If you pass only a class name, the method name defaults to `__invoke`.
```graphql
type Mutation {
createPost(title: String!): Post
createPost(title: String!): Post!
@field(resolver: "App\\GraphQL\\Mutations\\PostMutator@create")
}
```
Expand Down Expand Up @@ -1868,9 +1902,9 @@ automatically used for creating new models and cannot be manipulated.
```graphql
type Mutation {
createPost(title: String!, content: String!): Post
@create
createPost(title: String!, content: String!): Post!
@inject(context: "user.id", name: "user_id")
@create
}
```
Expand All @@ -1879,9 +1913,9 @@ set a nested argument.
```graphql
type Mutation {
createTask(input: CreateTaskInput!): Task
@create
createTask(input: CreateTaskInput!): Task!
@inject(context: "user.id", name: "input.user_id")
@create
}
```
Expand Down Expand Up @@ -2466,7 +2500,7 @@ This may be useful to logically group arg resolvers.
```graphql
type Mutation {
createUser(name: String, tasks: UserTasksOperations @nest): User @create
createUser(name: String, tasks: UserTasksOperations @nest): User! @create
}
input UserTasksOperations {
Expand Down Expand Up @@ -3444,7 +3478,7 @@ You may use [@spread](#spread) on field arguments or on input object fields:
```graphql
type Mutation {
updatePost(id: ID!, input: PostInput! @spread): Post @update
updatePost(id: ID!, input: PostInput! @spread): Post! @update
}
input PostInput {
Expand Down Expand Up @@ -3675,7 +3709,7 @@ final class Person
```graphql
"""
Update an Eloquent model with the input values of the field.
Update an Eloquent model with the given arguments.
"""
directive @update(
"""
Expand All @@ -3697,7 +3731,7 @@ Use it on a root mutation field that returns an instance of the Model.
```graphql
type Mutation {
updatePost(id: ID!, content: String): Post @update
updatePost(id: ID!, content: String): Post! @update
}
```
Expand All @@ -3706,7 +3740,7 @@ Client libraries such as Apollo base their caching mechanism on that assumption.
```graphql
type Mutation {
updatePost(id: ID! @rename(attribute: "post_id"), content: String): Post
updatePost(id: ID! @rename(attribute: "post_id"), content: String): Post!
@update
}
```
Expand All @@ -3716,12 +3750,47 @@ or is located in a non-default namespace, set it with the `model` argument.
```graphql
type Mutation {
updateAuthor(id: ID!, name: String): Author @update(model: "App\\User")
updateAuthor(id: ID!, name: String): Author! @update(model: "App\\User")
}
```
This directive can also be used as a [nested arg resolver](../concepts/arg-resolvers.md).
## @updateMany
```graphql
"""
Update multiple Eloquent models with the given arguments.
"""
directive @updateMany(
"""
Specify the class name of the model to use.
This is only needed when the default model detection does not work.
"""
model: String
"""
Specify the name of the relation on the parent model.
This is only needed when using this directive as a nested arg
resolver and if the name of the relation is not the arg name.
"""
relation: String
) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
```
When used on a field, it must have exactly one argument where the type is a non-null list of input objects.
```graphql
type Mutation {
updatePosts(inputs: [UpdatePostInput!]!): [Post!]! @updateMany
}
input UpdatePostInput {
id: ID!
title: String
}
```
## @upload
```graphql
Expand Down Expand Up @@ -3756,7 +3825,7 @@ For example, you want to pass in a user avatar, have that file uploaded and the
type Mutation {
createUser(
avatar: Upload @upload(disk: "public", path: "images/avatars", public: true)
): User @create
): User! @create
}
type User {
Expand All @@ -3768,7 +3837,7 @@ type User {
```graphql
"""
Create or update an Eloquent model with the input values of the field.
Create or update an Eloquent model with the given arguments.
"""
directive @upsert(
"""
Expand All @@ -3792,12 +3861,47 @@ In case no `id` is specified, an auto-generated fresh ID will be used instead.
```graphql
type Mutation {
upsertPost(post_id: ID!, content: String): Post @upsert
upsertPost(id: ID, content: String!): Post! @upsert
}
```
This directive can also be used as a [nested arg resolver](../concepts/arg-resolvers.md).
## @upsertMany
```graphql
"""
Create or update multiple Eloquent models with given arguments.
"""
directive @upsertMany(
"""
Specify the class name of the model to use.
This is only needed when the default model detection does not work.
"""
model: String
"""
Specify the name of the relation on the parent model.
This is only needed when using this directive as a nested arg
resolver and if the name of the relation is not the arg name.
"""
relation: String
) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
```
When used on a field, it must have exactly one argument where the type is a non-null list of input objects.
```graphql
type Mutation {
upsertPosts(inputs: [UpsertPostInput!]!): [Post!]! @upsertMany
}
input UpsertPostInput {
id: ID
title: String!
}
```
## @validator
```graphql
Expand Down
11 changes: 8 additions & 3 deletions docs/6/eloquent/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,15 @@ The newly created user is returned as a result:
}
```

To create multiple models at once, use the [@createMany](../api-reference/directives.md#createMany) directive.

## Update

You can update a model with the [@update](../api-reference/directives.md#update) directive.

```graphql
type Mutation {
updateUser(id: ID!, name: String): User @update
updateUser(id: ID!, name: String): User! @update
}
```

Expand Down Expand Up @@ -245,19 +247,20 @@ The update may fail to find the model you provided and return `null`:
}
```

To update multiple models at once, use the [@updateMany](../api-reference/directives.md#updatemany) directive.

## Upsert

Use the [@upsert](../api-reference/directives.md#upsert) directive to update a model with
a given `id` or create it if it does not exist.

```graphql
type Mutation {
upsertUser(id: ID!, name: String!, email: String): User @upsert
upsertUser(id: ID, name: String!, email: String): User! @upsert
}
```

Since upsert can create or update your data, your input should mark the minimum required fields as non-nullable.
The `id` must always be required.

```graphql
mutation {
Expand All @@ -281,6 +284,8 @@ mutation {
}
```

To upsert multiple models at once, use the [@upsertMany](../api-reference/directives.md#upsertmany) directive.

## Delete

Deleting models is a breeze using the [@delete](../api-reference/directives.md#delete) directive. Dangerously easy.
Expand Down
Loading

0 comments on commit 29b99f7

Please sign in to comment.