dimah-s3v0.4.1

Setup

Install `@dimah-s3/server`, configure S3, and mount the route.

Install

npm i @dimah-s3/server @aws-sdk/client-s3

S3 client

.env
AWS_REGION="us-east-1"
AWS_ACCESS_KEY_ID="your-access-key-id"
AWS_SECRET_ACCESS_KEY="your-secret-access-key"
AWS_S3_BUCKET="your-bucket-name"
lib/s3-client.ts
import { S3Client } from "@aws-sdk/client-s3";

export const s3Client = new S3Client({
  region: process.env.AWS_REGION!,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  },
});

export const defaultBucket = process.env.AWS_S3_BUCKET!;

Provider quirks (POST vs PUT, ACL, path-style): Providers.

Config

Enable only what you need. Start minimal for upload-first apps.

lib/s3.ts
import { dimahS3 } from "@dimah-s3/server";
import { s3Client, defaultBucket } from "@/lib/s3-client";

export const s3 = dimahS3({
  s3: s3Client,
  defaultBucket,
  // R2: { enabled: true, method: "PUT" }
  upload: { enabled: true },
  download: { enabled: false },
  delete: { enabled: false },
  multipart: { enabled: false },
});

Hook reference: Guard, Upload, Download, Delete, Multipart.

Prop

Type

Route handler

Mount at /api/s3 by default. Full examples for every supported framework: Adapters.

app/api/s3/[...s3]/route.ts
import { toNextJsHandler } from "@dimah-s3/server/next";
import { s3 } from "@/lib/s3";

export const { GET, POST, DELETE } = toNextJsHandler(s3);

Also available: @dimah-s3/server/fastify, @dimah-s3/server/elysia, @dimah-s3/server/svelte-kit, @dimah-s3/server/node.

Custom base path — set basePath on dimahS3({ basePath }) and pass the same value to createS3Client({ basePath }) on the client.

Server api

Call the same protocol from Server Actions or RSC without HTTP. Pass headers so guards / db scope still see the request context.

app/actions.ts
"use server";

import { headers } from "next/headers";
import { s3 } from "@/lib/s3";

export async function getDownloadUrl(key: string) {
  return s3.api.download(key, {
    headers: await headers(),
  });
}

s3.api implements the same S3Api shape as the browser client (upload, confirm, download, delete, multipart). Errors throw DimahS3Error with a status field.

Client

On the frontend, use createS3Client from @dimah-s3/react (recommended) or @dimah-s3/core (fetch-only):

components/s3-provider.tsx
"use client";

import { createS3Client } from "@dimah-s3/react";

export const { api, S3Provider, useApi } = createS3Client();

export function S3ClientProvider({ children }: { children: React.ReactNode }) {
  return <S3Provider>{children}</S3Provider>;
}

Same basePath as the server when customized: createS3Client({ basePath: "/api/your-path" }).

On this page