refactor: 🚨 Make more class methods static

This commit is contained in:
Jesse Wierzbinski 2024-10-03 19:02:13 +02:00
parent 5ec19f037a
commit 2537e3cd48
No known key found for this signature in database
8 changed files with 40 additions and 44 deletions

View file

@ -15,13 +15,13 @@ import {
import { rm } from "node:fs/promises"; import { rm } from "node:fs/promises";
import { join } from "node:path"; import { join } from "node:path";
import type { Config } from "~/packages/config-manager/config.type"; 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"; import { DiskMediaDriver } from "./disk";
describe("DiskMediaDriver", () => { describe("DiskMediaDriver", () => {
let diskDriver: DiskMediaDriver; let diskDriver: DiskMediaDriver;
let mockConfig: Config; let mockConfig: Config;
let mockMediaHasher: MediaHasher; let mockMediaHasher: Mock<typeof getMediaHash>;
let bunWriteSpy: Mock<typeof Bun.write>; let bunWriteSpy: Mock<typeof Bun.write>;
beforeEach(() => { beforeEach(() => {
@ -31,9 +31,11 @@ describe("DiskMediaDriver", () => {
}, },
} as Config; } as Config;
mockMediaHasher = mock(() => ({ mockMediaHasher = mock(() => Promise.resolve("testhash"));
getMediaHash: mock(() => Promise.resolve("testhash")),
}))(); mock.module("../media-hasher", () => ({
getMediaHash: mockMediaHasher,
}));
diskDriver = new DiskMediaDriver(mockConfig); diskDriver = new DiskMediaDriver(mockConfig);
// @ts-expect-error: Replacing private property for testing // @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 file = new File(["test"], "test.webp", { type: "image/webp" });
const result = await diskDriver.addFile(file); const result = await diskDriver.addFile(file);
expect(mockMediaHasher.getMediaHash).toHaveBeenCalledWith(file); expect(mockMediaHasher).toHaveBeenCalledWith(file);
expect(bunWriteSpy).toHaveBeenCalledWith( expect(bunWriteSpy).toHaveBeenCalledWith(
join("/test/uploads", "testhash", "test.webp"), join("/test/uploads", "testhash", "test.webp"),
expect.any(ArrayBuffer), expect.any(ArrayBuffer),
@ -81,7 +83,7 @@ describe("DiskMediaDriver", () => {
const file = new Blob(["test"], { type: "image/webp" }); const file = new Blob(["test"], { type: "image/webp" });
const result = await diskDriver.addFile(file as File); const result = await diskDriver.addFile(file as File);
expect(mockMediaHasher.getMediaHash).toHaveBeenCalledWith(file); expect(mockMediaHasher).toHaveBeenCalledWith(file);
expect(bunWriteSpy).toHaveBeenCalledWith( expect(bunWriteSpy).toHaveBeenCalledWith(
expect.stringContaining("testhash"), expect.stringContaining("testhash"),
expect.any(ArrayBuffer), expect.any(ArrayBuffer),

View file

@ -6,7 +6,7 @@
import { rm } from "node:fs/promises"; import { rm } from "node:fs/promises";
import { join } from "node:path"; import { join } from "node:path";
import type { Config } from "~/packages/config-manager/config.type"; 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 { UploadedFileMetadata } from "../media-manager";
import type { MediaDriver } from "./media-driver"; import type { MediaDriver } from "./media-driver";
@ -14,15 +14,11 @@ import type { MediaDriver } from "./media-driver";
* Implements the MediaDriver interface for disk storage. * Implements the MediaDriver interface for disk storage.
*/ */
export class DiskMediaDriver implements MediaDriver { export class DiskMediaDriver implements MediaDriver {
private mediaHasher: MediaHasher;
/** /**
* Creates a new DiskMediaDriver instance. * Creates a new DiskMediaDriver instance.
* @param config - The configuration object. * @param config - The configuration object.
*/ */
constructor(private config: Config) { constructor(private config: Config) {}
this.mediaHasher = new MediaHasher();
}
/** /**
* @inheritdoc * @inheritdoc
@ -33,7 +29,7 @@ export class DiskMediaDriver implements MediaDriver {
// Sometimes the file name is not available, so we generate a random name // Sometimes the file name is not available, so we generate a random name
const fileName = file.name ?? crypto.randomUUID(); const fileName = file.name ?? crypto.randomUUID();
const hash = await this.mediaHasher.getMediaHash(file); const hash = await getMediaHash(file);
const path = join(hash, fileName); const path = join(hash, fileName);
const fullPath = join(this.config.media.local_uploads_folder, path); const fullPath = join(this.config.media.local_uploads_folder, path);

View file

@ -3,17 +3,17 @@
* @module Tests/S3MediaDriver * @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 { S3Client } from "@bradenmacdonald/s3-lite-client";
import type { Config } from "~/packages/config-manager/config.type"; 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"; import { S3MediaDriver } from "./s3";
describe("S3MediaDriver", () => { describe("S3MediaDriver", () => {
let s3Driver: S3MediaDriver; let s3Driver: S3MediaDriver;
let mockConfig: Config; let mockConfig: Config;
let mockS3Client: S3Client; let mockS3Client: S3Client;
let mockMediaHasher: MediaHasher; let mockMediaHasher: Mock<typeof getMediaHash>;
beforeEach(() => { beforeEach(() => {
mockConfig = { mockConfig = {
@ -38,9 +38,11 @@ describe("S3MediaDriver", () => {
deleteObject: mock(() => Promise.resolve()), deleteObject: mock(() => Promise.resolve()),
}))() as unknown as S3Client; }))() as unknown as S3Client;
mockMediaHasher = mock(() => ({ mockMediaHasher = mock(() => Promise.resolve("testhash"));
getMediaHash: mock(() => Promise.resolve("testhash")),
}))(); mock.module("../media-hasher", () => ({
getMediaHash: mockMediaHasher,
}));
s3Driver = new S3MediaDriver(mockConfig); s3Driver = new S3MediaDriver(mockConfig);
// @ts-expect-error: Replacing private property for testing // @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 file = new File(["test"], "test.webp", { type: "image/webp" });
const result = await s3Driver.addFile(file); const result = await s3Driver.addFile(file);
expect(mockMediaHasher.getMediaHash).toHaveBeenCalledWith(file); expect(mockMediaHasher).toHaveBeenCalledWith(file);
expect(mockS3Client.putObject).toHaveBeenCalledWith( expect(mockS3Client.putObject).toHaveBeenCalledWith(
"testhash/test.webp", "testhash/test.webp",
expect.any(ReadableStream), expect.any(ReadableStream),
@ -70,7 +72,7 @@ describe("S3MediaDriver", () => {
const file = new Blob(["test"], { type: "image/webp" }); const file = new Blob(["test"], { type: "image/webp" });
const result = await s3Driver.addFile(file as File); const result = await s3Driver.addFile(file as File);
expect(mockMediaHasher.getMediaHash).toHaveBeenCalledWith(file); expect(mockMediaHasher).toHaveBeenCalledWith(file);
expect(mockS3Client.putObject).toHaveBeenCalledWith( expect(mockS3Client.putObject).toHaveBeenCalledWith(
expect.stringContaining("testhash"), expect.stringContaining("testhash"),
expect.any(ReadableStream), expect.any(ReadableStream),

View file

@ -5,7 +5,7 @@
import { S3Client } from "@bradenmacdonald/s3-lite-client"; import { S3Client } from "@bradenmacdonald/s3-lite-client";
import type { Config } from "~/packages/config-manager/config.type"; 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 { UploadedFileMetadata } from "../media-manager";
import type { MediaDriver } from "./media-driver"; import type { MediaDriver } from "./media-driver";
@ -14,7 +14,6 @@ import type { MediaDriver } from "./media-driver";
*/ */
export class S3MediaDriver implements MediaDriver { export class S3MediaDriver implements MediaDriver {
private s3Client: S3Client; private s3Client: S3Client;
private mediaHasher: MediaHasher;
/** /**
* Creates a new S3MediaDriver instance. * Creates a new S3MediaDriver instance.
@ -29,7 +28,6 @@ export class S3MediaDriver implements MediaDriver {
accessKey: config.s3.access_key, accessKey: config.s3.access_key,
secretKey: config.s3.secret_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 // Sometimes the file name is not available, so we generate a random name
const fileName = file.name ?? crypto.randomUUID(); const fileName = file.name ?? crypto.randomUUID();
const hash = await this.mediaHasher.getMediaHash(file); const hash = await getMediaHash(file);
const path = `${hash}/${fileName}`; const path = `${hash}/${fileName}`;
await this.s3Client.putObject(path, file.stream(), { await this.s3Client.putObject(path, file.stream(), {

View file

@ -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 { export const getMediaHash = async (file: File): Promise<string> => {
/** const arrayBuffer = await file.arrayBuffer();
* Generates a SHA-256 hash for a given file. const hash = new Bun.SHA256().update(arrayBuffer).digest("hex");
* @param file - The file to hash. return hash;
* @returns A promise that resolves to the SHA-256 hash of the file in hex format. };
*/
public async getMediaHash(file: File): Promise<string> {
const arrayBuffer = await file.arrayBuffer();
const hash = new Bun.SHA256().update(arrayBuffer).digest("hex");
return hash;
}
}

View file

@ -70,7 +70,10 @@ export class ImageConversionPreprocessor implements MediaPreprocessor {
return { return {
file: new File( file: new File(
[convertedBuffer], [convertedBuffer],
this.getReplacedFileName(file.name, commandName), ImageConversionPreprocessor.getReplacedFileName(
file.name,
commandName,
),
{ {
type: targetFormat, type: targetFormat,
lastModified: Date.now(), lastModified: Date.now(),
@ -100,7 +103,7 @@ export class ImageConversionPreprocessor implements MediaPreprocessor {
* @param newExtension - The new extension. * @param newExtension - The new extension.
* @returns The filename with the new extension. * @returns The filename with the new extension.
*/ */
private getReplacedFileName( private static getReplacedFileName(
fileName: string, fileName: string,
newExtension: string, newExtension: string,
): string { ): string {

View file

@ -99,7 +99,7 @@ describe("PluginLoader", () => {
]) ])
.mockResolvedValue(["manifest.json", "index.ts"]); .mockResolvedValue(["manifest.json", "index.ts"]);
const plugins = await pluginLoader.findPlugins("/some/path"); const plugins = await PluginLoader.findPlugins("/some/path");
expect(plugins).toEqual(["plugin1", "plugin2"]); expect(plugins).toEqual(["plugin1", "plugin2"]);
}); });

View file

@ -80,7 +80,7 @@ export class PluginLoader {
* @param {string} dir - The directory to search. * @param {string} dir - The directory to search.
* @returns {Promise<string[]>} - An array of plugin directories. * @returns {Promise<string[]>} - An array of plugin directories.
*/ */
public async findPlugins(dir: string): Promise<string[]> { public static async findPlugins(dir: string): Promise<string[]> {
const directories = await PluginLoader.getDirectories(dir); const directories = await PluginLoader.getDirectories(dir);
const plugins: string[] = []; const plugins: string[] = [];
@ -163,7 +163,7 @@ export class PluginLoader {
public async loadPlugins( public async loadPlugins(
dir: string, dir: string,
): Promise<{ manifest: Manifest; plugin: Plugin<ZodTypeAny> }[]> { ): Promise<{ manifest: Manifest; plugin: Plugin<ZodTypeAny> }[]> {
const plugins = await this.findPlugins(dir); const plugins = await PluginLoader.findPlugins(dir);
return Promise.all( return Promise.all(
plugins.map(async (plugin) => { plugins.map(async (plugin) => {