diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..e69de29 diff --git a/eslint.config.mjs b/eslint.config.mjs index a65f28d..cee8678 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -5,7 +5,7 @@ import { defineConfig } from "eslint/config"; export default defineConfig([ { - ignores: ["src/modules/debug/**"], + ignores: ["src/modules/debug/**", "src/helpers/characters/generateSlug.ts"], }, { files: ["src/**/*.{js,mjs,cjs,ts,mts,cts}"], diff --git a/prisma/seed/index.ts b/prisma/seed/index.ts index 6302203..7478bfb 100644 --- a/prisma/seed/index.ts +++ b/prisma/seed/index.ts @@ -7,7 +7,7 @@ async function main() { console.log("🔌 Connecting to database..."); const userSystemSeedResult = await userSystemSeed(); - const userRoleSeedResult = await userRoleSeed(userSystemSeedResult.id); + await userRoleSeed(userSystemSeedResult.id); console.log("🌳 All seeds completed"); } diff --git a/scripts/create-example-env.ts b/scripts/create-example-env.ts index c7d7dea..2b351e3 100644 --- a/scripts/create-example-env.ts +++ b/scripts/create-example-env.ts @@ -50,7 +50,7 @@ try { // Extract the key and the remainder after "=" const key = line.substring(0, delimiterIndex).trim(); - let remainder = line.substring(delimiterIndex + 1); + const remainder = line.substring(delimiterIndex + 1); // Attempt to separate value and inline comment (if any) let value = remainder; diff --git a/scripts/git-multipush.example.ts b/scripts/git-multipush.example.ts index 937ceed..485e606 100644 --- a/scripts/git-multipush.example.ts +++ b/scripts/git-multipush.example.ts @@ -14,7 +14,7 @@ for (const remote of remotes) { try { execSync(`git push ${remote} main`, { stdio: "inherit" }); } catch (err) { - console.error(`❌ Failed to push to ${remote}`); + console.error(`❌ Failed to push to ${remote}`, err); } } diff --git a/src/helpers/characters/generateSlug.ts b/src/helpers/characters/generateSlug.ts index 17fdbb4..97ca1a8 100644 --- a/src/helpers/characters/generateSlug.ts +++ b/src/helpers/characters/generateSlug.ts @@ -14,17 +14,13 @@ export async function generateSlug( const baseSlug = slugify(input, { lower: true, strict: true }); let uniqueSlug = baseSlug; - // CASE 1: Tidak ada config → langsung return slug if (!config) return uniqueSlug; - const { model, target } = config; - // CASE 2: Validasi pasangan model-target if (!model || !target) { throw new Error(`Both "model" and "target" must be provided together.`); } - // CASE 3: Cek unique const prismaModel = (prisma as any)[model]; if (!prismaModel) { throw new Error(`Model "${model as string}" not found in PrismaClient.`); diff --git a/src/helpers/databases/createManyWithUUID.ts b/src/helpers/databases/createManyWithUUID.ts index a2da1b8..e219442 100644 --- a/src/helpers/databases/createManyWithUUID.ts +++ b/src/helpers/databases/createManyWithUUID.ts @@ -1,8 +1,10 @@ import { generateUUIDv7 } from "./uuidv7"; -function createManyWithUUID(items: T[]): T[] { +export const createManyWithUUID = ( + items: T[], +): T[] => { return items.map((i) => ({ ...i, id: i.id ?? generateUUIDv7(), })); -} +}; diff --git a/src/index.ts b/src/index.ts index 01a69cd..6e74d95 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ + import { middleware } from "./middleware"; import { validateEnv } from "./utils/startups/validateEnv"; @@ -12,7 +14,7 @@ async function bootstrap() { sentryInit(); console.log("\x1b[1m\x1b[33m🚀 Starting backend services...\x1b[0m"); - const app = new Elysia() + new Elysia() .use(middleware) .use(routes) .listen(process.env.APP_PORT || 3000); diff --git a/src/middleware/global/appAccessToken.middleware.ts b/src/middleware/global/appAccessToken.middleware.ts index 459d137..35474f6 100644 --- a/src/middleware/global/appAccessToken.middleware.ts +++ b/src/middleware/global/appAccessToken.middleware.ts @@ -1,4 +1,4 @@ -import Elysia, { Context } from "elysia"; +import Elysia from "elysia"; import { returnErrorResponse } from "../../helpers/callback/httpResponse"; export const appAccessTokenMiddleware = () => diff --git a/src/middleware/userRoles/isAdmin.middleware.ts b/src/middleware/userRoles/isAdmin.middleware.ts index 61d5434..e680f30 100644 --- a/src/middleware/userRoles/isAdmin.middleware.ts +++ b/src/middleware/userRoles/isAdmin.middleware.ts @@ -1,5 +1,12 @@ import { Context } from "elysia"; export const isAdminMiddleware = (ctx: Context) => { - //validate here + const isAdmin = ctx.headers["isAdmin"]; + if (!isAdmin) { + ctx.set.status = 403; + return { + error: "Forbidden", + message: "You don't have access to this resource", + }; + } }; diff --git a/src/modules/auth/services/http/tokenValidation.service.ts b/src/modules/auth/services/http/tokenValidation.service.ts index 176f9ae..d2ec5fa 100644 --- a/src/modules/auth/services/http/tokenValidation.service.ts +++ b/src/modules/auth/services/http/tokenValidation.service.ts @@ -1,6 +1,5 @@ import { AppError } from "../../../../helpers/error/instances/app"; import { jwtDecode } from "../../../../helpers/http/jwt/decode"; -import { jwtEncode } from "../../../../helpers/http/jwt/encode"; export const tokenValidationService = (payload: string) => { try { diff --git a/src/modules/internal/services/http/bulkInsertEpisode.service.ts b/src/modules/internal/services/http/bulkInsertEpisode.service.ts index a6aacd0..f1b5ef3 100644 --- a/src/modules/internal/services/http/bulkInsertEpisode.service.ts +++ b/src/modules/internal/services/http/bulkInsertEpisode.service.ts @@ -1,4 +1,3 @@ -import { Prisma } from "@prisma/client"; import { getEpisodeReferenceAPI } from "../../../../config/apis/episode.reference"; import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder"; import { MediaEpisodeInfoResponse } from "../../types/mediaEpisodeInfo.type"; diff --git a/src/modules/internal/services/internal/bulkInsertCharWithVA.service.ts b/src/modules/internal/services/internal/bulkInsertCharWithVA.service.ts index bef3435..bd9d2e0 100644 --- a/src/modules/internal/services/internal/bulkInsertCharWithVA.service.ts +++ b/src/modules/internal/services/internal/bulkInsertCharWithVA.service.ts @@ -1,6 +1,5 @@ import { SystemAccountId } from "../../../../config/account/system"; import { getContentReferenceAPI } from "../../../../config/apis/media.reference"; -import { generateUUIDv7 } from "../../../../helpers/databases/uuidv7"; import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder"; import { bulkInsertCharactersRepository } from "../../repositories/bulkInsertCharacters.repository"; import { bulkInsertLangVARepository } from "../../repositories/bulkInsertLangVA.repository"; diff --git a/src/modules/internal/services/internal/bulkInsertStaffOrPeople.service.ts b/src/modules/internal/services/internal/bulkInsertStaffOrPeople.service.ts index d73e9c9..0f6ef4c 100644 --- a/src/modules/internal/services/internal/bulkInsertStaffOrPeople.service.ts +++ b/src/modules/internal/services/internal/bulkInsertStaffOrPeople.service.ts @@ -1,5 +1,4 @@ import { SystemAccountId } from "../../../../config/account/system"; -import { generateUUIDv7 } from "../../../../helpers/databases/uuidv7"; import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder"; import { bulkInsertVoiceActorRepository } from "../../repositories/bulkInsertVoiceActor.repository"; import { Person } from "../../types/mediaCharWithVAInfo"; diff --git a/src/modules/internal/types/mediaFullInfo.type.ts b/src/modules/internal/types/mediaFullInfo.type.ts index acdb229..a31da2b 100644 --- a/src/modules/internal/types/mediaFullInfo.type.ts +++ b/src/modules/internal/types/mediaFullInfo.type.ts @@ -34,12 +34,12 @@ interface Data { year: number; broadcast: Broadcast; producers: Genre[]; - licensors: any[]; + licensors: unknown[]; studios: Genre[]; genres: Genre[]; - explicit_genres: any[]; + explicit_genres: unknown[]; themes: Genre[]; - demographics: any[]; + demographics: unknown[]; relations: Relation[]; theme: Theme; external: External[]; diff --git a/src/modules/internal/types/peopleInfo.ts b/src/modules/internal/types/peopleInfo.ts index 1e2d22d..ef9018d 100644 --- a/src/modules/internal/types/peopleInfo.ts +++ b/src/modules/internal/types/peopleInfo.ts @@ -10,7 +10,7 @@ interface Data { name: string; given_name: null; family_name: null; - alternate_names: any[]; + alternate_names: string[]; birthday: Date; favorites: number; about: string; diff --git a/src/modules/user/schemas/getUserOptions.schema.ts b/src/modules/user/schemas/getUserOptions.schema.ts index 8707314..cab8595 100644 --- a/src/modules/user/schemas/getUserOptions.schema.ts +++ b/src/modules/user/schemas/getUserOptions.schema.ts @@ -6,14 +6,17 @@ const includeOptions = ["preference", "assignedRoles"] as const; export const getUserOptionsSchema = z.object({ verbosity: z.enum( ["exists", "basic", "full"], - "option: verbosity value must match with enum types" + "option: verbosity value must match with enum types", ), include: z .string() .optional() .transform((val) => val?.split(",") ?? []) .refine( - (arr) => arr.every((val) => includeOptions.includes(val.trim() as any)), - "option: include value didn't match with enum types" + (arr) => + arr.every((val) => + includeOptions.includes(val.trim() as typeof includeOptions[number]), + ), + "option: include value didn't match with enum types", ), }); diff --git a/src/modules/userSession/repositories/createUserSession.repository.ts b/src/modules/userSession/repositories/createUserSession.repository.ts index cf16edd..90b7968 100644 --- a/src/modules/userSession/repositories/createUserSession.repository.ts +++ b/src/modules/userSession/repositories/createUserSession.repository.ts @@ -2,26 +2,6 @@ import { Prisma } from "@prisma/client"; import { ErrorForwarder } from "../../../helpers/error/instances/forwarder"; import { userSessionModel } from "../userSession.model"; -type CreateUserSessionResponse = Prisma.UserSessionGetPayload<{ - select: { - id: true; - deviceType: true; - isAuthenticated: true; - validUntil: true; - user: { - select: { - id: true; - name: true; - email: true; - username: true; - avatar: true; - birthDate: true; - bioProfile: true; - }; - }; - }; -}>; - export const createUserSessionRepository = async ( data: Prisma.UserSessionUncheckedCreateInput, ) => { diff --git a/src/utils/storages/MinIO/operations/getStreamFile.ts b/src/utils/storages/MinIO/operations/getStreamFile.ts index fcd4592..fc4731c 100644 --- a/src/utils/storages/MinIO/operations/getStreamFile.ts +++ b/src/utils/storages/MinIO/operations/getStreamFile.ts @@ -1,4 +1,4 @@ -import { minioBucketName, minioClient } from "../client"; +import { minioClient } from "../client"; import { ensureBucketExists } from "../validations/ensureBucketExists"; export const getStreamFile = async (filename: string) => { diff --git a/src/utils/storages/MinIO/operations/uploadFile.ts b/src/utils/storages/MinIO/operations/uploadFile.ts index f20dd6b..f33346c 100644 --- a/src/utils/storages/MinIO/operations/uploadFile.ts +++ b/src/utils/storages/MinIO/operations/uploadFile.ts @@ -1,4 +1,4 @@ -import { minioBucketName, minioClient, minioProtocol } from "../client"; +import { minioBucketName, minioClient } from "../client"; import { ensureBucketExists } from "../validations/ensureBucketExists"; import { Readable } from "stream"; @@ -7,7 +7,7 @@ export const uploadFile = async ( options?: { fileDir?: string; fileName?: string; - } + }, ): Promise => { // Ensure the target MinIO bucket exists before performing any upload await ensureBucketExists();