Routes
Named file routes — server-owned keys, constraints, and object policies.
A route is a named storage policy on your server. Each route manages its own constraints, object keys, and enabled operations (upload, download, delete, and multipart).
The client specifies the route name on every request. The server enforces file constraints, validates permissions, and generates object keys.
import { S3Client } from "@aws-sdk/client-s3";
import { dimahS3, 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({
upload: {
fileTypes: ["image/*"],
maxFileSize: 2 * 1024 * 1024,
},
download: true,
delete: true,
}),
document: route({
upload: {
fileTypes: ["application/pdf", "image/*"],
maxFileSize: 10 * 1024 * 1024,
},
download: true,
delete: true,
}),
video: route({
upload: {
fileTypes: ["video/*"],
maxFileSize: 500 * 1024 * 1024,
multipart: true,
},
}),
},
});Combining operations
Enable operations on the same route when they manage the same objects. For example, if users upload, view, and remove their avatars:
avatar: route({
upload: {
fileTypes: ["image/*"],
maxFileSize: 2 * 1024 * 1024,
},
download: true,
delete: true,
}),Follow-up operations (confirm, download, delete) must target keys within that route's namespace.
Key generation & object identity
By default, the server generates object keys formatted as:
{keyPrefix}/{uuid}/{sanitizedFileName}keyPrefix defaults to the route name (e.g. avatar/…).
To customize key generation or organize files by user/tenant, return folder or key from upload.object:
avatar: route({
upload: {
fileTypes: ["image/*"],
maxFileSize: 2 * 1024 * 1024,
object: async ({ request }) => {
const session = await getSession(request);
return {
folder: `users/${session.userId}`,
// Results in: avatar/users/{userId}/{uuid}/{fileName}
};
},
},
}),Type reference
import type {
DimahS3RouteConfig,
UploadConfig,
DownloadConfig,
DeleteConfig,
MultipartConfig,
} from "@dimah-s3/server";DimahS3RouteConfig
Prop
Type
UploadConfig
Prop
Type
DownloadConfig
Prop
Type
DeleteConfig
Prop
Type
Frequently asked questions
Set replace: "overwrite" and return a deterministic key from object:
avatar: route({
upload: {
fileTypes: ["image/*"],
maxFileSize: 2 * 1024 * 1024,
replace: "overwrite",
object: async ({ request }) => {
const session = await getSession(request);
return {
key: `avatars/${session.userId}/avatar.png`,
};
},
},
}),Return previousKey from upload.object. Once the new upload confirms successfully, dimah-s3 will automatically delete the old object from S3:
avatar: route({
upload: {
fileTypes: ["image/*"],
maxFileSize: 2 * 1024 * 1024,
object: async ({ request }) => {
const user = await getCurrentUser(request);
return {
folder: `users/${user.id}`,
previousKey: user.currentAvatarKey,
};
},
},
}),Set checksum: true in your upload config. The React client will automatically compute the SHA-256 hash in the browser and attach it to the presigned request:
avatar: route({
upload: {
fileTypes: ["image/*"],
maxFileSize: 2 * 1024 * 1024,
checksum: true,
},
}),Set mode: "proxy" on download. The download URL will point to a same-origin /api/s3/file endpoint that streams the object through your backend:
avatar: route({
download: {
mode: "proxy",
},
}),