fix(icons): local icon repository does not work with medias (#1765)
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
"@homarr/cron-jobs": "workspace:^0.1.0",
|
"@homarr/cron-jobs": "workspace:^0.1.0",
|
||||||
"@homarr/db": "workspace:^0.1.0",
|
"@homarr/db": "workspace:^0.1.0",
|
||||||
"@homarr/definitions": "workspace:^0.1.0",
|
"@homarr/definitions": "workspace:^0.1.0",
|
||||||
|
"@homarr/icons": "workspace:^0.1.0",
|
||||||
"@homarr/integrations": "workspace:^0.1.0",
|
"@homarr/integrations": "workspace:^0.1.0",
|
||||||
"@homarr/log": "workspace:^",
|
"@homarr/log": "workspace:^",
|
||||||
"@homarr/old-import": "workspace:^0.1.0",
|
"@homarr/old-import": "workspace:^0.1.0",
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
|
|
||||||
|
import type { InferInsertModel } from "@homarr/db";
|
||||||
import { and, createId, desc, eq, like } from "@homarr/db";
|
import { and, createId, desc, eq, like } from "@homarr/db";
|
||||||
import { medias } from "@homarr/db/schema";
|
import { iconRepositories, icons, medias } from "@homarr/db/schema";
|
||||||
|
import { createLocalImageUrl, LOCAL_ICON_REPOSITORY_SLUG, mapMediaToIcon } from "@homarr/icons/local";
|
||||||
import { validation, z } from "@homarr/validation";
|
import { validation, z } from "@homarr/validation";
|
||||||
|
|
||||||
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure } from "../../trpc";
|
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure } from "../../trpc";
|
||||||
@@ -52,13 +54,29 @@ export const mediaRouter = createTRPCRouter({
|
|||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const content = Buffer.from(await input.file.arrayBuffer());
|
const content = Buffer.from(await input.file.arrayBuffer());
|
||||||
const id = createId();
|
const id = createId();
|
||||||
await ctx.db.insert(medias).values({
|
const media = {
|
||||||
id,
|
id,
|
||||||
creatorId: ctx.session.user.id,
|
creatorId: ctx.session.user.id,
|
||||||
content,
|
content,
|
||||||
size: input.file.size,
|
size: input.file.size,
|
||||||
contentType: input.file.type,
|
contentType: input.file.type,
|
||||||
name: input.file.name,
|
name: input.file.name,
|
||||||
|
} satisfies InferInsertModel<typeof medias>;
|
||||||
|
await ctx.db.insert(medias).values(media);
|
||||||
|
|
||||||
|
const localIconRepository = await ctx.db.query.iconRepositories.findFirst({
|
||||||
|
where: eq(iconRepositories.slug, LOCAL_ICON_REPOSITORY_SLUG),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!localIconRepository) return id;
|
||||||
|
|
||||||
|
const icon = mapMediaToIcon(media);
|
||||||
|
await ctx.db.insert(icons).values({
|
||||||
|
id: createId(),
|
||||||
|
checksum: icon.checksum,
|
||||||
|
name: icon.fileNameWithExtension,
|
||||||
|
url: icon.imageUrl,
|
||||||
|
iconRepositoryId: localIconRepository.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
@@ -67,6 +85,7 @@ export const mediaRouter = createTRPCRouter({
|
|||||||
const dbMedia = await ctx.db.query.medias.findFirst({
|
const dbMedia = await ctx.db.query.medias.findFirst({
|
||||||
where: eq(medias.id, input.id),
|
where: eq(medias.id, input.id),
|
||||||
columns: {
|
columns: {
|
||||||
|
id: true,
|
||||||
creatorId: true,
|
creatorId: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -87,5 +106,6 @@ export const mediaRouter = createTRPCRouter({
|
|||||||
}
|
}
|
||||||
|
|
||||||
await ctx.db.delete(medias).where(eq(medias.id, input.id));
|
await ctx.db.delete(medias).where(eq(medias.id, input.id));
|
||||||
|
await ctx.db.delete(icons).where(eq(icons.url, createLocalImageUrl(input.id)));
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./index.ts"
|
".": "./index.ts",
|
||||||
|
"./local": "./src/local.ts"
|
||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
|
|||||||
1
packages/icons/src/local.ts
Normal file
1
packages/icons/src/local.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { createLocalImageUrl, mapMediaToIcon, LOCAL_ICON_REPOSITORY_SLUG } from "./repositories/local.icon-repository";
|
||||||
@@ -1,26 +1,36 @@
|
|||||||
import { createHash } from "crypto";
|
import { createHash } from "crypto";
|
||||||
|
|
||||||
|
import type { InferSelectModel } from "@homarr/db";
|
||||||
import { db } from "@homarr/db";
|
import { db } from "@homarr/db";
|
||||||
|
import type { medias } from "@homarr/db/schema";
|
||||||
|
|
||||||
import type { RepositoryIconGroup } from "../types";
|
import type { RepositoryIcon, RepositoryIconGroup } from "../types";
|
||||||
import { IconRepository } from "./icon-repository";
|
import { IconRepository } from "./icon-repository";
|
||||||
|
|
||||||
|
export const LOCAL_ICON_REPOSITORY_SLUG = "local";
|
||||||
|
|
||||||
export class LocalIconRepository extends IconRepository {
|
export class LocalIconRepository extends IconRepository {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("Local", "local", undefined, undefined, undefined, undefined);
|
super("Local", LOCAL_ICON_REPOSITORY_SLUG, undefined, undefined, undefined, undefined);
|
||||||
}
|
}
|
||||||
protected async getAllIconsInternalAsync(): Promise<RepositoryIconGroup> {
|
protected async getAllIconsInternalAsync(): Promise<RepositoryIconGroup> {
|
||||||
const medias = await db.query.medias.findMany();
|
const medias = await db.query.medias.findMany();
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
icons: medias.map((media) => ({
|
icons: medias.map(mapMediaToIcon),
|
||||||
local: true,
|
slug: LOCAL_ICON_REPOSITORY_SLUG,
|
||||||
fileNameWithExtension: media.name,
|
|
||||||
imageUrl: `/api/user-medias/${media.id}`,
|
|
||||||
checksum: createHash("md5").update(media.content).digest("hex"),
|
|
||||||
sizeInBytes: media.size,
|
|
||||||
})),
|
|
||||||
slug: "local",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createLocalImageUrl = (id: string) => `/api/user-medias/${id}`;
|
||||||
|
|
||||||
|
export const mapMediaToIcon = (
|
||||||
|
media: Pick<InferSelectModel<typeof medias>, "name" | "id" | "content" | "size">,
|
||||||
|
): RepositoryIcon => ({
|
||||||
|
local: true,
|
||||||
|
fileNameWithExtension: media.name,
|
||||||
|
imageUrl: createLocalImageUrl(media.id),
|
||||||
|
checksum: createHash("md5").update(media.content).digest("hex"),
|
||||||
|
sizeInBytes: media.size,
|
||||||
|
});
|
||||||
|
|||||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -509,6 +509,9 @@ importers:
|
|||||||
'@homarr/definitions':
|
'@homarr/definitions':
|
||||||
specifier: workspace:^0.1.0
|
specifier: workspace:^0.1.0
|
||||||
version: link:../definitions
|
version: link:../definitions
|
||||||
|
'@homarr/icons':
|
||||||
|
specifier: workspace:^0.1.0
|
||||||
|
version: link:../icons
|
||||||
'@homarr/integrations':
|
'@homarr/integrations':
|
||||||
specifier: workspace:^0.1.0
|
specifier: workspace:^0.1.0
|
||||||
version: link:../integrations
|
version: link:../integrations
|
||||||
|
|||||||
Reference in New Issue
Block a user