diff --git a/classes/media/drivers/disk.test.ts b/classes/media/drivers/disk.test.ts index cc6bb323..41e1e6e4 100644 --- a/classes/media/drivers/disk.test.ts +++ b/classes/media/drivers/disk.test.ts @@ -15,13 +15,13 @@ import { import { rm } from "node:fs/promises"; import { join } from "node:path"; import type { Config } from "~/packages/config-manager/config.type"; -import type { MediaHasher } from "../media-hasher"; +import type { getMediaHash } from "../media-hasher"; import { DiskMediaDriver } from "./disk"; describe("DiskMediaDriver", () => { let diskDriver: DiskMediaDriver; let mockConfig: Config; - let mockMediaHasher: MediaHasher; + let mockMediaHasher: Mock; let bunWriteSpy: Mock; beforeEach(() => { @@ -31,9 +31,11 @@ describe("DiskMediaDriver", () => { }, } as Config; - mockMediaHasher = mock(() => ({ - getMediaHash: mock(() => Promise.resolve("testhash")), - }))(); + mockMediaHasher = mock(() => Promise.resolve("testhash")); + + mock.module("../media-hasher", () => ({ + getMediaHash: mockMediaHasher, + })); diskDriver = new DiskMediaDriver(mockConfig); // @ts-expect-error: Replacing private property for testing @@ -65,7 +67,7 @@ describe("DiskMediaDriver", () => { const file = new File(["test"], "test.webp", { type: "image/webp" }); const result = await diskDriver.addFile(file); - expect(mockMediaHasher.getMediaHash).toHaveBeenCalledWith(file); + expect(mockMediaHasher).toHaveBeenCalledWith(file); expect(bunWriteSpy).toHaveBeenCalledWith( join("/test/uploads", "testhash", "test.webp"), expect.any(ArrayBuffer), @@ -81,7 +83,7 @@ describe("DiskMediaDriver", () => { const file = new Blob(["test"], { type: "image/webp" }); const result = await diskDriver.addFile(file as File); - expect(mockMediaHasher.getMediaHash).toHaveBeenCalledWith(file); + expect(mockMediaHasher).toHaveBeenCalledWith(file); expect(bunWriteSpy).toHaveBeenCalledWith( expect.stringContaining("testhash"), expect.any(ArrayBuffer), diff --git a/classes/media/drivers/disk.ts b/classes/media/drivers/disk.ts index d915d184..a3b93406 100644 --- a/classes/media/drivers/disk.ts +++ b/classes/media/drivers/disk.ts @@ -6,7 +6,7 @@ import { rm } from "node:fs/promises"; import { join } from "node:path"; import type { Config } from "~/packages/config-manager/config.type"; -import { MediaHasher } from "../media-hasher"; +import { getMediaHash } from "../media-hasher"; import type { UploadedFileMetadata } from "../media-manager"; import type { MediaDriver } from "./media-driver"; @@ -14,15 +14,11 @@ import type { MediaDriver } from "./media-driver"; * Implements the MediaDriver interface for disk storage. */ export class DiskMediaDriver implements MediaDriver { - private mediaHasher: MediaHasher; - /** * Creates a new DiskMediaDriver instance. * @param config - The configuration object. */ - constructor(private config: Config) { - this.mediaHasher = new MediaHasher(); - } + constructor(private config: Config) {} /** * @inheritdoc @@ -33,7 +29,7 @@ export class DiskMediaDriver implements MediaDriver { // Sometimes the file name is not available, so we generate a random name const fileName = file.name ?? crypto.randomUUID(); - const hash = await this.mediaHasher.getMediaHash(file); + const hash = await getMediaHash(file); const path = join(hash, fileName); const fullPath = join(this.config.media.local_uploads_folder, path); diff --git a/classes/media/drivers/s3.test.ts b/classes/media/drivers/s3.test.ts index 8704e048..23809a87 100644 --- a/classes/media/drivers/s3.test.ts +++ b/classes/media/drivers/s3.test.ts @@ -3,17 +3,17 @@ * @module Tests/S3MediaDriver */ -import { beforeEach, describe, expect, it, mock } from "bun:test"; +import { type Mock, beforeEach, describe, expect, it, mock } from "bun:test"; import type { S3Client } from "@bradenmacdonald/s3-lite-client"; import type { Config } from "~/packages/config-manager/config.type"; -import type { MediaHasher } from "../media-hasher"; +import type { getMediaHash } from "../media-hasher"; import { S3MediaDriver } from "./s3"; describe("S3MediaDriver", () => { let s3Driver: S3MediaDriver; let mockConfig: Config; let mockS3Client: S3Client; - let mockMediaHasher: MediaHasher; + let mockMediaHasher: Mock; beforeEach(() => { mockConfig = { @@ -38,9 +38,11 @@ describe("S3MediaDriver", () => { deleteObject: mock(() => Promise.resolve()), }))() as unknown as S3Client; - mockMediaHasher = mock(() => ({ - getMediaHash: mock(() => Promise.resolve("testhash")), - }))(); + mockMediaHasher = mock(() => Promise.resolve("testhash")); + + mock.module("../media-hasher", () => ({ + getMediaHash: mockMediaHasher, + })); s3Driver = new S3MediaDriver(mockConfig); // @ts-expect-error: Replacing private property for testing @@ -53,7 +55,7 @@ describe("S3MediaDriver", () => { const file = new File(["test"], "test.webp", { type: "image/webp" }); const result = await s3Driver.addFile(file); - expect(mockMediaHasher.getMediaHash).toHaveBeenCalledWith(file); + expect(mockMediaHasher).toHaveBeenCalledWith(file); expect(mockS3Client.putObject).toHaveBeenCalledWith( "testhash/test.webp", expect.any(ReadableStream), @@ -70,7 +72,7 @@ describe("S3MediaDriver", () => { const file = new Blob(["test"], { type: "image/webp" }); const result = await s3Driver.addFile(file as File); - expect(mockMediaHasher.getMediaHash).toHaveBeenCalledWith(file); + expect(mockMediaHasher).toHaveBeenCalledWith(file); expect(mockS3Client.putObject).toHaveBeenCalledWith( expect.stringContaining("testhash"), expect.any(ReadableStream), diff --git a/classes/media/drivers/s3.ts b/classes/media/drivers/s3.ts index 396e0222..487c1b58 100644 --- a/classes/media/drivers/s3.ts +++ b/classes/media/drivers/s3.ts @@ -5,7 +5,7 @@ import { S3Client } from "@bradenmacdonald/s3-lite-client"; import type { Config } from "~/packages/config-manager/config.type"; -import { MediaHasher } from "../media-hasher"; +import { getMediaHash } from "../media-hasher"; import type { UploadedFileMetadata } from "../media-manager"; import type { MediaDriver } from "./media-driver"; @@ -14,7 +14,6 @@ import type { MediaDriver } from "./media-driver"; */ export class S3MediaDriver implements MediaDriver { private s3Client: S3Client; - private mediaHasher: MediaHasher; /** * Creates a new S3MediaDriver instance. @@ -29,7 +28,6 @@ export class S3MediaDriver implements MediaDriver { accessKey: config.s3.access_key, secretKey: config.s3.secret_access_key, }); - this.mediaHasher = new MediaHasher(); } /** @@ -41,7 +39,7 @@ export class S3MediaDriver implements MediaDriver { // Sometimes the file name is not available, so we generate a random name const fileName = file.name ?? crypto.randomUUID(); - const hash = await this.mediaHasher.getMediaHash(file); + const hash = await getMediaHash(file); const path = `${hash}/${fileName}`; await this.s3Client.putObject(path, file.stream(), { diff --git a/classes/media/media-hasher.ts b/classes/media/media-hasher.ts index eb70c2ed..7e30c032 100644 --- a/classes/media/media-hasher.ts +++ b/classes/media/media-hasher.ts @@ -4,17 +4,12 @@ */ /** - * Utility class for hashing media files. + * Generates a SHA-256 hash for a given file. + * @param file - The file to hash. + * @returns A promise that resolves to the SHA-256 hash of the file in hex format. */ -export class MediaHasher { - /** - * Generates a SHA-256 hash for a given file. - * @param file - The file to hash. - * @returns A promise that resolves to the SHA-256 hash of the file in hex format. - */ - public async getMediaHash(file: File): Promise { - const arrayBuffer = await file.arrayBuffer(); - const hash = new Bun.SHA256().update(arrayBuffer).digest("hex"); - return hash; - } -} +export const getMediaHash = async (file: File): Promise => { + const arrayBuffer = await file.arrayBuffer(); + const hash = new Bun.SHA256().update(arrayBuffer).digest("hex"); + return hash; +}; diff --git a/classes/media/preprocessors/image-conversion.ts b/classes/media/preprocessors/image-conversion.ts index a4f94b8f..e79c9ae8 100644 --- a/classes/media/preprocessors/image-conversion.ts +++ b/classes/media/preprocessors/image-conversion.ts @@ -70,7 +70,10 @@ export class ImageConversionPreprocessor implements MediaPreprocessor { return { file: new File( [convertedBuffer], - this.getReplacedFileName(file.name, commandName), + ImageConversionPreprocessor.getReplacedFileName( + file.name, + commandName, + ), { type: targetFormat, lastModified: Date.now(), @@ -100,7 +103,7 @@ export class ImageConversionPreprocessor implements MediaPreprocessor { * @param newExtension - The new extension. * @returns The filename with the new extension. */ - private getReplacedFileName( + private static getReplacedFileName( fileName: string, newExtension: string, ): string { diff --git a/classes/plugin/loader.test.ts b/classes/plugin/loader.test.ts index f84e0ea7..861550a4 100644 --- a/classes/plugin/loader.test.ts +++ b/classes/plugin/loader.test.ts @@ -99,7 +99,7 @@ describe("PluginLoader", () => { ]) .mockResolvedValue(["manifest.json", "index.ts"]); - const plugins = await pluginLoader.findPlugins("/some/path"); + const plugins = await PluginLoader.findPlugins("/some/path"); expect(plugins).toEqual(["plugin1", "plugin2"]); }); diff --git a/classes/plugin/loader.ts b/classes/plugin/loader.ts index e03edbf4..0456ba4d 100644 --- a/classes/plugin/loader.ts +++ b/classes/plugin/loader.ts @@ -80,7 +80,7 @@ export class PluginLoader { * @param {string} dir - The directory to search. * @returns {Promise} - An array of plugin directories. */ - public async findPlugins(dir: string): Promise { + public static async findPlugins(dir: string): Promise { const directories = await PluginLoader.getDirectories(dir); const plugins: string[] = []; @@ -163,7 +163,7 @@ export class PluginLoader { public async loadPlugins( dir: string, ): Promise<{ manifest: Manifest; plugin: Plugin }[]> { - const plugins = await this.findPlugins(dir); + const plugins = await PluginLoader.findPlugins(dir); return Promise.all( plugins.map(async (plugin) => {