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.
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
- delete.guardhook
- DeleteObject in S3S3
- onDeletedDatabase cleanup
Type reference
import type {
DeleteGuardContext,
DeleteOnDeletedContext,
} from "@dimah-s3/server";DeleteGuardContext
Prop
Type
DeleteOnDeletedContext
Prop
Type
Frequently asked questions
Batch deletion (deleteMany / removeMany) runs delete.guard for each target key, calls S3 DeleteObjects, and triggers onDeleted for all successfully removed keys:
const { removeMany } = useDelete({ route: "avatar" });
await removeMany([key1, key2]);If S3 returns an error during deletion, onDeleted does not execute and the endpoint returns an appropriate error response (502 S3_NETWORK_ERROR or INTERNAL_ERROR).