mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
refactor(api): 🎨 Simplify expressions
This commit is contained in:
parent
36d70fb612
commit
98f3ab23d8
|
|
@ -6,9 +6,7 @@ import { config } from "config-manager";
|
|||
import { and, eq } from "drizzle-orm";
|
||||
import type { Hono } from "hono";
|
||||
import ISO6391 from "iso-639-1";
|
||||
import { MediaBackendType } from "media-manager";
|
||||
import type { MediaBackend } from "media-manager";
|
||||
import { LocalMediaBackend, S3MediaBackend } from "media-manager";
|
||||
import { MediaBackend } from "media-manager";
|
||||
import { z } from "zod";
|
||||
import { getUrl } from "~/database/entities/attachment";
|
||||
import { parseEmojis } from "~/database/entities/emoji";
|
||||
|
|
@ -127,19 +125,10 @@ export default (app: Hono) =>
|
|||
display_name ?? "",
|
||||
);
|
||||
|
||||
let mediaManager: MediaBackend;
|
||||
|
||||
switch (config.media.backend as MediaBackendType) {
|
||||
case MediaBackendType.Local:
|
||||
mediaManager = new LocalMediaBackend(config);
|
||||
break;
|
||||
case MediaBackendType.S3:
|
||||
mediaManager = new S3MediaBackend(config);
|
||||
break;
|
||||
default:
|
||||
// TODO: Replace with logger
|
||||
throw new Error("Invalid media backend");
|
||||
}
|
||||
const mediaManager = await MediaBackend.fromBackendType(
|
||||
config.media.backend,
|
||||
config,
|
||||
);
|
||||
|
||||
if (display_name) {
|
||||
// Check if display name doesnt match filters
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@ import { errorResponse, jsonResponse, response } from "@/response";
|
|||
import { zValidator } from "@hono/zod-validator";
|
||||
import { config } from "config-manager";
|
||||
import type { Hono } from "hono";
|
||||
import type { MediaBackend } from "media-manager";
|
||||
import { MediaBackendType } from "media-manager";
|
||||
import { LocalMediaBackend, S3MediaBackend } from "media-manager";
|
||||
import { MediaBackend } from "media-manager";
|
||||
import { z } from "zod";
|
||||
import { getUrl } from "~/database/entities/attachment";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
|
|
@ -74,19 +72,10 @@ export default (app: Hono) =>
|
|||
|
||||
let thumbnailUrl = attachment.data.thumbnailUrl;
|
||||
|
||||
let mediaManager: MediaBackend;
|
||||
|
||||
switch (config.media.backend as MediaBackendType) {
|
||||
case MediaBackendType.Local:
|
||||
mediaManager = new LocalMediaBackend(config);
|
||||
break;
|
||||
case MediaBackendType.S3:
|
||||
mediaManager = new S3MediaBackend(config);
|
||||
break;
|
||||
default:
|
||||
// TODO: Replace with logger
|
||||
throw new Error("Invalid media backend");
|
||||
}
|
||||
const mediaManager = await MediaBackend.fromBackendType(
|
||||
config.media.backend,
|
||||
config,
|
||||
);
|
||||
|
||||
if (thumbnail) {
|
||||
const { path } = await mediaManager.addFile(thumbnail);
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ import { zValidator } from "@hono/zod-validator";
|
|||
import { encode } from "blurhash";
|
||||
import { config } from "config-manager";
|
||||
import type { Hono } from "hono";
|
||||
import { MediaBackendType } from "media-manager";
|
||||
import type { MediaBackend } from "media-manager";
|
||||
import { LocalMediaBackend, S3MediaBackend } from "media-manager";
|
||||
import { MediaBackend } from "media-manager";
|
||||
import sharp from "sharp";
|
||||
import { z } from "zod";
|
||||
import { getUrl } from "~/database/entities/attachment";
|
||||
|
|
@ -101,19 +99,10 @@ export default (app: Hono) =>
|
|||
|
||||
let url = "";
|
||||
|
||||
let mediaManager: MediaBackend;
|
||||
|
||||
switch (config.media.backend as MediaBackendType) {
|
||||
case MediaBackendType.Local:
|
||||
mediaManager = new LocalMediaBackend(config);
|
||||
break;
|
||||
case MediaBackendType.S3:
|
||||
mediaManager = new S3MediaBackend(config);
|
||||
break;
|
||||
default:
|
||||
// TODO: Replace with logger
|
||||
throw new Error("Invalid media backend");
|
||||
}
|
||||
const mediaManager = await MediaBackend.fromBackendType(
|
||||
config.media.backend,
|
||||
config,
|
||||
);
|
||||
|
||||
const { path } = await mediaManager.addFile(file);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import type { Hono } from "hono";
|
|||
import ISO6391 from "iso-639-1";
|
||||
import { z } from "zod";
|
||||
import { undoFederationRequest } from "~/database/entities/federation";
|
||||
import { db } from "~/drizzle/db";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Attachment } from "~/packages/database-interface/attachment";
|
||||
import { Note } from "~/packages/database-interface/note";
|
||||
|
||||
export const meta = applyConfig({
|
||||
|
|
@ -40,43 +40,58 @@ export const schemas = {
|
|||
param: z.object({
|
||||
id: z.string().regex(idValidator),
|
||||
}),
|
||||
form: z.object({
|
||||
status: z.string().max(config.validation.max_note_size).optional(),
|
||||
content_type: z.string().optional().default("text/plain"),
|
||||
media_ids: z
|
||||
.array(z.string().regex(idValidator))
|
||||
.max(config.validation.max_media_attachments)
|
||||
.optional(),
|
||||
spoiler_text: z.string().max(255).optional(),
|
||||
sensitive: z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
language: z
|
||||
.enum(ISO6391.getAllCodes() as [string, ...string[]])
|
||||
.optional(),
|
||||
"poll[options]": z
|
||||
.array(z.string().max(config.validation.max_poll_option_size))
|
||||
.max(config.validation.max_poll_options)
|
||||
.optional(),
|
||||
"poll[expires_in]": z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(config.validation.min_poll_duration)
|
||||
.max(config.validation.max_poll_duration)
|
||||
.optional(),
|
||||
"poll[multiple]": z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
"poll[hide_totals]": z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
}),
|
||||
form: z
|
||||
.object({
|
||||
status: z
|
||||
.string()
|
||||
.max(config.validation.max_note_size)
|
||||
.refine(
|
||||
(s) =>
|
||||
!config.filters.note_content.some((filter) =>
|
||||
s.match(filter),
|
||||
),
|
||||
"Status contains blocked words",
|
||||
)
|
||||
.optional(),
|
||||
content_type: z.string().optional().default("text/plain"),
|
||||
media_ids: z
|
||||
.array(z.string().regex(idValidator))
|
||||
.max(config.validation.max_media_attachments)
|
||||
.default([]),
|
||||
spoiler_text: z.string().max(255).optional(),
|
||||
sensitive: z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
language: z
|
||||
.enum(ISO6391.getAllCodes() as [string, ...string[]])
|
||||
.optional(),
|
||||
"poll[options]": z
|
||||
.array(z.string().max(config.validation.max_poll_option_size))
|
||||
.max(config.validation.max_poll_options)
|
||||
.optional(),
|
||||
"poll[expires_in]": z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(config.validation.min_poll_duration)
|
||||
.max(config.validation.max_poll_duration)
|
||||
.optional(),
|
||||
"poll[multiple]": z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
"poll[hide_totals]": z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
})
|
||||
.refine(
|
||||
(obj) => !(obj.media_ids.length > 0 && obj["poll[options]"]),
|
||||
"Cannot attach poll to media",
|
||||
),
|
||||
};
|
||||
|
||||
export default (app: Hono) =>
|
||||
|
|
@ -91,91 +106,65 @@ export default (app: Hono) =>
|
|||
const { id } = context.req.valid("param");
|
||||
const { user } = context.req.valid("header");
|
||||
|
||||
const foundStatus = await Note.fromId(id, user?.id);
|
||||
|
||||
if (!foundStatus?.isViewableByUser(user)) {
|
||||
return errorResponse("Record not found", 404);
|
||||
}
|
||||
|
||||
if (context.req.method === "GET") {
|
||||
return jsonResponse(await foundStatus.toApi(user));
|
||||
}
|
||||
if (context.req.method === "DELETE") {
|
||||
if (foundStatus.author.id !== user?.id) {
|
||||
return errorResponse("Unauthorized", 401);
|
||||
}
|
||||
|
||||
// TODO: Delete and redraft
|
||||
|
||||
await foundStatus.delete();
|
||||
|
||||
await user.federateToFollowers(
|
||||
undoFederationRequest(user, foundStatus.getUri()),
|
||||
);
|
||||
|
||||
return jsonResponse(await foundStatus.toApi(user), 200);
|
||||
}
|
||||
|
||||
// TODO: Polls
|
||||
const {
|
||||
status: statusText,
|
||||
content_type,
|
||||
"poll[options]": options,
|
||||
media_ids,
|
||||
spoiler_text,
|
||||
sensitive,
|
||||
} = context.req.valid("form");
|
||||
|
||||
if (!(statusText || (media_ids && media_ids.length > 0))) {
|
||||
return errorResponse(
|
||||
"Status is required unless media is attached",
|
||||
422,
|
||||
);
|
||||
const note = await Note.fromId(id, user?.id);
|
||||
|
||||
if (!note?.isViewableByUser(user)) {
|
||||
return errorResponse("Record not found", 404);
|
||||
}
|
||||
|
||||
if (media_ids && media_ids.length > 0 && options) {
|
||||
return errorResponse(
|
||||
"Cannot attach poll to post with media",
|
||||
422,
|
||||
);
|
||||
}
|
||||
switch (context.req.method) {
|
||||
case "GET": {
|
||||
return jsonResponse(await note.toApi(user));
|
||||
}
|
||||
case "DELETE": {
|
||||
if (note.author.id !== user?.id) {
|
||||
return errorResponse("Unauthorized", 401);
|
||||
}
|
||||
|
||||
if (
|
||||
config.filters.note_content.some((filter) =>
|
||||
statusText?.match(filter),
|
||||
)
|
||||
) {
|
||||
return errorResponse("Status contains blocked words", 422);
|
||||
}
|
||||
// TODO: Delete and redraft
|
||||
|
||||
if (media_ids && media_ids.length > 0) {
|
||||
const foundAttachments = await db.query.Attachments.findMany({
|
||||
where: (attachment, { inArray }) =>
|
||||
inArray(attachment.id, media_ids),
|
||||
});
|
||||
await note.delete();
|
||||
|
||||
if (foundAttachments.length !== (media_ids ?? []).length) {
|
||||
return errorResponse("Invalid media IDs", 422);
|
||||
await user.federateToFollowers(
|
||||
undoFederationRequest(user, note.getUri()),
|
||||
);
|
||||
|
||||
return jsonResponse(await note.toApi(user), 200);
|
||||
}
|
||||
case "PUT": {
|
||||
if (media_ids.length > 0) {
|
||||
const foundAttachments =
|
||||
await Attachment.fromIds(media_ids);
|
||||
|
||||
if (foundAttachments.length !== media_ids.length) {
|
||||
return errorResponse("Invalid media IDs", 422);
|
||||
}
|
||||
}
|
||||
|
||||
const newNote = await note.updateFromData({
|
||||
content: statusText
|
||||
? {
|
||||
[content_type]: {
|
||||
content: statusText,
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
isSensitive: sensitive,
|
||||
spoilerText: spoiler_text,
|
||||
mediaAttachments: media_ids,
|
||||
});
|
||||
|
||||
return jsonResponse(await newNote.toApi(user));
|
||||
}
|
||||
}
|
||||
|
||||
const newNote = await foundStatus.updateFromData({
|
||||
content: statusText
|
||||
? {
|
||||
[content_type]: {
|
||||
content: statusText,
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
isSensitive: sensitive,
|
||||
spoilerText: spoiler_text,
|
||||
mediaAttachments: media_ids,
|
||||
});
|
||||
|
||||
if (!newNote) {
|
||||
return errorResponse("Failed to update status", 500);
|
||||
}
|
||||
|
||||
return jsonResponse(await newNote.toApi(user));
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ describe(meta.route, () => {
|
|||
const response = await sendTestRequest(
|
||||
new Request(new URL(meta.route, config.http.base_url), {
|
||||
method: "POST",
|
||||
body: new URLSearchParams(),
|
||||
body: new URLSearchParams({
|
||||
status: "Hello, world!",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import type { Hono } from "hono";
|
|||
import ISO6391 from "iso-639-1";
|
||||
import { z } from "zod";
|
||||
import { federateNote } from "~/database/entities/status";
|
||||
import { db } from "~/drizzle/db";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Attachment } from "~/packages/database-interface/attachment";
|
||||
import { Note } from "~/packages/database-interface/note";
|
||||
|
||||
export const meta = applyConfig({
|
||||
|
|
@ -26,61 +26,81 @@ export const meta = applyConfig({
|
|||
});
|
||||
|
||||
export const schemas = {
|
||||
form: z.object({
|
||||
status: z
|
||||
.string()
|
||||
.max(config.validation.max_note_size)
|
||||
.trim()
|
||||
.optional(),
|
||||
// TODO: Add regex to validate
|
||||
content_type: z.string().optional().default("text/plain"),
|
||||
media_ids: z
|
||||
.array(z.string().uuid())
|
||||
.max(config.validation.max_media_attachments)
|
||||
.optional(),
|
||||
spoiler_text: z.string().max(255).trim().optional(),
|
||||
sensitive: z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
language: z
|
||||
.enum(ISO6391.getAllCodes() as [string, ...string[]])
|
||||
.optional(),
|
||||
"poll[options]": z
|
||||
.array(z.string().max(config.validation.max_poll_option_size))
|
||||
.max(config.validation.max_poll_options)
|
||||
.optional(),
|
||||
"poll[expires_in]": z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(config.validation.min_poll_duration)
|
||||
.max(config.validation.max_poll_duration)
|
||||
.optional(),
|
||||
"poll[multiple]": z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
"poll[hide_totals]": z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
in_reply_to_id: z.string().uuid().optional().nullable(),
|
||||
quote_id: z.string().uuid().optional().nullable(),
|
||||
visibility: z
|
||||
.enum(["public", "unlisted", "private", "direct"])
|
||||
.optional()
|
||||
.default("public"),
|
||||
scheduled_at: z.string().optional().nullable(),
|
||||
local_only: z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional()
|
||||
.default(false),
|
||||
}),
|
||||
form: z
|
||||
.object({
|
||||
status: z
|
||||
.string()
|
||||
.max(config.validation.max_note_size)
|
||||
.trim()
|
||||
.refine(
|
||||
(s) =>
|
||||
!config.filters.note_content.some((filter) =>
|
||||
s.match(filter),
|
||||
),
|
||||
"Status contains blocked words",
|
||||
)
|
||||
.optional(),
|
||||
// TODO: Add regex to validate
|
||||
content_type: z.string().optional().default("text/plain"),
|
||||
media_ids: z
|
||||
.array(z.string().uuid())
|
||||
.max(config.validation.max_media_attachments)
|
||||
.default([]),
|
||||
spoiler_text: z.string().max(255).trim().optional(),
|
||||
sensitive: z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
language: z
|
||||
.enum(ISO6391.getAllCodes() as [string, ...string[]])
|
||||
.optional(),
|
||||
"poll[options]": z
|
||||
.array(z.string().max(config.validation.max_poll_option_size))
|
||||
.max(config.validation.max_poll_options)
|
||||
.optional(),
|
||||
"poll[expires_in]": z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.min(config.validation.min_poll_duration)
|
||||
.max(config.validation.max_poll_duration)
|
||||
.optional(),
|
||||
"poll[multiple]": z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
"poll[hide_totals]": z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional(),
|
||||
in_reply_to_id: z.string().uuid().optional().nullable(),
|
||||
quote_id: z.string().uuid().optional().nullable(),
|
||||
visibility: z
|
||||
.enum(["public", "unlisted", "private", "direct"])
|
||||
.optional()
|
||||
.default("public"),
|
||||
scheduled_at: z.coerce
|
||||
.date()
|
||||
.min(new Date(), "Scheduled time must be in the future")
|
||||
.optional()
|
||||
.nullable(),
|
||||
local_only: z
|
||||
.string()
|
||||
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
|
||||
.or(z.boolean())
|
||||
.optional()
|
||||
.default(false),
|
||||
})
|
||||
.refine(
|
||||
(obj) => obj.status || obj.media_ids.length > 0,
|
||||
"Status is required unless media is attached",
|
||||
)
|
||||
.refine(
|
||||
(obj) => !(obj.media_ids.length > 0 && obj["poll[options]"]),
|
||||
"Cannot attach poll to media",
|
||||
),
|
||||
};
|
||||
|
||||
export default (app: Hono) =>
|
||||
|
|
@ -100,10 +120,8 @@ export default (app: Hono) =>
|
|||
const {
|
||||
status,
|
||||
media_ids,
|
||||
"poll[options]": options,
|
||||
in_reply_to_id,
|
||||
quote_id,
|
||||
scheduled_at,
|
||||
sensitive,
|
||||
spoiler_text,
|
||||
visibility,
|
||||
|
|
@ -111,68 +129,22 @@ export default (app: Hono) =>
|
|||
local_only,
|
||||
} = context.req.valid("form");
|
||||
|
||||
// Validate status
|
||||
if (!(status || (media_ids && media_ids.length > 0))) {
|
||||
return errorResponse(
|
||||
"Status is required unless media is attached",
|
||||
422,
|
||||
);
|
||||
}
|
||||
|
||||
if (media_ids && media_ids.length > 0 && options) {
|
||||
// Disallow poll
|
||||
return errorResponse("Cannot attach poll to media", 422);
|
||||
}
|
||||
|
||||
if (scheduled_at) {
|
||||
if (
|
||||
Number.isNaN(new Date(scheduled_at).getTime()) ||
|
||||
new Date(scheduled_at).getTime() < Date.now()
|
||||
) {
|
||||
return errorResponse(
|
||||
"Scheduled time must be in the future",
|
||||
422,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if status body doesnt match filters
|
||||
if (
|
||||
config.filters.note_content.some((filter) =>
|
||||
status?.match(filter),
|
||||
)
|
||||
) {
|
||||
return errorResponse("Status contains blocked words", 422);
|
||||
}
|
||||
|
||||
// Check if media attachments are all valid
|
||||
if (media_ids && media_ids.length > 0) {
|
||||
const foundAttachments = await db.query.Attachments.findMany({
|
||||
where: (attachment, { inArray }) =>
|
||||
inArray(attachment.id, media_ids),
|
||||
}).catch(() => []);
|
||||
if (media_ids.length > 0) {
|
||||
const foundAttachments = await Attachment.fromIds(media_ids);
|
||||
|
||||
if (foundAttachments.length !== (media_ids ?? []).length) {
|
||||
if (foundAttachments.length !== media_ids.length) {
|
||||
return errorResponse("Invalid media IDs", 422);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that in_reply_to_id and quote_id are real posts if provided
|
||||
if (in_reply_to_id) {
|
||||
const foundReply = await Note.fromId(in_reply_to_id);
|
||||
if (!foundReply) {
|
||||
return errorResponse(
|
||||
"Invalid in_reply_to_id (not found)",
|
||||
422,
|
||||
);
|
||||
}
|
||||
if (in_reply_to_id && !(await Note.fromId(in_reply_to_id))) {
|
||||
return errorResponse("Invalid in_reply_to_id (not found)", 422);
|
||||
}
|
||||
|
||||
if (quote_id) {
|
||||
const foundQuote = await Note.fromId(quote_id);
|
||||
if (!foundQuote) {
|
||||
return errorResponse("Invalid quote_id (not found)", 422);
|
||||
}
|
||||
if (quote_id && !(await Note.fromId(quote_id))) {
|
||||
return errorResponse("Invalid quote_id (not found)", 422);
|
||||
}
|
||||
|
||||
const newNote = await Note.fromData({
|
||||
|
|
@ -191,10 +163,6 @@ export default (app: Hono) =>
|
|||
application: application ?? undefined,
|
||||
});
|
||||
|
||||
if (!newNote) {
|
||||
return errorResponse("Failed to create status", 500);
|
||||
}
|
||||
|
||||
if (!local_only) {
|
||||
await federateNote(newNote);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ import { zValidator } from "@hono/zod-validator";
|
|||
import { encode } from "blurhash";
|
||||
import { config } from "config-manager";
|
||||
import type { Hono } from "hono";
|
||||
import type { MediaBackend } from "media-manager";
|
||||
import { MediaBackendType } from "media-manager";
|
||||
import { LocalMediaBackend, S3MediaBackend } from "media-manager";
|
||||
import { MediaBackend } from "media-manager";
|
||||
import sharp from "sharp";
|
||||
import { z } from "zod";
|
||||
import { getUrl } from "~/database/entities/attachment";
|
||||
|
|
@ -101,19 +99,10 @@ export default (app: Hono) =>
|
|||
|
||||
let url = "";
|
||||
|
||||
let mediaManager: MediaBackend;
|
||||
|
||||
switch (config.media.backend as MediaBackendType) {
|
||||
case MediaBackendType.Local:
|
||||
mediaManager = new LocalMediaBackend(config);
|
||||
break;
|
||||
case MediaBackendType.S3:
|
||||
mediaManager = new S3MediaBackend(config);
|
||||
break;
|
||||
default:
|
||||
// TODO: Replace with logger
|
||||
throw new Error("Invalid media backend");
|
||||
}
|
||||
const mediaManager = await MediaBackend.fromBackendType(
|
||||
config.media.backend,
|
||||
config,
|
||||
);
|
||||
|
||||
const { path } = await mediaManager.addFile(file);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue