We are currently working on a new version of the documentation.

Storage Options

Complete reference for configuring createStorage.

Required Options

bucket

Target bucket name for object operations.

const storage = createStorage({
  bucket: "my-bucket",
  // ...
});

adapter

S3 provider integration used for presigned URLs and object operations. See Adapters for a full list of supported adapters.

import { aws } from "vs3/adapters";

const storage = createStorage({
  bucket: "my-bucket",
  adapter: aws({
    region: "us-east-1",
    credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
    },
  }),
  // ...
});

Validation Options

maxFileSize

The maximum allowed file size in bytes. Files larger than this value will be rejected from uploads with a FILE_TOO_LARGE error. Value must be a positive number. Defaults to undefined (no restriction).

createStorage({
  // ...
  maxFileSize: 10 * 1024 * 1024, // 10MB
});

allowedFileTypes

Allowlist of MIME types and/or extensions. Accepts a string array of MIME types and/or extensions. Defaults to undefined (no restriction).

createStorage({
  // ...
  allowedFileTypes: ["image/png", "image/jpeg", ".pdf"],
});

contentValidators

Custom content validators for uploads. Validators are run sequentially after built-in validations (size, file type). If any validator fails, the upload is rejected with a CONTENT_VALIDATION_ERROR. Validators can be synchronous or asynchronous functions. Each validator receives the file info and parsed metadata, and must return a validation result.

Simple validator

const storage = createStorage({
  // ...
  contentValidators: [
    (ctx) => {
      if (ctx.fileInfo.name.includes("tmp")) {
        return { valid: false, reason: "Temporary files are not allowed." };
      }
      return { valid: true };
    },
  ];
})

Named validator

const storage = createStorage({
  // ...
  contentValidators: [
    {
      name: "quota-check",
      validate: async (ctx) => {
        const usage = await getUserUsage(ctx.metadata.userId);
        return usage < 1024 * 1024 * 1024
          ? { valid: true }
          : { valid: false, reason: "Quota exceeded." };
      },
    },
  ];
})
Information

Named validators provide better error messages when validation fails.

contentValidatorTimeoutMs

Timeout in milliseconds for each content validator. If a validator takes longer than this, the upload is rejected. Defaults to undefined (no timeout).

createStorage({
  // ...
  contentValidatorTimeoutMs: 5000, // 5 seconds
});

Metadata and Key Options

metadataSchema

Schema used to validate metadata at endpoint boundaries. Defaults to undefined (no validation). See Metadata Schemas for more information.

createStorage({
  // ...
  metadataSchema: z.object({
    userId: z.string(),
  }),
});

generateKey

Custom function to generate the object key for the uploaded file. Defaults to undefined (uses a default key generator). The function receives the file info and metadata, and must return a string or promise resolving to a string.

createStorage({
  // ...
  generateKey: (fileInfo, metadata) => {
    return `uploads/${metadata.userId}/${Date.now()}-${fileInfo.name}`,
  }
});
Information

This can be helpful when you want to sort different types of uploads into different directories.

API Surface Options

baseUrl

The base URL of the API. Defaults to http://localhost:3000.

createStorage({
  // ...
  baseUrl: "https://example.com",
});

apiPath

The api path where the API handler is mounted. Defaults to /api/storage.

createStorage({
  // ...
  apiPath: "/api/files",
});

Middleware Option

middlewares

Global middleware chain executed before endpoint logic. Defaults to [] (no middlewares applied). Middlewares are applied in the order they are provided. See Middleware Overview for more information.

middlewares: [
  createLoggingMiddleware({ logger: console.log }),
  createRateLimitMiddleware({
    maxRequests: 100,
    windowMs: 60_000,
    store: createInMemoryRateLimitStore(),
  }),
];

Hook Options

For more information on hooks, see Hooks. The storage instance supports the following hooks:

  • beforeUpload
  • afterUpload
  • beforeDownload
  • afterDownload