2.0 beta is ready. Install with @beta.
dimah-s3v1.7.2

Delete Hooks

Authorize deletion and execute cleanup after S3 removes the object.

Enable object deletion with delete: true or a DeleteConfig object on a named route.

Unlike upload and download, object deletion is executed directly on your server using DeleteObjectCommand after passing guard checks. The client never deletes from S3 directly.

delete: true turns the endpoint on. It does not check who owns the object. The key must still sit under this route's keyPrefix (the route name by default) — that check always runs, with or without db(). Ownership is delete.guard or the db plugin. See Security.

lib/s3.ts
import { S3Client } from "@aws-sdk/client-s3";
import { dimahS3, errors, route } from "@dimah-s3/server";

export const awsS3 = new S3Client({/* env */});

export const s3 = dimahS3({
  client: awsS3,
  bucket: process.env.S3_BUCKET!,
  routes: {
    avatar: route({
      delete: {
        guard: async ({ key, request }) => {
          const session = await getSession(request);
          if (!session) throw errors.unauthorized();

          const isOwner = await checkAvatarOwnership(session.userId, key);
          if (!isOwner) throw errors.forbidden();
        },
        onDeleted: async ({ key, request }) => {
          const session = await getSession(request); 
          await db.user.update({
            where: { id: session.userId }, 
            data: { avatarKey: null }, 
          }); 
        }, 
      },
    }),
  },
});

Delete lifecycle flow

Before delete.guard, the server resolves the named route and rejects keys outside its keyPrefix (INVALID_KEY).

Delete flow
  1. delete.guardhook
  2. HeadObject in S3S3
  3. DeleteObject in S3Only if it exists
  4. onDeletedDatabase cleanup

Delete is idempotent. When HeadObject finds nothing — an upload that was presigned but never sent, an aborted multipart upload, or an object a bucket lifecycle rule already removed — the server skips DeleteObject, still runs onDeleted with existed: false, and responds with { success: true, existed: false }. A database row for that key is cleaned up the same way as for a stored object.


Type reference

import type {
  DeleteGuardContext,
  DeleteOnDeletedContext,
} from "@dimah-s3/server";

DeleteGuardContext

Prop

Type


DeleteOnDeletedContext

Prop

Type

Frequently asked questions

On this page