@s3 Directive
The @s3 directive resolves a field by executing an operation against an S3 or S3-compatible storage service (MinIO, Cloudflare R2, etc.). It requires a storage endpoint linked via @link(type: S3, src: "...").
Fields
| Field | Type | Default | Description |
|---|---|---|---|
bucket | String | Required | Target bucket name. Supports Mustache templates. |
operation | S3Operation | Required | The S3 operation to perform. See below. |
key | String | null | Object key. Supports Mustache templates. Required for presigned URLs and DELETE. |
prefix | String | null | Prefix filter for LIST operations. Supports Mustache templates. |
expiration | Int | 3600 | Presigned URL expiration time in seconds. |
contentType | String | null | Content-Type for PUT presigned URLs. Supports Mustache templates. |
linkId | String | null | The @link id of the S3 connection to use. Omit for the default. |
dedupe | Boolean | false | Deduplicate identical in-flight S3 calls. |
S3Operation
| Value | Description |
|---|---|
GET_PRESIGNED_URL | Generate a presigned URL for downloading. |
PUT_PRESIGNED_URL | Generate a presigned URL for uploading. |
LIST | List objects in a bucket (with optional prefix). |
DELETE | Delete an object from a bucket. |
Examples
Generating a download URL
type Query {
getFileUrl(key: String!): String! @s3(bucket: "my-bucket", operation: GET_PRESIGNED_URL, key: "{{.args.key}}")
}
Generating an upload URL
type Mutation {
uploadUrl(key: String!, contentType: String): String!
@s3(
bucket: "my-bucket"
operation: PUT_PRESIGNED_URL
key: "{{.args.key}}"
contentType: "{{.args.contentType}}"
expiration: 3600
)
}
Listing objects
Note: The
JSONscalar is not built-in to GraphQL. You must declarescalar JSONin your schema (or use@linkto import it) before using it as a return type.
type Query {
listFiles(prefix: String): JSON! @s3(bucket: "my-bucket", operation: LIST, prefix: "{{.args.prefix}}")
}
Deleting an object
type Mutation {
deleteFile(key: String!): Boolean! @s3(bucket: "my-bucket", operation: DELETE, key: "{{.args.key}}")
}
Using a specific S3 connection
When multiple @link(type: S3) entries are defined, use linkId to choose which one:
type Query {
getMinioFile(key: String!): String!
@s3(bucket: "local-bucket", operation: GET_PRESIGNED_URL, key: "{{.args.key}}", linkId: "minio")
}
Security
All dynamic values referenced by Mustache templates in bucket, key, prefix, and contentType are rendered at runtime from the GraphQL context. AWS credentials are resolved via the standard AWS credential chain (environment variables, shared config, IAM roles) and are never exposed in the GraphQL schema.