feat: Introduce TimerKey enum and refactor timer key usage across services with new tests.
Some checks failed
Deploy to Production / test (push) Failing after 27s
Some checks failed
Deploy to Production / test (push) Failing after 27s
This commit is contained in:
@@ -50,7 +50,7 @@ export const userTimers = pgTable('user_timers', {
|
||||
userId: bigint('user_id', { mode: 'bigint' })
|
||||
.references(() => users.id, { onDelete: 'cascade' }).notNull(),
|
||||
type: varchar('type', { length: 50 }).notNull(), // 'COOLDOWN', 'EFFECT', 'ACCESS'
|
||||
key: varchar('key', { length: 100 }).notNull(), // 'daily', 'chn_12345', 'xp_boost'
|
||||
key: varchar('key', { length: 100 }).notNull(), // TimerKey, 'chn_12345', 'xp_boost'
|
||||
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
||||
metadata: jsonb('metadata').default({}),
|
||||
}, (table) => [
|
||||
|
||||
44
shared/lib/constants.test.ts
Normal file
44
shared/lib/constants.test.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { TimerKey, TimerType, TransactionType } from "./constants";
|
||||
|
||||
describe("TimerKey", () => {
|
||||
it("should have CHAT_XP value", () => {
|
||||
expect(TimerKey.CHAT_XP).toBe("chat_xp" as TimerKey);
|
||||
});
|
||||
|
||||
it("should have DAILY value", () => {
|
||||
expect(TimerKey.DAILY).toBe("daily" as TimerKey);
|
||||
});
|
||||
|
||||
it("should have WEEKLY value", () => {
|
||||
expect(TimerKey.WEEKLY).toBe("weekly" as TimerKey);
|
||||
});
|
||||
});
|
||||
|
||||
describe("TimerType", () => {
|
||||
it("should have COOLDOWN value", () => {
|
||||
expect(TimerType.COOLDOWN).toBe("COOLDOWN" as TimerType);
|
||||
});
|
||||
|
||||
it("should have EFFECT value", () => {
|
||||
expect(TimerType.EFFECT).toBe("EFFECT" as TimerType);
|
||||
});
|
||||
|
||||
it("should have ACCESS value", () => {
|
||||
expect(TimerType.ACCESS).toBe("ACCESS" as TimerType);
|
||||
});
|
||||
});
|
||||
|
||||
describe("TransactionType", () => {
|
||||
it("should have DAILY_REWARD value", () => {
|
||||
expect(TransactionType.DAILY_REWARD).toBe("DAILY_REWARD" as TransactionType);
|
||||
});
|
||||
|
||||
it("should have TRANSFER_IN value", () => {
|
||||
expect(TransactionType.TRANSFER_IN).toBe("TRANSFER_IN" as TransactionType);
|
||||
});
|
||||
|
||||
it("should have TRANSFER_OUT value", () => {
|
||||
expect(TransactionType.TRANSFER_OUT).toBe("TRANSFER_OUT" as TransactionType);
|
||||
});
|
||||
});
|
||||
@@ -10,6 +10,12 @@ export enum TimerType {
|
||||
TRIVIA_COOLDOWN = 'TRIVIA_COOLDOWN',
|
||||
}
|
||||
|
||||
export enum TimerKey {
|
||||
CHAT_XP = 'chat_xp',
|
||||
DAILY = 'daily',
|
||||
WEEKLY = 'weekly',
|
||||
}
|
||||
|
||||
export enum EffectType {
|
||||
ADD_XP = 'ADD_XP',
|
||||
ADD_BALANCE = 'ADD_BALANCE',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { config } from "@shared/lib/config";
|
||||
import { withTransaction } from "@/lib/db";
|
||||
import type { Transaction } from "@shared/lib/types";
|
||||
import { UserError } from "@shared/lib/errors";
|
||||
import { TimerType, TransactionType } from "@shared/lib/constants";
|
||||
import { TimerKey, TimerType, TransactionType } from "@shared/lib/constants";
|
||||
|
||||
export const economyService = {
|
||||
transfer: async (fromUserId: string, toUserId: string, amount: bigint, tx?: Transaction) => {
|
||||
@@ -82,7 +82,7 @@ export const economyService = {
|
||||
where: and(
|
||||
eq(userTimers.userId, BigInt(userId)),
|
||||
eq(userTimers.type, TimerType.COOLDOWN),
|
||||
eq(userTimers.key, 'daily')
|
||||
eq(userTimers.key, TimerKey.DAILY)
|
||||
),
|
||||
});
|
||||
|
||||
@@ -141,7 +141,7 @@ export const economyService = {
|
||||
.values({
|
||||
userId: BigInt(userId),
|
||||
type: TimerType.COOLDOWN,
|
||||
key: 'daily',
|
||||
key: TimerKey.DAILY,
|
||||
expiresAt: nextReadyAt,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
|
||||
@@ -3,7 +3,7 @@ import { eq, sql, and } from "drizzle-orm";
|
||||
import { withTransaction } from "@/lib/db";
|
||||
import { config } from "@shared/lib/config";
|
||||
import type { Transaction } from "@shared/lib/types";
|
||||
import { TimerType } from "@shared/lib/constants";
|
||||
import { TimerKey, TimerType } from "@shared/lib/constants";
|
||||
|
||||
export const levelingService = {
|
||||
// Calculate total XP required to REACH a specific level (Cumulative)
|
||||
@@ -84,7 +84,7 @@ export const levelingService = {
|
||||
where: and(
|
||||
eq(userTimers.userId, BigInt(id)),
|
||||
eq(userTimers.type, TimerType.COOLDOWN),
|
||||
eq(userTimers.key, 'chat_xp')
|
||||
eq(userTimers.key, TimerKey.CHAT_XP)
|
||||
),
|
||||
});
|
||||
|
||||
@@ -120,7 +120,7 @@ export const levelingService = {
|
||||
.values({
|
||||
userId: BigInt(id),
|
||||
type: TimerType.COOLDOWN,
|
||||
key: 'chat_xp',
|
||||
key: TimerKey.CHAT_XP,
|
||||
expiresAt: nextReadyAt,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
|
||||
Reference in New Issue
Block a user