Compare commits
5 Commits
ae0830cbe7
...
ebc143dc74
| Author | SHA1 | Date | |
|---|---|---|---|
| ebc143dc74 | |||
| 5a7f9bbebe | |||
| 02ad14d382 | |||
| a6b2c77bd1 | |||
| d858e54fe8 |
@ -498,6 +498,7 @@ Table hero_banner {
|
|||||||
orderPriority Int [unique]
|
orderPriority Int [unique]
|
||||||
isClickable Boolean [not null, default: false]
|
isClickable Boolean [not null, default: false]
|
||||||
title String
|
title String
|
||||||
|
tags String[] [not null]
|
||||||
description String
|
description String
|
||||||
buttonContent String
|
buttonContent String
|
||||||
buttonLink String
|
buttonLink String
|
||||||
@ -512,7 +513,7 @@ Table hero_banner {
|
|||||||
|
|
||||||
Table system_preferences {
|
Table system_preferences {
|
||||||
id String [pk]
|
id String [pk]
|
||||||
key String [not null]
|
key String [unique, not null]
|
||||||
value String [not null]
|
value String [not null]
|
||||||
description String [not null]
|
description String [not null]
|
||||||
deletedAt DateTime
|
deletedAt DateTime
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "hero_banner" ADD COLUMN "tags" TEXT[];
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- A unique constraint covering the columns `[key]` on the table `system_preferences` will be added. If there are existing duplicate values, this will fail.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "system_preferences_key_key" ON "system_preferences"("key");
|
||||||
@ -559,6 +559,7 @@ model HeroBanner {
|
|||||||
orderPriority Int? @unique
|
orderPriority Int? @unique
|
||||||
isClickable Boolean @default(false)
|
isClickable Boolean @default(false)
|
||||||
title String? @db.VarChar(225)
|
title String? @db.VarChar(225)
|
||||||
|
tags String[]
|
||||||
description String? @db.Text
|
description String? @db.Text
|
||||||
buttonContent String? @db.VarChar(100)
|
buttonContent String? @db.VarChar(100)
|
||||||
buttonLink String? @db.Text
|
buttonLink String? @db.Text
|
||||||
@ -574,7 +575,7 @@ model HeroBanner {
|
|||||||
|
|
||||||
model SystemPreference {
|
model SystemPreference {
|
||||||
id String @id @db.Uuid
|
id String @id @db.Uuid
|
||||||
key String @db.VarChar(225)
|
key String @db.VarChar(225) @unique
|
||||||
value String @db.VarChar(225)
|
value String @db.VarChar(225)
|
||||||
description String @db.Text
|
description String @db.Text
|
||||||
deletedAt DateTime?
|
deletedAt DateTime?
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { prisma } from "../../src/utils/databases/prisma/connection";
|
import { prisma } from "../../src/utils/databases/prisma/connection";
|
||||||
|
import { systemPreferenceSeed } from "./systemPreference.seed";
|
||||||
import { userRoleSeed } from "./userRole.seed";
|
import { userRoleSeed } from "./userRole.seed";
|
||||||
import { userSystemSeed } from "./userSystem.seed";
|
import { userSystemSeed } from "./userSystem.seed";
|
||||||
|
|
||||||
@ -8,6 +9,7 @@ async function main() {
|
|||||||
|
|
||||||
const userSystemSeedResult = await userSystemSeed();
|
const userSystemSeedResult = await userSystemSeed();
|
||||||
await userRoleSeed(userSystemSeedResult.id);
|
await userRoleSeed(userSystemSeedResult.id);
|
||||||
|
await systemPreferenceSeed();
|
||||||
|
|
||||||
console.log("🌳 All seeds completed");
|
console.log("🌳 All seeds completed");
|
||||||
}
|
}
|
||||||
|
|||||||
35
prisma/seed/systemPreference.seed.ts
Normal file
35
prisma/seed/systemPreference.seed.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { Prisma } from "@prisma/client";
|
||||||
|
import { generateUUIDv7 } from "../../src/helpers/databases/uuidv7";
|
||||||
|
import { prisma } from "../../src/utils/databases/prisma/connection";
|
||||||
|
|
||||||
|
export const systemPreferenceSeed = async () => {
|
||||||
|
const preferences: Prisma.SystemPreferenceUpsertArgs["create"][] = [
|
||||||
|
{
|
||||||
|
id: generateUUIDv7(),
|
||||||
|
key: "REGISTRATION_ENABLED",
|
||||||
|
value: process.env.ENABLE_REGISTRATION === "true" ? "true" : "false",
|
||||||
|
description: "Enable or disable user registration",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: generateUUIDv7(),
|
||||||
|
key: "HERO_BANNER_ENABLED",
|
||||||
|
value: process.env.ENABLE_HERO_BANNER === "true" ? "true" : "false",
|
||||||
|
description: "Enable or disable hero banner feature",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await prisma.$transaction(async (tx) => {
|
||||||
|
return await Promise.all(
|
||||||
|
preferences.map(
|
||||||
|
async (pref) =>
|
||||||
|
await tx.systemPreference.upsert({
|
||||||
|
where: {
|
||||||
|
key: pref.key,
|
||||||
|
},
|
||||||
|
update: pref,
|
||||||
|
create: pref,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
@ -1,8 +1,17 @@
|
|||||||
|
import { AppError } from "../../../helpers/error/instances/app";
|
||||||
import { ErrorForwarder } from "../../../helpers/error/instances/forwarder";
|
import { ErrorForwarder } from "../../../helpers/error/instances/forwarder";
|
||||||
|
import { findSystemPreferenceService } from "../../systemPreference/services/internal/findSystemPreference.service";
|
||||||
import { findAllActiveHeroBannerRepository } from "../repositories/GET/findAllActiveHeroBanner.repository";
|
import { findAllActiveHeroBannerRepository } from "../repositories/GET/findAllActiveHeroBanner.repository";
|
||||||
|
|
||||||
export const getActiveHeroBannerService = async () => {
|
export const getActiveHeroBannerService = async () => {
|
||||||
try {
|
try {
|
||||||
|
const isHeroBannerEnabled = await findSystemPreferenceService(
|
||||||
|
"HERO_BANNER_ENABLED",
|
||||||
|
"boolean",
|
||||||
|
);
|
||||||
|
if (!isHeroBannerEnabled)
|
||||||
|
throw new AppError(403, "Hero Banner is disabled");
|
||||||
|
|
||||||
return await findAllActiveHeroBannerRepository();
|
return await findAllActiveHeroBannerRepository();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ErrorForwarder(error);
|
ErrorForwarder(error);
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { createHeroBannerService } from "../services/http/createHeroBanner.servi
|
|||||||
export interface CreateHeroBannerRequestBody {
|
export interface CreateHeroBannerRequestBody {
|
||||||
isClickable?: boolean;
|
isClickable?: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
tags: string[];
|
||||||
description?: string;
|
description?: string;
|
||||||
buttonContent?: string;
|
buttonContent?: string;
|
||||||
buttonLink?: string;
|
buttonLink?: string;
|
||||||
|
|||||||
12
src/modules/systemPreference/index.tsx
Normal file
12
src/modules/systemPreference/index.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import Elysia, { Context } from "elysia";
|
||||||
|
import { returnWriteResponse } from "../../helpers/callback/httpResponse";
|
||||||
|
|
||||||
|
export const systemPreferenceModule = new Elysia({
|
||||||
|
prefix: "/system-preference",
|
||||||
|
}).get("/", (ctx: Context) => {
|
||||||
|
return returnWriteResponse(
|
||||||
|
ctx.set,
|
||||||
|
200,
|
||||||
|
"System Preference module is up and running",
|
||||||
|
);
|
||||||
|
});
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
import { AppError } from "../../../../helpers/error/instances/app";
|
||||||
|
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
|
||||||
|
import { redis } from "../../../../utils/databases/redis/connection";
|
||||||
|
import { findSystemPreferenceRepository } from "../repositories/findSystemPreference.repository";
|
||||||
|
|
||||||
|
export const findSystemPreferenceService = async (
|
||||||
|
key: string,
|
||||||
|
type: "boolean" | "string" | "number" = "string",
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
// First, check if the system preference is exists in redis cache
|
||||||
|
const cachedValue = await redis.get(
|
||||||
|
`${process.env.APP_NAME}:configs:${key}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!cachedValue) {
|
||||||
|
// If not exists in cache, fetch from database. If found, return the value and set it to cache, if not found, throw an error
|
||||||
|
const systemPreference = await findSystemPreferenceRepository(key);
|
||||||
|
if (!systemPreference)
|
||||||
|
throw new AppError(404, "System preference not found");
|
||||||
|
|
||||||
|
// and set it to cache for future requests
|
||||||
|
await redis.set(
|
||||||
|
`${process.env.APP_NAME}:configs:${key}`,
|
||||||
|
systemPreference.value,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Return the value from database
|
||||||
|
return parseValue(systemPreference.value, type);
|
||||||
|
} else {
|
||||||
|
return parseValue(cachedValue, type);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ErrorForwarder(error, 500, "Failed to find system preference");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseValue = (value: string, type: "boolean" | "string" | "number") => {
|
||||||
|
switch (type) {
|
||||||
|
case "boolean":
|
||||||
|
return value === "true";
|
||||||
|
case "number":
|
||||||
|
return Number(value);
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import { AppError } from "../../../../helpers/error/instances/app";
|
||||||
|
import { prisma } from "../../../../utils/databases/prisma/connection";
|
||||||
|
|
||||||
|
export const findSystemPreferenceRepository = async (key: string) => {
|
||||||
|
try {
|
||||||
|
return await prisma.systemPreference.findUnique({
|
||||||
|
where: {
|
||||||
|
key,
|
||||||
|
deletedAt: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new AppError(500, "Failed to find system preference", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user