ImageKit Storage Provider

This provider adds the ImageKit Node SDK, validates IMAGEKIT_PRIVATE_KEY with Zod, and ships the same Multer memory-upload middleware pattern as the Cloudinary provider.


Installation Guide

npx servercn-cli add pr imagekit-storage

Basic Implementation

src/configs/env.ts
import "dotenv-flow/config";
import { z } from "zod";
 
export const envSchema = z.object({
  IMAGEKIT_PRIVATE_KEY: z.string()
});
 
export type Env = z.infer<typeof envSchema>;
 
const result = envSchema.safeParse(process.env);
 
if (!result.success) {
  console.error("❌ Invalid environment configuration");
  console.error(z.prettifyError(result.error));
  process.exit(1);
}
 
export const env: Readonly<Env> = Object.freeze(result.data);
 
export default env;

src/configs/imagekit.ts
import ImageKit from "@imagekit/nodejs";
import env from "./env";
 
const imagekitClient = new ImageKit({
  privateKey: env.IMAGEKIT_PRIVATE_KEY
});
 
export default imagekitClient;

The template file includes commented uploadToImageKit and deleteFileFromImageKit helpers using toFile from @imagekit/nodejs—use those as a starting point in a service layer.


src/middlewares/upload-file.ts
import multer from "multer";
 
export const ALLOWED_FILE_TYPES = [
  "image/jpeg",
  "image/png",
  "image/webp",
  "video/mp4",
  "video/mpeg",
  "video/quicktime",
  "application/pdf"
];
 
export const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
 
const storage = multer.memoryStorage();
 
const fileFilter: multer.Options["fileFilter"] = (_req, file, cb) => {
  if (!ALLOWED_FILE_TYPES.includes(file.mimetype)) {
    return cb(null, false);
  }
  cb(null, true);
};
 
const upload = multer({
  storage,
  limits: { fileSize: MAX_FILE_SIZE },
  fileFilter
});
 
export default upload;

Usage

Use upload.single("fieldName") (or array/fields) on your route, then upload req.file.buffer via the helpers described in the template’s imagekit.ts comments.

src/services/imagekit.service.ts
import imagekitClient from "../configs/imagekit";
import { toFile } from "@imagekit/nodejs";
 
export interface UploadOptions {
  folder: string;
  fileName?: string;
}
 
export interface ImageKitUploadResult {
  url: string;
  fileId: string;
  size: number;
}
 
export const uploadToImageKit = async (
  buffer: Buffer,
  options: UploadOptions
): Promise<ImageKitUploadResult> => {
  try {
    const fileName = options.fileName || `file-${Date.now()}`;
    const file = await toFile(buffer, fileName);
 
    const result = await imagekitClient.files.upload({
      file: file,
      fileName: fileName,
      folder: options.folder || "uploads"
    });
 
    return {
      url: result.url || "",
      fileId: result.fileId || "",
      size: result.size || 0
    };
  } catch (error) {
    throw error;
  }
};
 
export const deleteFileFromImageKit = async (
  fileIds: string[]
): Promise<void> => {
  try {
    await Promise.all(
      fileIds.map(fileId => imagekitClient.files.delete(fileId))
    );
  } catch (error) {
    throw error;
  }
};

File & Folder Structure

Loading files...

Installation

npx servercn-cli add pr imagekit-storage