♻️ refactor: add schema to all controllers in internal module
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
import { Context } from "elysia";
|
import { Context } from "elysia";
|
||||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||||
import { createHeroBannerService } from "../services/http/createHeroBanner.service";
|
import { createHeroBannerService } from "../services/http/createHeroBanner.service";
|
||||||
|
import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
|
||||||
|
|
||||||
export interface CreateHeroBannerRequestBody {
|
export interface CreateHeroBannerRequestBody {
|
||||||
isClickable?: boolean;
|
isClickable?: boolean;
|
||||||
@ -14,11 +15,10 @@ export interface CreateHeroBannerRequestBody {
|
|||||||
endDate: string;
|
endDate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createHeroBannerController = async (
|
export const createHeroBannerController = async (ctx: Context & { body: CreateHeroBannerRequestBody }) => {
|
||||||
ctx: Context & { body: CreateHeroBannerRequestBody },
|
|
||||||
) => {
|
|
||||||
try {
|
try {
|
||||||
return await createHeroBannerService(ctx.body);
|
const createdBanner = await createHeroBannerService(ctx.body);
|
||||||
|
return returnWriteResponse(ctx.set, 201, "Hero banner created successfully", createdBanner);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return mainErrorHandler(ctx.set, error);
|
return mainErrorHandler(ctx.set, error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,79 +1,26 @@
|
|||||||
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 { createVideoServiceInternalService } from "../services/http/createVideoService.service";
|
import { createVideoServiceInternalService } from "../services/http/createVideoService.service";
|
||||||
|
import { createVideoServiceInternalSchema } from "../schemas/createVideoServiceInternal.schema";
|
||||||
export interface CreateVideoServiceInternalBodyRequest {
|
|
||||||
name: string;
|
|
||||||
domain: string;
|
|
||||||
logo: string;
|
|
||||||
hexColor: string;
|
|
||||||
endpointVideo: string;
|
|
||||||
endpointThumbnail: string;
|
|
||||||
endpointDownload?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function createVideoServiceInternalController
|
* Controller for creating a new video service.
|
||||||
* @description Perform creation of a new video service. This operation adds a new video service to the database based on the provided data.
|
|
||||||
*
|
*
|
||||||
* @param {Context & { body: CreateVideoServiceInternalBodyRequest }} ctx
|
* This controller handles the HTTP request for creating a new video service.
|
||||||
* The context object containing the request body.
|
* It validates the incoming request body against the defined schema,
|
||||||
* The body must include:
|
* invokes the service layer to perform the creation logic,
|
||||||
* - name: string - The name of the video service.
|
* and returns an appropriate HTTP response based on the outcome of the operation.
|
||||||
* - domain: string - The domain of the video service.
|
|
||||||
* - logo: string - The logo URL of the video service.
|
|
||||||
* - hexColor: string - The hex color associated with the video service.
|
|
||||||
* - endpointVideo: string - The endpoint URL for video streaming.
|
|
||||||
* - endpointThumbnail: string - The endpoint URL for thumbnails.
|
|
||||||
* - endpointDownload?: string - (Optional) The endpoint URL for downloads.
|
|
||||||
*
|
*
|
||||||
* @example
|
* See OpenAPI documentation for request/response schema.
|
||||||
* Request route: POST /internal/video-service
|
|
||||||
* Request body:
|
|
||||||
* {
|
|
||||||
* "name": "Example Video Service",
|
|
||||||
* "domain": "example.com",
|
|
||||||
* "logo": "https://example.com/logo.png",
|
|
||||||
* "hexColor": "#FF5733",
|
|
||||||
* "endpointVideo": "https://api.example.com/videos",
|
|
||||||
* "endpointThumbnail": "https://api.example.com/thumbnails",
|
|
||||||
* "endpointDownload": "https://api.example.com/downloads"
|
|
||||||
* },
|
|
||||||
*
|
|
||||||
* @returns {Promise<Object>}
|
|
||||||
* A response object indicating success or failure.
|
|
||||||
* Return example:
|
|
||||||
* {
|
|
||||||
* success: true,
|
|
||||||
* status: 201,
|
|
||||||
* message: "Video service created",
|
|
||||||
* data: { ...createdVideoService } // 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: <Status Code>,
|
|
||||||
* message: "<Error Message>",
|
|
||||||
* error: { ...errorDetails } // Additional error details if available and the env run on development mode
|
|
||||||
* }
|
|
||||||
*/
|
*/
|
||||||
export const createVideoServiceInternalController = async (
|
export const createVideoServiceInternalController = async (ctx: {
|
||||||
ctx: Context & { body: CreateVideoServiceInternalBodyRequest },
|
set: Context["set"];
|
||||||
) => {
|
body: Static<typeof createVideoServiceInternalSchema.body>;
|
||||||
|
}) => {
|
||||||
try {
|
try {
|
||||||
const createdVideoService = await createVideoServiceInternalService(
|
const createdVideoService = await createVideoServiceInternalService(ctx.body);
|
||||||
ctx.body,
|
return returnWriteResponse(ctx.set, 201, "Video service created", createdVideoService);
|
||||||
);
|
|
||||||
return returnWriteResponse(
|
|
||||||
ctx.set,
|
|
||||||
201,
|
|
||||||
"Video service created",
|
|
||||||
createdVideoService,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw mainErrorHandler(ctx.set, error);
|
throw mainErrorHandler(ctx.set, error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,15 +3,18 @@ import { mainErrorHandler } from "../../../helpers/error/handler";
|
|||||||
import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
|
import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
|
||||||
import { purgeUnusedSessionService } from "../services/http/purgeUnusedSession.service";
|
import { purgeUnusedSessionService } from "../services/http/purgeUnusedSession.service";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller for purging unused user sessions
|
||||||
|
*
|
||||||
|
* This controller handles the HTTP request for purging all unused user sessions. It will delete all unused sessions from the database based on their authentication status and deleted status.
|
||||||
|
* The response will indicate the success of the operation and may include details about the number of sessions purged if the environment is running in development mode.
|
||||||
|
*
|
||||||
|
* See OpenAPI documentation for request/response schema.
|
||||||
|
*/
|
||||||
export const purgeUnusedSessionController = async (ctx: Context) => {
|
export const purgeUnusedSessionController = async (ctx: Context) => {
|
||||||
try {
|
try {
|
||||||
const result = await purgeUnusedSessionService();
|
const result = await purgeUnusedSessionService();
|
||||||
return returnWriteResponse(
|
return returnWriteResponse(ctx.set, 200, "Successfully purged all unused user sessions", result);
|
||||||
ctx.set,
|
|
||||||
200,
|
|
||||||
"Successfully purged all unused user sessions",
|
|
||||||
result,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return mainErrorHandler(ctx.set, error);
|
return mainErrorHandler(ctx.set, error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,9 @@ 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 { updateAllEpisodeThumbnailSchema } from "./schemas/updateAllEpisodeThumbnail.schema";
|
||||||
import { bulkInsertVideoSchema } from "./schemas/bulkInsertVideo.schema";
|
import { bulkInsertVideoSchema } from "./schemas/bulkInsertVideo.schema";
|
||||||
|
import { createVideoServiceInternalSchema } from "./schemas/createVideoServiceInternal.schema";
|
||||||
|
import { purgeUnusedSessionSchema } from "./schemas/purgeUnusedSession.schema";
|
||||||
|
import { createHeroBannerSchema } from "./schemas/createHeroBanner.schema";
|
||||||
|
|
||||||
export const internalModule = new Elysia({
|
export const internalModule = new Elysia({
|
||||||
prefix: "/internal",
|
prefix: "/internal",
|
||||||
@ -19,6 +22,6 @@ export const internalModule = new Elysia({
|
|||||||
.post("/episode/bulk-insert", bulkInsertEpisodeController, bulkInsertEpisodeSchema)
|
.post("/episode/bulk-insert", bulkInsertEpisodeController, bulkInsertEpisodeSchema)
|
||||||
.put("/episode/update-thumbnails", updateAllEpisodeThumbnailController, updateAllEpisodeThumbnailSchema)
|
.put("/episode/update-thumbnails", updateAllEpisodeThumbnailController, updateAllEpisodeThumbnailSchema)
|
||||||
.post("/video/bulk-insert", bulkInsertVideoController, bulkInsertVideoSchema)
|
.post("/video/bulk-insert", bulkInsertVideoController, bulkInsertVideoSchema)
|
||||||
.post("/video-service", createVideoServiceInternalController)
|
.post("/video-service", createVideoServiceInternalController, createVideoServiceInternalSchema)
|
||||||
.post("/user-session/purge-unused", purgeUnusedSessionController)
|
.post("/user-session/purge-unused", purgeUnusedSessionController, purgeUnusedSessionSchema)
|
||||||
.post("/hero-banner", createHeroBannerController);
|
.post("/hero-banner", createHeroBannerController, createHeroBannerSchema);
|
||||||
|
|||||||
107
src/modules/internal/schemas/createHeroBanner.schema.ts
Normal file
107
src/modules/internal/schemas/createHeroBanner.schema.ts
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import { t } from "elysia";
|
||||||
|
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||||
|
|
||||||
|
export const createHeroBannerSchema = {
|
||||||
|
body: t.Object({
|
||||||
|
isClickable: t.Optional(
|
||||||
|
t.Boolean({
|
||||||
|
description: "Indicates whether the hero banner is clickable",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
title: t.Optional(
|
||||||
|
t.String({
|
||||||
|
description: "The title of the hero banner",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
tags: t.Array(t.String(), {
|
||||||
|
description: "An array of tags associated with the hero banner",
|
||||||
|
}),
|
||||||
|
description: t.Optional(
|
||||||
|
t.String({
|
||||||
|
description: "A brief description of the hero banner",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
buttonContent: t.Optional(
|
||||||
|
t.String({
|
||||||
|
description: "The text content of the button on the hero banner",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
buttonLink: t.Optional(
|
||||||
|
t.String({
|
||||||
|
description: "The URL that the button on the hero banner links to",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
imageUrl: t.Optional(
|
||||||
|
t.String({
|
||||||
|
description: "The URL of the image used in the hero banner",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
startDate: t.String({
|
||||||
|
description: "The start date for the hero banner in ISO 8601 format",
|
||||||
|
}),
|
||||||
|
endDate: t.String({
|
||||||
|
description: "The end date for the hero banner in ISO 8601 format",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
detail: {
|
||||||
|
summary: "Create a new hero banner",
|
||||||
|
description:
|
||||||
|
"Perform creation of a new hero banner. This operation adds a new hero banner to the database based on the provided data.",
|
||||||
|
responses: {
|
||||||
|
201: {
|
||||||
|
description: "Hero banner created successfully",
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
success: { type: "boolean", default: true },
|
||||||
|
status: { type: "integer", default: 201 },
|
||||||
|
message: { type: "string", default: "Hero banner created successfully" },
|
||||||
|
data: {
|
||||||
|
type: "object",
|
||||||
|
description:
|
||||||
|
"The created hero banner object. This field is returned only if the environment is running in development mode.",
|
||||||
|
properties: {
|
||||||
|
id: { type: "string", description: "The ID of the created hero banner" },
|
||||||
|
isClickable: { type: "boolean", description: "Indicates whether the hero banner is clickable" },
|
||||||
|
title: { type: "string", description: "The title of the hero banner" },
|
||||||
|
tags: {
|
||||||
|
type: "array",
|
||||||
|
items: { type: "string" },
|
||||||
|
description: "An array of tags associated with the hero banner",
|
||||||
|
},
|
||||||
|
description: { type: "string", description: "A brief description of the hero banner" },
|
||||||
|
buttonContent: { type: "string", description: "The text content of the button on the hero banner" },
|
||||||
|
buttonLink: { type: "string", description: "The URL that the button on the hero banner links to" },
|
||||||
|
imageUrl: { type: "string", description: "The URL of the image used in the hero banner" },
|
||||||
|
startDate: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
description: "The start date for the hero banner in ISO 8601 format",
|
||||||
|
},
|
||||||
|
endDate: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
description: "The end date for the hero banner in ISO 8601 format",
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
description: "The timestamp when the hero banner was created",
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
description: "The timestamp when the hero banner was last updated",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies AppRouteSchema;
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
import { t } from "elysia";
|
||||||
|
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||||
|
|
||||||
|
export const createVideoServiceInternalSchema = {
|
||||||
|
body: t.Object({
|
||||||
|
name: t.String({
|
||||||
|
description: "The name of the video service",
|
||||||
|
}),
|
||||||
|
domain: t.String({
|
||||||
|
description: "The domain of the video service",
|
||||||
|
}),
|
||||||
|
logo: t.String({
|
||||||
|
description: "The logo URL of the video service",
|
||||||
|
}),
|
||||||
|
hexColor: t.String({
|
||||||
|
description: "The hex color associated with the video service",
|
||||||
|
}),
|
||||||
|
endpointVideo: t.String({
|
||||||
|
description: "The endpoint URL for video streaming",
|
||||||
|
}),
|
||||||
|
endpointThumbnail: t.String({
|
||||||
|
description: "The endpoint URL for thumbnails",
|
||||||
|
}),
|
||||||
|
endpointDownload: t.Optional(
|
||||||
|
t.String({
|
||||||
|
description: "The endpoint URL for downloads",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
detail: {
|
||||||
|
summary: "Create a new video service",
|
||||||
|
description:
|
||||||
|
"Perform creation of a new video service. This operation adds a new video service to the database based on the provided data.",
|
||||||
|
responses: {
|
||||||
|
201: {
|
||||||
|
description: "Video service created successfully",
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
success: { type: "boolean", default: true },
|
||||||
|
status: { type: "integer", default: 201 },
|
||||||
|
message: { type: "string", default: "Video service created" },
|
||||||
|
data: {
|
||||||
|
type: "object",
|
||||||
|
description:
|
||||||
|
"The created video service object. This field is returned only if the environment is running in development mode.",
|
||||||
|
properties: {
|
||||||
|
id: { type: "string", description: "The ID of the created video service" },
|
||||||
|
name: { type: "string", description: "The name of the video service" },
|
||||||
|
domain: { type: "string", description: "The domain of the video service" },
|
||||||
|
logo: { type: "string", description: "The logo URL of the video service" },
|
||||||
|
hexColor: { type: "string", description: "The hex color associated with the video service" },
|
||||||
|
endpointVideo: { type: "string", description: "The endpoint URL for video streaming" },
|
||||||
|
endpointThumbnail: { type: "string", description: "The endpoint URL for thumbnails" },
|
||||||
|
endpointDownload: {
|
||||||
|
type: "string",
|
||||||
|
description:
|
||||||
|
"The endpoint URL for downloads. This field is optional and may be null if not provided.",
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
description: "The timestamp when the video service was created",
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
description: "The timestamp when the video service was last updated",
|
||||||
|
},
|
||||||
|
deletedAt: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
description:
|
||||||
|
"The timestamp when the video service was deleted. This field is null if the video service is not deleted.",
|
||||||
|
},
|
||||||
|
createdBy: {
|
||||||
|
type: "string",
|
||||||
|
description:
|
||||||
|
"The ID of the account that created the video service (filled with the system account ID)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies AppRouteSchema;
|
||||||
34
src/modules/internal/schemas/purgeUnusedSession.schema.ts
Normal file
34
src/modules/internal/schemas/purgeUnusedSession.schema.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||||
|
|
||||||
|
export const purgeUnusedSessionSchema = {
|
||||||
|
detail: {
|
||||||
|
summary: "Purge all unused user sessions",
|
||||||
|
description:
|
||||||
|
"Perform purge of all unused user sessions. This operation deletes all user sessions from the database that are considered unused based on authentication status and deleted status. This helps in maintaining a clean session store and improving security by removing stale sessions.",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: "Unused user sessions purged successfully",
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
success: { type: "boolean", default: true },
|
||||||
|
status: { type: "integer", default: 200 },
|
||||||
|
message: { type: "string", default: "Successfully purged all unused user sessions" },
|
||||||
|
data: {
|
||||||
|
type: "object",
|
||||||
|
description:
|
||||||
|
"An object containing details about the purge operation. This field is returned only if the environment is running in development mode.",
|
||||||
|
properties: {
|
||||||
|
count: { type: "integer", description: "The number of user sessions that were purged" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies AppRouteSchema;
|
||||||
@ -1,11 +1,10 @@
|
|||||||
|
import { Static } from "elysia";
|
||||||
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 { CreateVideoServiceInternalBodyRequest } from "../../controllers/createVideoService.controller";
|
|
||||||
import { createVideoServiceInternalRepository } from "../../repositories/createVideoService.repository";
|
import { createVideoServiceInternalRepository } from "../../repositories/createVideoService.repository";
|
||||||
|
import { createVideoServiceInternalSchema } from "../../schemas/createVideoServiceInternal.schema";
|
||||||
|
|
||||||
export const createVideoServiceInternalService = async (
|
export const createVideoServiceInternalService = async (body: Static<typeof createVideoServiceInternalSchema.body>) => {
|
||||||
body: CreateVideoServiceInternalBodyRequest,
|
|
||||||
) => {
|
|
||||||
try {
|
try {
|
||||||
return await createVideoServiceInternalRepository({
|
return await createVideoServiceInternalRepository({
|
||||||
name: body.name,
|
name: body.name,
|
||||||
|
|||||||
Reference in New Issue
Block a user