### Install and Run Example
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/examples/example-graphql-upload-nextjs/README.md
Clone the repository, navigate to the example directory, install dependencies, and start the development server.
```bash
git clone https://github.com/lafittemehdy/graphql-upload-nextjs.git
cd graphql-upload-nextjs/examples/example-graphql-upload-nextjs
npm install
npm run dev
```
--------------------------------
### Migrate from graphql-upload to graphql-upload-nextjs
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
This example shows the difference in setup between the older graphql-upload with Express and the new graphql-upload-nextjs for Next.js App Router.
```typescript
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs'
app.use(graphqlUploadExpress())
```
```typescript
import { GraphQLUpload, uploadProcess } from 'graphql-upload-nextjs'
// In your route handler:
if (request.headers.get("content-type")?.includes("multipart/form-data")) {
return await uploadProcess(request, context, server);
}
```
--------------------------------
### Install and Build Project
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Clone the repository, install dependencies, build the project, and run tests.
```bash
git clone https://github.com/lafittemehdy/graphql-upload-nextjs.git
cd graphql-upload-nextjs
npm install
npm run build
npm test
```
--------------------------------
### Install graphql-upload-nextjs
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Use npm to install the graphql-upload-nextjs package.
```bash
npm install graphql-upload-nextjs
```
--------------------------------
### GraphQL Upload Configuration Options
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Demonstrates how to configure upload limits for file type, number of files, and maximum file size. These options are passed to the `uploadProcess` function to enforce constraints on uploads, returning a 413 error if exceeded.
```typescript
await uploadProcess(request, context, server, {
allowedTypes: ["image/jpeg", "image/png", "text/plain"],
maxFiles: 10,
maxFileSize: 10 * 1024 * 1024, // 10MB
});
```
--------------------------------
### Configuration Options for `uploadProcess`
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Provides configuration options to customize the file upload process, including allowed file types, maximum number of files, and maximum file size.
```APIDOC
## Configuration Options for `uploadProcess`
### Description
Provides configuration options to customize the file upload process, including allowed file types, maximum number of files, and maximum file size.
### Options
- **`allowedTypes`** (`string[]`, optional)
- Description: Restricts MIME types. Verified via magic bytes.
- Example: `["image/jpeg", "image/png", "text/plain"]`
- **`maxFiles`** (`number`, optional)
- Description: Maximum number of files per request. Returns 413 if exceeded.
- Example: `10`
- **`maxFileSize`** (`number`, optional)
- Description: Maximum file size in bytes. Returns 413 if exceeded.
- Example: `10485760` (10MB)
```
--------------------------------
### Client-Side File Upload Mutation with Apollo Client
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Shows how to use Apollo Client's `useMutation` hook to handle file uploads from an HTML file input element. The file is automatically formatted for the GraphQL mutation as per the specification.
```typescript
import { gql, useMutation } from '@apollo/client';
const UPLOAD = gql`
mutation UploadFile($file: Upload!) {
uploadFile(file: $file) { filename mimetype fileSize }
}
`;
function Uploader() {
const [upload] = useMutation(UPLOAD);
return {
const file = e.target.files?.[0];
if (file) upload({ variables: { file } });
}} />;
}
```
--------------------------------
### Core Exports
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
These are the main exports provided by the library for integrating GraphQL file uploads.
```APIDOC
## GraphQLUpload
### Description
The `GraphQLUpload` scalar type is used in your GraphQL schema to define file upload fields.
### Type
`GraphQLScalarType`
```
```APIDOC
## uploadProcess
### Description
This function processes incoming multipart requests that contain file uploads, preparing them for GraphQL resolvers.
### Type
`function`
```
```APIDOC
## Upload
### Description
The `Upload` class is used internally to hold a promise that resolves with the details of a file upload.
### Type
`class`
```
--------------------------------
### Utility Exports
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Helper functions provided by the library for common tasks related to file uploads and data manipulation.
```APIDOC
## bufferToStream
### Description
Converts a Node.js Buffer into a Node.js readable stream.
### Parameters
- **`buffer`** (`Buffer`) - The buffer to convert.
### Returns
`ReadableStream`
```
```APIDOC
## parseOperationsJSON
### Description
Parses the `operations` field from a multipart request. This field can be a single JSON object or an array for batching.
### Parameters
- **`input`** (`string`) - The JSON string from the `operations` field.
### Returns
`object | object[]`
```
```APIDOC
## sanitizeAndValidateJSON
### Description
Parses a JSON string and validates that it is a non-null, non-array object.
### Parameters
- **`input`** (`string`) - The JSON string to parse and validate.
### Returns
`object`
```
```APIDOC
## setValueAtPath
### Description
Sets a value at a specified dot-notation path within a nested object.
### Parameters
- **`obj`** (`object`) - The object to modify.
- **`path`** (`string`) - The dot-notation path to the property.
- **`value`** (`any`) - The value to set.
### Returns
`void`
```
```APIDOC
## streamToBuffer
### Description
Collects the contents of a readable stream into a Node.js Buffer.
### Parameters
- **`stream`** (`ReadableStream`) - The readable stream to collect.
### Returns
`Promise`
```
```APIDOC
## validateMap
### Description
Validates the `map` field from a multipart request, ensuring each entry is an array of string paths.
### Parameters
- **`map`** (`object`) - The map object to validate.
### Returns
`string | null` - Returns an error message string if validation fails, otherwise `null`.
```
--------------------------------
### GraphQL Schema and Resolvers for File Uploads
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Defines the GraphQL schema for file uploads and implements the corresponding resolvers for handling single and multiple file uploads. Ensure filenames are sanitized to prevent path traversal attacks. Avoid writing uploaded files to publicly accessible directories in production.
```typescript
import path from 'node:path'
import { createWriteStream } from 'node:fs'
import { pipeline } from 'node:stream'
import { gql } from '@apollo/client' // Optional: syntax highlighting only.
import { ApolloServer } from '@apollo/server'
import { startServerAndCreateNextHandler } from '@as-integrations/next'
import { type File, GraphQLUpload, uploadProcess } from 'graphql-upload-nextjs'
import type { NextRequest } from 'next/server.js'
const typeDefs = gql`
scalar Upload
type File {
encoding: String!
filename: String!
fileSize: Int!
mimetype: String!
uri: String!
}
type Query {
default: Boolean!
}
type Mutation {
uploadFile(file: Upload!): File!
uploadFiles(files: [Upload!]!): [File!]!
}
`
interface FileResponse {
encoding: string;
filename: string;
fileSize: number;
mimetype: string;
uri: string;
}
const resolvers = {
Mutation: {
uploadFile: async (
_parent: undefined,
{ file }: { file: Promise },
): Promise => {
const { createReadStream, encoding, filename, fileSize, mimetype } = await file;
const safeName = path.basename(filename);
return new Promise((resolve, reject) => {
pipeline(
createReadStream(),
createWriteStream(`./uploads/${safeName}`),
(error) => {
if (error) reject(new Error("Error during file upload."));
else resolve({ encoding, filename: safeName, fileSize, mimetype, uri: `/${safeName}` });
},
);
});
},
uploadFiles: async (
_parent: undefined,
{ files }: { files: Promise[] },
): Promise => {
const resolvedFiles = await Promise.all(files);
return Promise.all(resolvedFiles.map(async ({ createReadStream, encoding, filename, fileSize, mimetype }) => {
const safeName = path.basename(filename);
return new Promise((resolve, reject) => {
pipeline(
createReadStream(),
createWriteStream(`./uploads/${safeName}`),
(error) => {
if (error) reject(new Error(`Error during upload of ${safeName}.`));
else resolve({ encoding, filename: safeName, fileSize, mimetype, uri: `/${safeName}` });
},
);
});
}));
},
},
Query: { default: async () => true },
Upload: GraphQLUpload,
}
```
--------------------------------
### File Object Properties
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Details about the structure of the file object passed to GraphQL resolvers after processing.
```APIDOC
## File Object
### Description
The resolved file object passed to resolvers contains the following properties:
- **`createReadStream`** (`() => ReadableStream`) - Creates a Node.js readable stream of the file contents. This stream is replayable.
- **`encoding`** (`string`) - The transfer encoding of the file. Typically `'binary'` when using the FormData API.
- **`filename`** (`string`) - The original name of the file as provided by the client.
- **`fileSize`** (`number`) - The size of the file in bytes.
- **`mimetype`** (`string`) - The MIME type of the file, verified using magic bytes.
```
--------------------------------
### GraphQL Mutation for Multiple File Upload
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/examples/example-graphql-upload-nextjs/README.md
Define a GraphQL mutation to upload multiple files. The input is an array of the `Upload` scalar type.
```graphql
mutation UploadFiles($files: [Upload!]!) {
uploadFiles(files: $files) {
encoding
filename
fileSize
mimetype
uri
}
}
```
--------------------------------
### Route Handler for GraphQL Uploads
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
The route handler integrates Apollo Server with Next.js, enabling it to process both standard GraphQL requests and multipart/form-data requests for file uploads.
```APIDOC
## Route Handler for GraphQL Uploads
### Description
The route handler integrates Apollo Server with Next.js, enabling it to process both standard GraphQL requests and multipart/form-data requests for file uploads.
### Methods
- GET
- POST
- OPTIONS
### Endpoint
`/api/graphql` (Assumed based on Next.js conventions)
### Request Handling
- If the `content-type` header includes `multipart/form-data`, the `uploadProcess` function is used to handle the file upload.
- Otherwise, the standard Apollo Server handler is used.
### Context
The request context includes `ip` and the original `req` object.
```
--------------------------------
### GraphQL Mutations for File Upload
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Defines the GraphQL mutations for uploading single and multiple files. The `uploadFile` mutation accepts a single `Upload` scalar and returns a `File` object. The `uploadFiles` mutation accepts an array of `Upload` scalars and returns an array of `File` objects.
```APIDOC
## GraphQL Mutations for File Upload
### Description
Defines the GraphQL mutations for uploading single and multiple files. The `uploadFile` mutation accepts a single `Upload` scalar and returns a `File` object. The `uploadFiles` mutation accepts an array of `Upload` scalars and returns an array of `File` objects.
### Mutation `uploadFile`
- **Description**: Uploads a single file.
- **Parameters**:
- `file` (Upload!) - Required - The file to upload.
- **Returns**: `File` - Information about the uploaded file.
### Mutation `uploadFiles`
- **Description**: Uploads multiple files.
- **Parameters**:
- `files` ([Upload!]!) - Required - An array of files to upload.
- **Returns**: `[File!]` - An array of information about the uploaded files.
```
--------------------------------
### Next.js Route Handler for GraphQL Uploads
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/README.md
Configures a Next.js route handler to manage incoming requests, distinguishing between standard GraphQL requests and multipart/form-data requests for file uploads. This handler integrates with Apollo Server and the graphql-upload-nextjs library.
```typescript
const server = new ApolloServer({ resolvers, typeDefs });
const handler = startServerAndCreateNextHandler(server, {
context: async (req: NextRequest) => ({
ip: req.headers.get("x-forwarded-for") || "",
req,
}),
});
const requestHandler = async (request: NextRequest) => {
if (request.headers.get("content-type")?.includes("multipart/form-data")) {
const context = { ip: request.headers.get("x-forwarded-for") || "", req: request };
return await uploadProcess(request, context, server);
}
return handler(request);
};
export const GET = requestHandler;
export const POST = requestHandler;
export const OPTIONS = requestHandler;
```
--------------------------------
### Multiple File Upload Mutation
Source: https://github.com/lafittemehdy/graphql-upload-nextjs/blob/main/examples/example-graphql-upload-nextjs/README.md
This GraphQL mutation allows for the upload of multiple files simultaneously. It returns details for each uploaded file.
```APIDOC
## Multiple File Upload
### Description
Allows for the upload of multiple files.
### Method
`mutation`
### GraphQL Operation
`UploadFiles`
### Parameters
#### Variable
- **files** ([Upload!]!) - Required - An array of files to upload.
### Response
#### Success Response
- **uploadFiles** (Array