From 5a4e4d04a4ecc0474d7d930dde4ea0004e2c2074 Mon Sep 17 00:00:00 2001 From: Rafi Arrafif Date: Sat, 7 Mar 2026 14:57:16 +0700 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20align=20bulk-i?= =?UTF-8?q?nsert=20implementation=20with=20latest=20Elysia=20standards?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierrc | 3 +- .../bulkInsertEpisode.controller.ts | 63 +++------------- .../controllers/bulkInsertMedia.controller.ts | 1 - src/modules/internal/index.ts | 3 +- .../schemas/bulkInsertEpisode.schema.ts | 73 +++++++++++++++++++ .../schemas/bulkInsertMedia.schema.ts | 7 -- 6 files changed, 89 insertions(+), 61 deletions(-) create mode 100644 src/modules/internal/schemas/bulkInsertEpisode.schema.ts diff --git a/.prettierrc b/.prettierrc index 2340e06..9693eed 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,3 +1,4 @@ { - "parser": "typescript" + "parser": "typescript", + "printWidth": 120 } diff --git a/src/modules/internal/controllers/bulkInsertEpisode.controller.ts b/src/modules/internal/controllers/bulkInsertEpisode.controller.ts index 6d450dd..5fdc2bb 100644 --- a/src/modules/internal/controllers/bulkInsertEpisode.controller.ts +++ b/src/modules/internal/controllers/bulkInsertEpisode.controller.ts @@ -1,62 +1,23 @@ -import { Context } from "elysia"; +import { Context, Static } from "elysia"; import { mainErrorHandler } from "../../../helpers/error/handler"; import { bulkInsertEpisodeService } from "../services/http/bulkInsertEpisode.service"; import { returnWriteResponse } from "../../../helpers/callback/httpResponse"; +import { bulkInsertEpisodeSchema } from "../schemas/bulkInsertEpisode.schema"; /** - * @function bulkInsertMediaController - * @description Perform bulk insert of episodes for a specific media. This operation fetches episode data from external sources and inserts them into the database. The page parameter is optional; if not provided, the first page of episodes will be fetched. + * Perform bulk insert of episodes for a specific media. + * This operation fetches episode data from external sources and inserts them into the database. * - * @param {Context & { body: { media_mal_id: number }; query: { page?: number } }} ctx - * The context object containing the request body. - * The body must include: - * - media_mal_id: number - The MyAnimeList ID of the media for which episodes will be inserted. - * The query may include: - * - page?: number - (Optional) The page number of episodes to fetch and insert. If not provided, defaults to the first page. - * - * @example - * Request route: POST /internal/episode/bulk-insert - * Request body: - * { - * "media_mal_id": 12345 - * } - * Query parameter: - * ?page=2 (Optional, specifies the page number of episodes to fetch and insert) - * - * @returns {Promise} - * A response object indicating success or failure. - * Return example: - * { - * success: true, - * status: 201, - * message: "Bulk insert episode operation completed successfully", - * data: { ...bulkInsertResult } // Data returned only if the env run on development mode - * } - * - * @throws {Object} - * An error response object if validation fails or an error occurs during bulk insert operation. - * Return example: - * { - * success: false, - * status: , - * message: "", - * error: { ...errorDetails } // Additional error details if available and the env run on development mode - * } + * See OpenAPI documentation for request/response schema. */ -export const bulkInsertEpisodeController = async ( - ctx: Context & { body: { media_mal_id: number }; query: { page?: number } }, -) => { +export const bulkInsertEpisodeController = async (ctx: { + set: Context["set"]; + body: Static; + query: Static; +}) => { try { - const bulkInsertResult = await bulkInsertEpisodeService( - ctx.body.media_mal_id, - ctx.query.page, - ); - return returnWriteResponse( - ctx.set, - 201, - "Bulk insert episode operation completed successfully", - bulkInsertResult, - ); + const bulkInsertResult = await bulkInsertEpisodeService(ctx.body.media_mal_id, ctx.query.page); + return returnWriteResponse(ctx.set, 201, "Bulk insert episode operation completed successfully", bulkInsertResult); } catch (err) { return mainErrorHandler(ctx.set, err); } diff --git a/src/modules/internal/controllers/bulkInsertMedia.controller.ts b/src/modules/internal/controllers/bulkInsertMedia.controller.ts index 54a79fc..ef067b2 100644 --- a/src/modules/internal/controllers/bulkInsertMedia.controller.ts +++ b/src/modules/internal/controllers/bulkInsertMedia.controller.ts @@ -15,7 +15,6 @@ import { bulkInsertMediaSchema } from "../schemas/bulkInsertMedia.schema"; export const bulkInsertMediaController = async (ctx: { set: Context["set"]; body: Static; - query: Static; }) => { try { const bulkInsertResult = await bulkInsertAnimeService(ctx.body.mal_id); diff --git a/src/modules/internal/index.ts b/src/modules/internal/index.ts index 31e6687..59ce26a 100644 --- a/src/modules/internal/index.ts +++ b/src/modules/internal/index.ts @@ -7,13 +7,14 @@ import { updateAllEpisodeThumbnailController } from "./controllers/updateAllEpis import { purgeUnusedSessionController } from "./controllers/purgeUnusedSession.controller"; import { createHeroBannerController } from "./controllers/createHeroBanner.controller"; import { bulkInsertMediaSchema } from "./schemas/bulkInsertMedia.schema"; +import { bulkInsertEpisodeSchema } from "./schemas/bulkInsertEpisode.schema"; export const internalModule = new Elysia({ prefix: "/internal", tags: ["Internal"], }) .post("/media/bulk-insert", bulkInsertMediaController, bulkInsertMediaSchema) - .post("/episode/bulk-insert", bulkInsertEpisodeController) + .post("/episode/bulk-insert", bulkInsertEpisodeController, bulkInsertEpisodeSchema) .put("/episode/update-thumbnails", updateAllEpisodeThumbnailController) .post("/video/bulk-insert", bulkInsertVideoController) .post("/video-service", createVideoServiceInternalController) diff --git a/src/modules/internal/schemas/bulkInsertEpisode.schema.ts b/src/modules/internal/schemas/bulkInsertEpisode.schema.ts new file mode 100644 index 0000000..a8947b1 --- /dev/null +++ b/src/modules/internal/schemas/bulkInsertEpisode.schema.ts @@ -0,0 +1,73 @@ +import { t } from "elysia"; +import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema"; + +export const bulkInsertEpisodeSchema = { + body: t.Object({ + media_mal_id: t.Number({ + description: "The MyAnimeList ID of the media for which episodes will be inserted", + }), + }), + query: t.Object({ + page: t.Optional( + t.Number({ + description: "Episode page number to fetch", + }), + ), + }), + detail: { + summary: "Bulk insert episodes for a media", + description: + "Perform bulk insert of episodes for a specific media. This operation fetches episode data from external sources and inserts them into the database. The page parameter is optional; if not provided, the first page of episodes will be fetched.", + responses: { + 201: { + description: + "Bulk insert episode operation completed successfully (Data returned only if the env run on development mode)", + content: { + "application/json": { + schema: { + type: "object", + properties: { + success: { type: "boolean", default: true }, + status: { type: "integer", default: 201 }, + message: { + type: "string", + default: "Bulk insert episode operation completed successfully", + }, + data: { + type: "object", + properties: { + pagination: { + type: "object", + properties: { + last_visible_page: { type: "integer", default: 1 }, + has_next_page: { type: "boolean", default: false }, + }, + }, + data: { + type: "array", + items: { + type: "object", + properties: { + mal_id: { type: "integer", default: 1 }, + url: { type: "string", default: "https://myanimelist.net/anime/1" }, + title: { type: "string", default: "Example Episode Title" }, + title_japanese: { type: "string", default: "例のエピソードタイトル" }, + title_romanji: { type: "string", default: "Rei no Episōdo Taitoru" }, + aired: { type: "string", format: "date-time", default: "2022-01-01T00:00:00.000Z" }, + score: { type: "number", default: 8.5 }, + filler: { type: "boolean", default: false }, + recap: { type: "boolean", default: false }, + forum_url: { type: "string", default: "https://myanimelist.net/forum/1" }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} satisfies AppRouteSchema; diff --git a/src/modules/internal/schemas/bulkInsertMedia.schema.ts b/src/modules/internal/schemas/bulkInsertMedia.schema.ts index 74cb8cd..5f46e99 100644 --- a/src/modules/internal/schemas/bulkInsertMedia.schema.ts +++ b/src/modules/internal/schemas/bulkInsertMedia.schema.ts @@ -8,13 +8,6 @@ export const bulkInsertMediaSchema = { "The MyAnimeList ID of the media for which episodes will be inserted", }), }), - query: t.Object({ - page: t.Optional( - t.Number({ - description: "Episode page number to fetch", - }), - ), - }), detail: { summary: "Bulk insert media", description: