♻️ refactor: align update-thumbnail and bulk-insert-video with latest Elysia standards

This commit is contained in:
2026-03-08 07:31:38 +07:00
parent 5a4e4d04a4
commit 9f47f8f298
6 changed files with 124 additions and 66 deletions

View File

@ -1,19 +1,8 @@
import { Context } from "elysia"; import { Context, Static } from "elysia";
import { mainErrorHandler } from "../../../helpers/error/handler"; import { mainErrorHandler } from "../../../helpers/error/handler";
import { bulkInsertVideoService } from "../services/http/bulkInsertVideo.service"; import { bulkInsertVideoService } from "../services/http/bulkInsertVideo.service";
import { returnWriteResponse } from "../../../helpers/callback/httpResponse"; import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
import { bulkInsertVideoSchema } from "../schemas/bulkInsertVideo.schema";
export interface BulkInsertVideoBodyRequest {
media_id: string;
data: Array<{
episode: number;
videos: Array<{
service_id: string;
video_code: string;
thumbnail_code?: string;
}>;
}>;
}
/** /**
* @function bulkInsertVideoController * @function bulkInsertVideoController
@ -76,12 +65,13 @@ export interface BulkInsertVideoBodyRequest {
* error: { ...errorDetails } // Additional error details if available and the env run on development mode * error: { ...errorDetails } // Additional error details if available and the env run on development mode
* } * }
*/ */
export const bulkInsertVideoController = async ( export const bulkInsertVideoController = async (ctx: {
ctx: Context & { body: BulkInsertVideoBodyRequest }, set: Context["set"];
) => { body: Static<typeof bulkInsertVideoSchema.body>;
}) => {
try { try {
const insertedVideos = await bulkInsertVideoService(ctx.body); const insertedVideos = await bulkInsertVideoService(ctx.body);
return returnWriteResponse(ctx.set, 201, "Videos inserted", insertedVideos); return returnWriteResponse(ctx.set, 201, "Videos inserted successfully", insertedVideos);
} catch (error) { } catch (error) {
throw mainErrorHandler(ctx.set, error); throw mainErrorHandler(ctx.set, error);
} }

View File

@ -1,55 +1,24 @@
import { Context } from "elysia"; import { Context, Static } from "elysia";
import { mainErrorHandler } from "../../../helpers/error/handler"; import { mainErrorHandler } from "../../../helpers/error/handler";
import { returnWriteResponse } from "../../../helpers/callback/httpResponse"; import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
import { updateAllEpisodeThumbnailService } from "../services/http/updateAllEpisodeThumbnail.service"; import { updateAllEpisodeThumbnailService } from "../services/http/updateAllEpisodeThumbnail.service";
import { updateAllEpisodeThumbnailSchema } from "../schemas/updateAllEpisodeThumbnail.schema";
/** /**
* @function updateAllEpisodeThumbnailController * Updating all episode thumbnails for a specific target service reference ID.
* @description Controller to handle the bulk updating of episode thumbnails for all episodes associated with a specific service reference ID.
* *
* @param {Context & { body: { service_reference_id: string } }} ctx * This controller handles the bulk update of episode thumbnails for all episodes associated with a specific service reference ID.
* The context object containing the request body. * It fetches the latest thumbnail data from external sources and updates the existing episode records in the database accordingly.
* The body must include:
* - service_reference_id: string - The ID of the service to which the episodes belong.
* *
* @example * See OpenAPI documentation for request/response schema.
* Request route: PUT /internal/episode/update-thumbnails
* Request body:
* {
* "service_reference_id": "019c0df6-f8fe-7565-82cd-9c29b20232ab"
* },
*
* @returns {Promise<Object>}
* A response object indicating success or failure.
* Return example:
* {
* success: true,
* status: 204,
* message: "Updating {newEpisodeThumbnailsCount} episode thumbnails successfully.",
* }
*
* @throws {Object}
* An error response object if validation fails or an error occurs during bulk insert operation.
* Return example:
* {
* success: false,
* status: <Status Code>,
* message: "<Error Message>",
* error: { ...errorDetails } // Additional error details if available and the env run on development mode
* }
*/ */
export const updateAllEpisodeThumbnailController = async ( export const updateAllEpisodeThumbnailController = async (ctx: {
ctx: Context & { body: { service_reference_id?: string } }, set: Context["set"];
) => { body: Static<typeof updateAllEpisodeThumbnailSchema.body>;
}) => {
try { try {
const newEpisodeThumbnailsCount = await updateAllEpisodeThumbnailService( const newEpisodeThumbnailsCount = await updateAllEpisodeThumbnailService(ctx.body.service_reference_id);
ctx.body.service_reference_id, return returnWriteResponse(ctx.set, 204, `Updating ${newEpisodeThumbnailsCount} episode thumbnails successfully.`);
);
return returnWriteResponse(
ctx.set,
204,
`Updating ${newEpisodeThumbnailsCount} episode thumbnails successfully.`,
);
} catch (error) { } catch (error) {
return mainErrorHandler(ctx.set, error); return mainErrorHandler(ctx.set, error);
} }

View File

@ -8,6 +8,8 @@ import { purgeUnusedSessionController } from "./controllers/purgeUnusedSession.c
import { createHeroBannerController } from "./controllers/createHeroBanner.controller"; import { createHeroBannerController } from "./controllers/createHeroBanner.controller";
import { bulkInsertMediaSchema } from "./schemas/bulkInsertMedia.schema"; import { bulkInsertMediaSchema } from "./schemas/bulkInsertMedia.schema";
import { bulkInsertEpisodeSchema } from "./schemas/bulkInsertEpisode.schema"; import { bulkInsertEpisodeSchema } from "./schemas/bulkInsertEpisode.schema";
import { updateAllEpisodeThumbnailSchema } from "./schemas/updateAllEpisodeThumbnail.schema";
import { bulkInsertVideoSchema } from "./schemas/bulkInsertVideo.schema";
export const internalModule = new Elysia({ export const internalModule = new Elysia({
prefix: "/internal", prefix: "/internal",
@ -15,8 +17,8 @@ export const internalModule = new Elysia({
}) })
.post("/media/bulk-insert", bulkInsertMediaController, bulkInsertMediaSchema) .post("/media/bulk-insert", bulkInsertMediaController, bulkInsertMediaSchema)
.post("/episode/bulk-insert", bulkInsertEpisodeController, bulkInsertEpisodeSchema) .post("/episode/bulk-insert", bulkInsertEpisodeController, bulkInsertEpisodeSchema)
.put("/episode/update-thumbnails", updateAllEpisodeThumbnailController) .put("/episode/update-thumbnails", updateAllEpisodeThumbnailController, updateAllEpisodeThumbnailSchema)
.post("/video/bulk-insert", bulkInsertVideoController) .post("/video/bulk-insert", bulkInsertVideoController, bulkInsertVideoSchema)
.post("/video-service", createVideoServiceInternalController) .post("/video-service", createVideoServiceInternalController)
.post("/user-session/purge-unused", purgeUnusedSessionController) .post("/user-session/purge-unused", purgeUnusedSessionController)
.post("/hero-banner", createHeroBannerController); .post("/hero-banner", createHeroBannerController);

View File

@ -0,0 +1,63 @@
import { t } from "elysia";
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
export const bulkInsertVideoSchema = {
body: t.Object({
media_id: t.String({
description: "The ID of the media for which episodes will be inserted",
}),
data: t.Array(
t.Object({
episode: t.Number({
description: "The episode number",
}),
videos: t.Array(
t.Object({
service_id: t.String({
description: "The ID of the video service",
}),
video_code: t.String({
description: "The code of the video on the service",
}),
thumbnail_code: t.Optional(
t.String({
description: "The code of the thumbnail for the video on the service",
}),
),
}),
),
}),
),
}),
detail: {
summary: "Bulk insert videos for a media episode",
description:
"Perform bulk insert of videos for specific episodes of a media. This operation inserts multiple videos associated with different episodes into the database based on the provided data.",
responses: {
201: {
description: "Videos inserted successfully",
content: {
"application/json": {
schema: {
type: "object",
properties: {
success: { type: "boolean", default: true },
status: { type: "integer", default: 201 },
message: { type: "string", default: "Videos inserted successfully" },
data: {
type: "array",
default: ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],
description: "An array of IDs of the inserted videos",
items: {
type: "string",
description: "The ID of the inserted video",
},
},
},
},
},
},
},
},
},
} satisfies AppRouteSchema;

View File

@ -0,0 +1,35 @@
import { t } from "elysia";
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
export const updateAllEpisodeThumbnailSchema = {
body: t.Object({
service_reference_id: t.String({
description: "The ID of the service to which the target of episode thumbnails belong",
}),
}),
detail: {
summary: "Bulk update episode thumbnails",
description:
"Perform bulk update of episode thumbnails for all episodes associated with a specific service reference ID. This operation fetches the latest thumbnail data from external sources and updates the existing episode records in the database accordingly.",
responses: {
204: {
description: "Updating episode thumbnails operation completed successfully",
content: {
"application/json": {
schema: {
type: "object",
properties: {
success: { type: "boolean", default: true },
status: { type: "integer", default: 204 },
message: {
type: "string",
default: "Updating {newEpisodeThumbnailsCount} episode thumbnails operation completed successfully",
},
},
},
},
},
},
},
},
} satisfies AppRouteSchema;

View File

@ -1,12 +1,11 @@
import { SystemAccountId } from "../../../../config/account/system"; import { SystemAccountId } from "../../../../config/account/system";
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder"; import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
import { BulkInsertVideoBodyRequest } from "../../controllers/bulkInsertVideo.controller";
import { findEpisodeWithMediaIdRepository } from "../../repositories/findEpisodeWithMediaId.repository"; import { findEpisodeWithMediaIdRepository } from "../../repositories/findEpisodeWithMediaId.repository";
import { bulkInsertVideoRepository } from "../../repositories/bulkInsertVideo.repository"; import { bulkInsertVideoRepository } from "../../repositories/bulkInsertVideo.repository";
import { Static } from "elysia";
import { bulkInsertVideoSchema } from "../../schemas/bulkInsertVideo.schema";
export const bulkInsertVideoService = async ( export const bulkInsertVideoService = async (body: Static<typeof bulkInsertVideoSchema.body>) => {
body: BulkInsertVideoBodyRequest,
) => {
try { try {
const insertedVideos: string[] = []; const insertedVideos: string[] = [];
for (const episodeData of body.data) { for (const episodeData of body.data) {