UPDATE: Change using api to using static file
Some checks failed
Gitea Auto Deploy / Deploy-Container (push) Failing after 2m2s

This commit is contained in:
2025-12-31 16:51:39 +07:00
parent 30f8796430
commit 6704216908
114 changed files with 142 additions and 1111 deletions

View File

@@ -1,19 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { loadAS } from '@/lib/loader'
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string, locale: string }> }
) {
const { id, locale } = await params
const asData = await loadAS([id], locale)
const as = asData[id]
if (!as) {
return NextResponse.json({ error: 'AS info not found' }, { status: 404 })
}
return new NextResponse(JSON.stringify(as), {
headers: { "Content-Type": "application/json" }
});
}

View File

@@ -1,22 +0,0 @@
import { loadAS } from "@/lib/loader";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest, { params }: { params: Promise<{ locale: string }> }) {
try {
const body = await request.json();
const asIds = body.asIds as string[];
const { locale } = await params;
if (!Array.isArray(asIds) || asIds.some(id => typeof id !== 'string')) {
return NextResponse.json({ error: 'Invalid asIds' }, { status: 400 });
}
const asData = await loadAS(asIds, locale);
return new NextResponse(JSON.stringify(asData), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load as data' }, { status: 500 });
}
}

View File

@@ -1,20 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { loadCharacters } from '@/lib/loader'
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string, locale: string }> }
) {
const { id, locale } = await params
const characters = await loadCharacters([id], locale)
const char = characters[id]
if (!char) {
return NextResponse.json({ error: 'Character not found' }, { status: 404 })
}
return new NextResponse(JSON.stringify(char), {
headers: { "Content-Type": "application/json" }
});
}

View File

@@ -1,22 +0,0 @@
import { loadCharacters } from "@/lib/loader";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest, { params }: { params: Promise<{ locale: string }> }) {
try {
const body = await request.json();
const charIds = body.charIds as string[];
const { locale } = await params;
if (!Array.isArray(charIds) || charIds.some(id => typeof id !== 'string')) {
return NextResponse.json({ error: 'Invalid charIds' }, { status: 400 });
}
const characters = await loadCharacters(charIds, locale);
return new NextResponse(JSON.stringify(characters), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load characters' }, { status: 500 });
}
}

View File

@@ -1,20 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { loadLightcones } from '@/lib/loader'
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string, locale: string }> }
) {
const { id, locale } = await params
const lightcones = await loadLightcones([id], locale)
const lightcone = lightcones[id]
if (!lightcone) {
return NextResponse.json({ error: 'Lightcone not found' }, { status: 404 })
}
return new NextResponse(JSON.stringify(lightcone), {
headers: { "Content-Type": "application/json" }
});
}

View File

@@ -1,22 +0,0 @@
import { loadLightcones } from "@/lib/loader";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest, { params }: { params: Promise<{ locale: string }> }) {
try {
const body = await request.json();
const lightconeIds = body.lightconeIds as string[];
const { locale } = await params;
if (!Array.isArray(lightconeIds) || lightconeIds.some(id => typeof id !== 'string')) {
return NextResponse.json({ error: 'Invalid lightconeIds' }, { status: 400 });
}
const lightcones = await loadLightcones(lightconeIds, locale);
return new NextResponse(JSON.stringify(lightcones), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load lightcones' }, { status: 500 });
}
}

View File

@@ -1,20 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { loadMOC } from '@/lib/loader'
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string, locale: string }> }
) {
const { id, locale } = await params
const mocData = await loadMOC([id], locale)
const moc = mocData[id]
if (!moc) {
return NextResponse.json({ error: 'MOC info not found' }, { status: 404 })
}
return new NextResponse(JSON.stringify(moc), {
headers: { "Content-Type": "application/json" }
});
}

View File

@@ -1,22 +0,0 @@
import { loadMOC } from "@/lib/loader";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest, { params }: { params: Promise<{ locale: string }> }) {
try {
const body = await request.json();
const mocIds = body.mocIds as string[];
const { locale } = await params;
if (!Array.isArray(mocIds) || mocIds.some(id => typeof id !== 'string')) {
return NextResponse.json({ error: 'Invalid mocIds' }, { status: 400 });
}
const mocData = await loadMOC(mocIds, locale);
return new NextResponse(JSON.stringify(mocData), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load moc data' }, { status: 500 });
}
}

View File

@@ -1,19 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { loadMonster } from '@/lib/loader'
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string, locale: string }> }
) {
const { id, locale } = await params
const monsterData = await loadMonster([id], locale)
const monster = monsterData[id]
if (!monster) {
return NextResponse.json({ error: 'Monster info not found' }, { status: 404 })
}
return new NextResponse(JSON.stringify(monster), {
headers: { "Content-Type": "application/json" }
});
}

View File

@@ -1,22 +0,0 @@
import { loadMonster } from "@/lib/loader";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest, { params }: { params: Promise<{ locale: string }> }) {
try {
const body = await request.json();
const monsterIds = body.monsterIds as string[];
const { locale } = await params;
if (!Array.isArray(monsterIds) || monsterIds.some(id => typeof id !== 'string')) {
return NextResponse.json({ error: 'Invalid monsterIds' }, { status: 400 });
}
const monsterData = await loadMonster(monsterIds, locale);
return new NextResponse(JSON.stringify(monsterData), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load monster data' }, { status: 500 });
}
}

View File

@@ -1,20 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { loadPeak } from '@/lib/loader'
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string, locale: string }> }
) {
const { id, locale } = await params
const peakData = await loadPeak([id], locale)
const peak = peakData[id]
if (!peak) {
return NextResponse.json({ error: 'Peak info not found' }, { status: 404 })
}
return new NextResponse(JSON.stringify(peak), {
headers: { "Content-Type": "application/json" }
});
}

View File

@@ -1,22 +0,0 @@
import { loadPeak } from "@/lib/loader";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest, { params }: { params: Promise<{ locale: string }> }) {
try {
const body = await request.json();
const peakIds = body.peakIds as string[];
const { locale } = await params;
if (!Array.isArray(peakIds) || peakIds.some(id => typeof id !== 'string')) {
return NextResponse.json({ error: 'Invalid peakIds' }, { status: 400 });
}
const peakData = await loadPeak(peakIds, locale);
return new NextResponse(JSON.stringify(peakData), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load peak data' }, { status: 500 });
}
}

View File

@@ -1,21 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { loadPF } from '@/lib/loader'
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string, locale: string }> }
) {
const { id, locale } = await params
const pfData = await loadPF([id], locale)
const pf = pfData[id]
if (!pf) {
return NextResponse.json({ error: 'PF info not found' }, { status: 404 })
}
return new NextResponse(JSON.stringify(pf), {
headers: { "Content-Type": "application/json" }
});
}

View File

@@ -1,22 +0,0 @@
import { loadPF } from "@/lib/loader";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest, { params }: { params: Promise<{ locale: string }> }) {
try {
const body = await request.json();
const pfIds = body.pfIds as string[];
const { locale } = await params;
if (!Array.isArray(pfIds) || pfIds.some(id => typeof id !== 'string')) {
return NextResponse.json({ error: 'Invalid pfIds' }, { status: 400 });
}
const pfData = await loadPF(pfIds, locale);
return new NextResponse(JSON.stringify(pfData), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load pf data' }, { status: 500 });
}
}

View File

@@ -1,20 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { loadRelics } from '@/lib/loader'
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string, locale: string }> }
) {
const { id, locale } = await params
const relics = await loadRelics([id], locale)
const relic = relics[id]
if (!relic) {
return NextResponse.json({ error: 'Relic not found' }, { status: 404 })
}
return new NextResponse(JSON.stringify(relic), {
headers: { "Content-Type": "application/json" }
});
}

View File

@@ -1,22 +0,0 @@
import { NextRequest, NextResponse } from "next/server";
import { loadRelics } from "@/lib/loader";
export async function POST(request: NextRequest, { params }: { params: Promise<{ locale: string }> }) {
try {
const body = await request.json();
const relicIds = body.relicIds as string[];
const { locale } = await params;
if (!Array.isArray(relicIds) || relicIds.some(id => typeof id !== 'string')) {
return NextResponse.json({ error: 'Invalid relicIds' }, { status: 400 });
}
const relics = await loadRelics(relicIds, locale);
return new NextResponse(JSON.stringify(relics), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load relics' }, { status: 500 });
}
}

View File

@@ -1,13 +0,0 @@
import { loadConfigMaze } from "@/lib/loader";
import { NextResponse } from "next/server";
export async function GET() {
try {
const configMaze = await loadConfigMaze();
return new NextResponse(JSON.stringify(configMaze), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load config maze' }, { status: 500 });
}
}

View File

@@ -1,13 +0,0 @@
import { loadMainAffix } from "@/lib/loader";
import { NextResponse } from "next/server";
export async function GET() {
try {
const mainAffix = await loadMainAffix();
return new NextResponse(JSON.stringify(mainAffix), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load main affix' }, { status: 500 });
}
}

View File

@@ -1,13 +0,0 @@
import { loadSubAffix } from "@/lib/loader";
import { NextResponse } from "next/server";
export async function GET() {
try {
const subAffix = await loadSubAffix();
return new NextResponse(JSON.stringify(subAffix), {
headers: { "Content-Type": "application/json" }
});
} catch {
return NextResponse.json({ error: 'Failed to load sub affix' }, { status: 500 });
}
}

View File

@@ -234,7 +234,7 @@ export default function ActionBar() {
<Image
src={`/icon/${avatarSelected.damageType.toLowerCase()}.webp`}
alt={'fire'}
className="h-[40px] w-[40px] object-contain"
className="h-10 w-10 object-contain"
width={100}
height={100}
/>

View File

@@ -1,6 +1,5 @@
"use client";
import React, { useEffect, useState, useRef, useMemo, useCallback } from 'react';
import { useEffect, useState, useRef, useMemo, useCallback } from 'react';
import useAvatarStore from "@/stores/avatarStore";
import { FastAverageColor, FastAverageColorResult } from 'fast-average-color';
import NextImage from 'next/image';
@@ -53,7 +52,8 @@ export default function ShowCaseInfo() {
link.href = canvas.toDataURL("image/png");
link.click();
})
.catch(() => {
.catch((e) => {
console.log(e)
toast.error("Error generating showcase card!");
});
}, [cardRef, avatarSelected, locale]);
@@ -567,7 +567,7 @@ export default function ShowCaseInfo() {
<div className="absolute top-4 left-4">
{avatarSelected && avatarInfo && avatarData?.data && typeof avatarData?.data?.rank === "number" && (
<div className="flex flex-col">
{avatarInfo?.RankIcon.map((src, index) => {
{avatarInfo?.RankIcon?.map((src, index) => {
const isActive = avatarData?.data?.rank > index;
return (

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
"use client"
import { useQuery } from '@tanstack/react-query'
import { fetchASByIdsNative, getASEventListApi } from '@/lib/api'
import { fetchASEventApi, getASEventListApi } from '@/lib/api'
import { useEffect } from 'react'
import { listCurrentLanguageApi } from '@/constant/constant'
import useLocaleStore from '@/stores/localeStore'
@@ -21,8 +22,7 @@ export const useFetchASData = () => {
const { data: dataASInfo, error: errorASInfo } = useQuery({
queryKey: ['asInfoData', locale],
queryFn: () =>
fetchASByIdsNative(
dataAS!.map((item) => item.id),
fetchASEventApi(
listCurrentLanguageApi[locale.toLowerCase()]
),
staleTime: 1000 * 60 * 5,
@@ -33,13 +33,19 @@ export const useFetchASData = () => {
for (const item of newData[key].Level) {
item.EventIDList1 = item.EventIDList1.map((event: EventStageDetail) => ({
...event,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
MonsterList: event.MonsterList.map(({ $type, ...rest }) => rest)
MonsterList: event.MonsterList.map((monster) => {
const { $type, ...rest } = monster;
return rest;
})
}))
item.EventIDList2 = item.EventIDList2.map((event: EventStageDetail) => ({
...event,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
MonsterList: event.MonsterList.map(({ $type, ...rest }) => rest)
MonsterList: event.MonsterList.map((monster) => {
const { $type, ...rest } = monster;
return rest;
})
}))
}
}

View File

@@ -1,6 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */
"use client"
import { useQuery } from '@tanstack/react-query'
import { fetchCharactersByIdsNative, getCharacterListApi } from '@/lib/api'
import { fetchCharactersApi, getCharacterListApi } from '@/lib/api'
import { useEffect } from 'react'
import { toast } from 'react-toastify'
import useAvatarStore from '@/stores/avatarStore'
@@ -36,14 +37,12 @@ export const useFetchAvatarData = () => {
for (const avatar of Object.values(avatarStore)) {
setAvatar(avatar)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mapAvatarInfo])
const { data: dataAvatarInfo, error: errorAvatarInfo } = useQuery({
queryKey: ['avatarInfoData', locale],
queryFn: () =>
fetchCharactersByIdsNative(
dataAvatar!.map((item) => item.id),
fetchCharactersApi(
listCurrentLanguageApi[locale.toLowerCase()]
),
staleTime: 1000 * 60 * 5,
@@ -60,7 +59,6 @@ export const useFetchAvatarData = () => {
} else if (errorAvatar) {
toast.error("Failed to load avatar data")
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dataAvatar, errorAvatar])
useEffect(() => {
@@ -69,6 +67,5 @@ export const useFetchAvatarData = () => {
} else if (errorAvatarInfo) {
toast.error("Failed to load avatar info data")
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dataAvatarInfo, errorAvatarInfo])
}

View File

@@ -1,6 +1,6 @@
"use client"
import { useQuery } from '@tanstack/react-query'
import { fetchLightconesByIdsNative, getLightconeListApi } from '@/lib/api'
import { fetchLightconesApi, getLightconeListApi } from '@/lib/api'
import { useEffect } from 'react'
import useLightconeStore from '@/stores/lightconeStore'
import { listCurrentLanguageApi } from '@/constant/constant'
@@ -20,8 +20,7 @@ export const useFetchLightconeData = () => {
const { data: dataLightconeInfo, error: errorLightconeInfo } = useQuery({
queryKey: ['lightconeInfoData', locale],
queryFn: () =>
fetchLightconesByIdsNative(
dataLightcone!.map((item) => item.id),
fetchLightconesApi(
listCurrentLanguageApi[locale.toLowerCase()]
),
staleTime: 1000 * 60 * 5,

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
"use client"
import { useQuery } from '@tanstack/react-query'
import { fetchMOCByIdsNative, getMOCEventListApi } from '@/lib/api'
import { fetchMOCEventApi, getMOCEventListApi } from '@/lib/api'
import { useEffect } from 'react'
import { listCurrentLanguageApi } from '@/constant/constant'
import useLocaleStore from '@/stores/localeStore'
@@ -21,8 +22,7 @@ export const useFetchMOCData = () => {
const { data: dataMOCInfo, error: errorMOCInfo } = useQuery({
queryKey: ['mocInfoData', locale],
queryFn: async () => {
const result = await fetchMOCByIdsNative(
dataMOC!.map((item) => item.id),
const result = await fetchMOCEventApi(
listCurrentLanguageApi[locale.toLowerCase()]
);
return result;
@@ -34,12 +34,10 @@ export const useFetchMOCData = () => {
for (const item of newData[key]) {
item.EventIDList1 = item.EventIDList1.map((event: EventStageDetail) => ({
...event,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
MonsterList: event.MonsterList.map(({ $type, ...rest }) => rest)
}))
item.EventIDList2 = item.EventIDList2.map((event: EventStageDetail) => ({
...event,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
MonsterList: event.MonsterList.map(({ $type, ...rest }) => rest)
}))
}

View File

@@ -1,6 +1,6 @@
"use client"
import { useQuery } from '@tanstack/react-query'
import { getMonsterValueApi, getMonsterListApi, fetchMonsterByIdsNative } from '@/lib/api'
import { getMonsterValueApi, getMonsterListApi, fetchMonstersApi } from '@/lib/api'
import { useEffect } from 'react'
import { toast } from 'react-toastify'
import useMonsterStore from '@/stores/monsterStore'
@@ -25,8 +25,7 @@ export const useFetchMonsterData = () => {
const { data: dataMonsterDetail, error: errorMonsterDetail } = useQuery({
queryKey: ['monsterDetailData', locale],
queryFn: () =>
fetchMonsterByIdsNative(
dataMonster!.list.map((item) => item.id),
fetchMonstersApi(
listCurrentLanguageApi[locale.toLowerCase()]
),
staleTime: 1000 * 60 * 5,

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
"use client"
import { useQuery } from '@tanstack/react-query'
import { fetchPeakByIdsNative, getPEAKEventListApi } from '@/lib/api'
import { fetchPeakEventApi, getPEAKEventListApi } from '@/lib/api'
import { useEffect } from 'react'
import { listCurrentLanguageApi } from '@/constant/constant'
import useLocaleStore from '@/stores/localeStore'
@@ -21,8 +22,7 @@ export const useFetchPEAKData = () => {
const { data: dataPEAKInfo, error: errorPEAKInfo } = useQuery({
queryKey: ['peakInfoData', locale],
queryFn: () =>
fetchPeakByIdsNative(
dataPEAK!.map((item) => item.id),
fetchPeakEventApi(
listCurrentLanguageApi[locale.toLowerCase()]
),
staleTime: 1000 * 60 * 5,
@@ -32,18 +32,15 @@ export const useFetchPEAKData = () => {
for (const item of newData[key].PreLevel) {
item.EventIDList = item.EventIDList.map((event: EventStageDetail) => ({
...event,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
MonsterList: event.MonsterList.map(({ $type, ...rest }) => rest)
}))
}
newData[key].BossLevel.EventIDList = newData[key].BossLevel.EventIDList.map((event: EventStageDetail) => ({
...event,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
MonsterList: event.MonsterList.map(({ $type, ...rest }) => rest)
}))
newData[key].BossConfig.EventIDList = newData[key].BossConfig.EventIDList.map((event: EventStageDetail) => ({
...event,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
MonsterList: event.MonsterList.map(({ $type, ...rest }) => rest)
}))
}

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
"use client"
import { useQuery } from '@tanstack/react-query'
import { fetchPFByIdsNative, getPFEventListApi } from '@/lib/api'
import { fetchPFEventApi, getPFEventListApi } from '@/lib/api'
import { useEffect } from 'react'
import { listCurrentLanguageApi } from '@/constant/constant'
import useLocaleStore from '@/stores/localeStore'
@@ -21,8 +22,7 @@ export const useFetchPFData = () => {
const { data: dataPFInfo, error: errorPFInfo } = useQuery({
queryKey: ['pfInfoData', locale],
queryFn: () =>
fetchPFByIdsNative(
dataPF!.map((item) => item.id),
fetchPFEventApi(
listCurrentLanguageApi[locale.toLowerCase()]
),
staleTime: 1000 * 60 * 5,
@@ -33,12 +33,10 @@ export const useFetchPFData = () => {
for (const item of newData[key].Level) {
item.EventIDList1 = item.EventIDList1.map((event: EventStageDetail) => ({
...event,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
MonsterList: event.MonsterList.map(({ $type, ...rest }) => rest)
}))
item.EventIDList2 = item.EventIDList2.map((event: EventStageDetail) => ({
...event,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
MonsterList: event.MonsterList.map(({ $type, ...rest }) => rest)
}))
}

View File

@@ -1,6 +1,6 @@
"use client"
import { useQuery } from '@tanstack/react-query'
import { fetchRelicsByIdsNative, getRelicSetListApi } from '@/lib/api'
import { fetchRelicsApi, getRelicSetListApi } from '@/lib/api'
import { useEffect } from 'react'
import useRelicStore from '@/stores/relicStore'
import { listCurrentLanguageApi } from '@/constant/constant'
@@ -19,8 +19,7 @@ export const useFetchRelicData = () => {
const { data: dataRelicInfo, error: errorRelicInfo } = useQuery({
queryKey: ['relicInfoData', locale],
queryFn: () =>
fetchRelicsByIdsNative(
dataRelic!.map((item) => item.id),
fetchRelicsApi(
listCurrentLanguageApi[locale.toLowerCase()]
),
staleTime: 1000 * 60 * 5,

View File

@@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { AffixDetail, ASDetail, CharacterDetail, ConfigMaze, FreeSRJson, LightConeDetail, MocDetail, MonsterDetail, PeakDetail, PFDetail, PSResponse, RelicDetail } from "@/types";
import axios from 'axios';
import { psResponseSchema } from "@/zod";
@@ -7,15 +6,7 @@ import { ExtraData } from "@/types";
export async function getConfigMazeApi(): Promise<ConfigMaze> {
try {
const res = await axios.get<ConfigMaze>(
`/api/config-maze`,
{
headers: {
'Content-Type': 'application/json',
},
}
);
const res = await axios.get<ConfigMaze>(`/data/config_maze.json`);
return res.data as ConfigMaze;
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
@@ -35,15 +26,7 @@ export async function getConfigMazeApi(): Promise<ConfigMaze> {
export async function getMainAffixApi(): Promise<Record<string, Record<string, AffixDetail>>> {
try {
const res = await axios.get<Record<string, Record<string, AffixDetail>>>(
`/api/main-affixes`,
{
headers: {
'Content-Type': 'application/json',
},
}
);
const res = await axios.get<Record<string, Record<string, AffixDetail>>>(`/data/main_affixes.json`);
return res.data as Record<string, Record<string, AffixDetail>>;
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
@@ -57,14 +40,7 @@ export async function getMainAffixApi(): Promise<Record<string, Record<string, A
export async function getSubAffixApi(): Promise<Record<string, Record<string, AffixDetail>>> {
try {
const res = await axios.get<Record<string, Record<string, AffixDetail>>>(
`/api/sub-affixes`,
{
headers: {
'Content-Type': 'application/json',
},
}
);
const res = await axios.get<Record<string, Record<string, AffixDetail>>>(`/data/sub_affixes.json`);
return res.data as Record<string, Record<string, AffixDetail>>;
} catch (error: unknown) {
@@ -77,19 +53,15 @@ export async function getSubAffixApi(): Promise<Record<string, Record<string, Af
}
}
export async function fetchCharacterByIdNative(id: string, locale: string): Promise<CharacterDetail | null> {
export async function fetchCharactersApi(locale: string): Promise<Record<string, CharacterDetail>> {
try {
const res = await axios.get<CharacterDetail>(`/api/${locale}/characters/${id}`);
return res.data;
} catch (error) {
console.error('Failed to fetch character:', error);
return null;
}
}
export async function fetchCharactersByIdsNative(ids: string[], locale: string): Promise<Record<string, CharacterDetail>> {
try {
const res = await axios.post<Record<string, CharacterDetail>>(`/api/${locale}/characters`, { charIds: ids });
const res = await axios.get<Record<string, CharacterDetail>>(`/data/characters.${locale}.json`);
const resIcon = await axios.get<Record<string, string[]>>(`/data/rank_icon.json`);
for (const [key, char] of Object.entries(res.data)) {
if (resIcon.data[key]) {
char.RankIcon = resIcon.data[key];
}
}
return res.data;
} catch (error) {
console.error('Failed to fetch characters:', error);
@@ -97,19 +69,15 @@ export async function fetchCharactersByIdsNative(ids: string[], locale: string):
}
}
export async function fetchLightconeByIdNative(id: string, locale: string): Promise<LightConeDetail | null> {
export async function fetchLightconesApi(locale: string): Promise<Record<string, LightConeDetail>> {
try {
const res = await axios.get<LightConeDetail>(`/api/${locale}/lightcones/${id}`);
return res.data;
} catch (error) {
console.error('Failed to fetch lightcone:', error);
return null;
}
}
export async function fetchLightconesByIdsNative(ids: string[], locale: string): Promise<Record<string, LightConeDetail>> {
try {
const res = await axios.post<Record<string, LightConeDetail>>(`/api/${locale}/lightcones`, { lightconeIds: ids });
const res = await axios.get<Record<string, LightConeDetail>>(`/data/lightcones.${locale}.json`);
const resBonus = await axios.get<Record<string, Record<string, { type: string, value: number }[]>>>('/data/lightcone_bonus.json');
for (const [key, relic] of Object.entries(res.data)) {
if (resBonus.data[key]) {
relic.Bonus = resBonus.data[key];
}
}
return res.data;
} catch (error) {
console.error('Failed to fetch lightcones:', error);
@@ -117,19 +85,15 @@ export async function fetchLightconesByIdsNative(ids: string[], locale: string):
}
}
export async function fetchRelicByIdNative(id: string, locale: string): Promise<RelicDetail | null> {
export async function fetchRelicsApi(locale: string): Promise<Record<string, RelicDetail>> {
try {
const res = await axios.get<RelicDetail>(`/api/${locale}/relics/${id}`);
return res.data;
} catch (error) {
console.error('Failed to fetch relic:', error);
return null;
}
}
export async function fetchRelicsByIdsNative(ids: string[], locale: string): Promise<Record<string, RelicDetail>> {
try {
const res = await axios.post<Record<string, RelicDetail>>(`/api/${locale}/relics`, { relicIds: ids });
const res = await axios.get<Record<string, RelicDetail>>(`/data/relics.${locale}.json`);
const resBonus = await axios.get<Record<string, Record<string, { type: string, value: number }[]>>>('/data/relic_bonus.json');
for (const [key, relic] of Object.entries(res.data)) {
if (resBonus.data[key]) {
relic.Bonus = resBonus.data[key];
}
}
return res.data;
} catch (error) {
console.error('Failed to fetch relics:', error);
@@ -137,9 +101,9 @@ export async function fetchRelicsByIdsNative(ids: string[], locale: string): Pro
}
}
export async function fetchASByIdsNative(ids: string[], locale: string): Promise<Record<string, ASDetail> | null> {
export async function fetchASEventApi(locale: string): Promise<Record<string, ASDetail> | null> {
try {
const res = await axios.post<Record<string, ASDetail>>(`/api/${locale}/as`, { asIds: ids });
const res = await axios.get<Record<string, ASDetail>>(`/data/as.${locale}.json`);
return res.data;
} catch (error) {
console.error('Failed to fetch AS:', error);
@@ -147,19 +111,9 @@ export async function fetchASByIdsNative(ids: string[], locale: string): Promise
}
}
export async function fetchASByIdNative(ids: string, locale: string): Promise<ASDetail | null> {
export async function fetchPFEventApi(locale: string): Promise<Record<string, PFDetail> | null> {
try {
const res = await axios.get<ASDetail>(`/api/${locale}/as/${ids}`);
return res.data;
} catch (error) {
console.error('Failed to fetch AS:', error);
return null;
}
}
export async function fetchPFByIdsNative(ids: string[], locale: string): Promise<Record<string, PFDetail> | null> {
try {
const res = await axios.post<Record<string, PFDetail>>(`/api/${locale}/pf`, { pfIds: ids });
const res = await axios.get<Record<string, PFDetail>>(`/data/pf.${locale}.json`);
return res.data;
} catch (error) {
console.error('Failed to fetch PF:', error);
@@ -167,19 +121,9 @@ export async function fetchPFByIdsNative(ids: string[], locale: string): Promise
}
}
export async function fetchPFByIdNative(ids: string, locale: string): Promise<PFDetail | null> {
export async function fetchMOCEventApi(locale: string): Promise<Record<string, MocDetail[]> | null> {
try {
const res = await axios.get<PFDetail>(`/api/${locale}/pf/${ids}`);
return res.data;
} catch (error) {
console.error('Failed to fetch PF:', error);
return null;
}
}
export async function fetchMOCByIdsNative(ids: string[], locale: string): Promise<Record<string, MocDetail[]> | null> {
try {
const res = await axios.post<Record<string, MocDetail[]>>(`/api/${locale}/moc`, { mocIds: ids });
const res = await axios.get<Record<string, MocDetail[]>>(`/data/moc.${locale}.json`);
return res.data;
} catch (error) {
console.error('Failed to fetch MOC:', error);
@@ -187,19 +131,9 @@ export async function fetchMOCByIdsNative(ids: string[], locale: string): Promis
}
}
export async function fetchMOCByIdNative(ids: string, locale: string): Promise<MocDetail[] | null> {
export async function fetchPeakEventApi(locale: string): Promise<Record<string, PeakDetail> | null> {
try {
const res = await axios.get<MocDetail[]>(`/api/${locale}/moc/${ids}`);
return res.data;
} catch (error) {
console.error('Failed to fetch MOC:', error);
return null;
}
}
export async function fetchPeakByIdsNative(ids: string[], locale: string): Promise<Record<string, PeakDetail> | null> {
try {
const res = await axios.post<Record<string, PeakDetail>>(`/api/${locale}/peak`, { peakIds: ids });
const res = await axios.get<Record<string, PeakDetail>>(`/data/peak.${locale}.json`);
return res.data;
} catch (error) {
console.error('Failed to fetch peak:', error);
@@ -207,29 +141,9 @@ export async function fetchPeakByIdsNative(ids: string[], locale: string): Promi
}
}
export async function fetchPeakByIdNative(ids: string, locale: string): Promise<PeakDetail | null> {
export async function fetchMonstersApi(locale: string): Promise<Record<string, MonsterDetail> | null> {
try {
const res = await axios.get<PeakDetail>(`/api/${locale}/peak/${ids}`);
return res.data;
} catch (error) {
console.error('Failed to fetch peak:', error);
return null;
}
}
export async function fetchMonsterByIdsNative(ids: string[], locale: string): Promise<Record<string, MonsterDetail> | null> {
try {
const res = await axios.post<Record<string, MonsterDetail>>(`/api/${locale}/monster`, { monsterIds: ids });
return res.data;
} catch (error) {
console.error('Failed to fetch monster:', error);
return null;
}
}
export async function fetchMonsterByIdNative(ids: string, locale: string): Promise<MonsterDetail | null> {
try {
const res = await axios.get<MonsterDetail>(`/api/${locale}/monster/${ids}`);
const res = await axios.get<Record<string, MonsterDetail>>(`/data/monsters.${locale}.json`);
return res.data;
} catch (error) {
console.error('Failed to fetch monster:', error);

View File

@@ -1,32 +0,0 @@
import { AffixDetail } from '@/types';
import fs from 'fs';
import path from 'path';
const DATA_DIR = path.join(process.cwd(), 'data');
let mainAffixCache: Record<string, Record<string, AffixDetail>> = {};
let subAffixCache: Record<string, Record<string, AffixDetail>> = {};
const mainAffixPath = path.join(DATA_DIR, `main_affixes.json`)
const subAffixPath = path.join(DATA_DIR, `sub_affixes.json`)
function loadFromFileIfExists(filePath: string): Record<string, Record<string, AffixDetail>> {
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, Record<string, AffixDetail>>;
return data;
}
return {};
}
export async function loadMainAffix(): Promise<Record<string, Record<string, AffixDetail>>> {
if (Object.keys(mainAffixCache).length > 0) return mainAffixCache;
const fileData = loadFromFileIfExists(mainAffixPath);
mainAffixCache = fileData;
return fileData;
}
export async function loadSubAffix(): Promise<Record<string, Record<string, AffixDetail>>> {
if (Object.keys(subAffixCache).length > 0) return subAffixCache;
const fileData = loadFromFileIfExists(subAffixPath);
subAffixCache = fileData;
return fileData;
}

View File

@@ -1,52 +0,0 @@
import fs from 'fs';
import path from 'path';
import { ASDetail } from '@/types';
import { getASEventInfoApi } from '../api';
const DATA_DIR = path.join(process.cwd(), 'data');
const asFileCache: Record<string, Record<string, ASDetail>> = {};
export let asMap: Record<string, ASDetail> = {};
function getJsonFilePath(locale: string): string {
return path.join(DATA_DIR, `as.${locale}.json`);
}
function loadFromFileIfExists(locale: string): Record<string, ASDetail> | null {
if (asFileCache[locale]) return asFileCache[locale];
const filePath = getJsonFilePath(locale);
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, ASDetail>;
asFileCache[locale] = data;
return data;
}
return null;
}
export async function loadAS(charIds: string[], locale: string): Promise<Record<string, ASDetail>> {
const fileData = loadFromFileIfExists(locale);
const fileIds = fileData ? Object.keys(fileData) : [];
if (fileData && charIds.every(id => fileIds.includes(id))) {
asMap = fileData;
return asMap;
}
const result: Record<string, ASDetail> = {};
await Promise.all(
charIds.map(async id => {
const info = await getASEventInfoApi(Number(id), locale);
if (info) result[id] = info;
})
);
fs.mkdirSync(DATA_DIR, { recursive: true });
const filePath = getJsonFilePath(locale);
fs.writeFileSync(filePath, JSON.stringify(result), 'utf-8');
asFileCache[locale] = result;
asMap = result;
return result;
}

View File

@@ -1,63 +0,0 @@
import fs from 'fs';
import path from 'path';
import { CharacterDetail } from '@/types/characterDetail';
import { getCharacterInfoApi } from '../api';
const DATA_DIR = path.join(process.cwd(), 'data');
const characterFileCache: Record<string, Record<string, CharacterDetail>> = {};
export let characterMap: Record<string, CharacterDetail> = {};
export let rankIconMap: Record<string, string[]> = {};
function getJsonFilePath(locale: string): string {
return path.join(DATA_DIR, `characters.${locale}.json`);
}
function loadFromFileIfExists(locale: string): Record<string, CharacterDetail> | null {
if (characterFileCache[locale]) return characterFileCache[locale];
const filePath = getJsonFilePath(locale);
const fileRankIconPath = path.join(DATA_DIR, `rank_icon.json`);
if (fs.existsSync(fileRankIconPath)) {
const data = JSON.parse(fs.readFileSync(fileRankIconPath, 'utf-8')) as Record<string, string[]>;
rankIconMap = data;
}
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, CharacterDetail>;
Object.keys(data).forEach((key) => {
data[key].RankIcon = rankIconMap[key] || [];
});
characterFileCache[locale] = data;
return data;
}
return null;
}
export async function loadCharacters(charIds: string[], locale: string): Promise<Record<string, CharacterDetail>> {
const fileData = loadFromFileIfExists(locale);
const fileIds = fileData ? Object.keys(fileData) : [];
if (fileData && charIds.every(id => fileIds.includes(id))) {
characterMap = fileData;
return characterMap;
}
const result: Record<string, CharacterDetail> = {};
await Promise.all(
charIds.map(async id => {
const info = await getCharacterInfoApi(Number(id), locale);
if (info){
info.RankIcon = rankIconMap[id] || [];
result[id] = info;
}
})
);
fs.mkdirSync(DATA_DIR, { recursive: true });
const filePath = getJsonFilePath(locale);
fs.writeFileSync(filePath, JSON.stringify(result), 'utf-8');
characterFileCache[locale] = result;
characterMap = result;
return result;
}

View File

@@ -1,23 +0,0 @@
import { ConfigMaze } from "@/types";
import fs from 'fs';
import path from "path";
const DATA_DIR = path.join(process.cwd(), 'data');
export let configMazeMap: Record<string, ConfigMaze> = {};
function loadFromFileIfExists(): Record<string, ConfigMaze> | null {
const filePath = path.join(DATA_DIR, 'config_maze.json');
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, ConfigMaze>;
configMazeMap = data;
return data;
}
return null;
}
export async function loadConfigMaze(): Promise<Record<string, ConfigMaze>> {
if (Object.keys(configMazeMap).length > 0) return configMazeMap;
const fileData = loadFromFileIfExists();
return fileData || {};
}

View File

@@ -1,10 +0,0 @@
export * from "./characterLoader";
export * from "./lighconeLoader";
export * from "./affixLoader";
export * from "./configMazeLoader";
export * from "./relicLoader";
export * from "./asLoader";
export * from "./pfLoader";
export * from "./mocLoader";
export * from "./peakLoader";
export * from "./monsterLoader";

View File

@@ -1,64 +0,0 @@
import fs from 'fs';
import path from 'path';
import { getLightconeInfoApi } from '../api';
import { LightConeDetail } from '@/types';
const DATA_DIR = path.join(process.cwd(), 'data');
const lightconeFileCache: Record<string, Record<string, LightConeDetail>> = {};
export let lightconeMap: Record<string, LightConeDetail> = {};
export let lightconeBonusMap: Record<string, Record<string, { type: string, value: number }[]>> = {};
function getJsonFilePath(locale: string): string {
return path.join(DATA_DIR, `lightcones.${locale}.json`);
}
function loadLightconeFromFileIfExists(locale: string): Record<string, LightConeDetail> | null {
if (lightconeFileCache[locale]) return lightconeFileCache[locale];
const filePath = getJsonFilePath(locale);
const fileBonusPath = path.join(DATA_DIR, `lightcone_bonus.json`);
if (fs.existsSync(fileBonusPath)) {
const data = JSON.parse(fs.readFileSync(fileBonusPath, 'utf-8')) as Record<string, Record<string, { type: string, value: number }[]>>;
lightconeBonusMap = data;
}
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, LightConeDetail>;
Object.keys(data).forEach((key) => {
data[key].Bonus = lightconeBonusMap[key] || {};
});
lightconeFileCache[locale] = data;
return data;
}
return null;
}
export async function loadLightcones(charIds: string[], locale: string): Promise<Record<string, LightConeDetail>> {
const fileData = loadLightconeFromFileIfExists(locale);
const fileIds = fileData ? Object.keys(fileData) : [];
if (fileData && charIds.every(id => fileIds.includes(id))) {
lightconeMap = fileData;
return lightconeMap;
}
const result: Record<string, LightConeDetail> = {};
await Promise.all(
charIds.map(async id => {
const info = await getLightconeInfoApi(Number(id), locale);
if (info) {
info.Bonus = lightconeBonusMap[id] || {};
result[id] = info;
}
})
);
fs.mkdirSync(DATA_DIR, { recursive: true });
const filePath = getJsonFilePath(locale);
fs.writeFileSync(filePath, JSON.stringify(result), 'utf-8');
lightconeFileCache[locale] = result;
lightconeMap = result;
return result;
}

View File

@@ -1,51 +0,0 @@
import fs from 'fs';
import path from 'path';
import { MocDetail } from '@/types';
import { getMOCEventInfoApi } from '../api';
const DATA_DIR = path.join(process.cwd(), 'data');
const mocFileCache: Record<string, Record<string, MocDetail[]>> = {};
export let mocMap: Record<string, MocDetail[]> = {};
function getJsonFilePath(locale: string): string {
return path.join(DATA_DIR, `moc.${locale}.json`);
}
function loadFromFileIfExists(locale: string): Record<string, MocDetail[]> | null {
if (mocFileCache[locale]) return mocFileCache[locale];
const filePath = getJsonFilePath(locale);
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, MocDetail[]>;
mocFileCache[locale] = data;
return data;
}
return null;
}
export async function loadMOC(charIds: string[], locale: string): Promise<Record<string, MocDetail[]>> {
const fileData = loadFromFileIfExists(locale);
const fileIds = fileData ? Object.keys(fileData) : [];
if (fileData && charIds.every(id => fileIds.includes(id))) {
mocMap = fileData;
return mocMap;
}
const result: Record<string, MocDetail[]> = {};
await Promise.all(
charIds.map(async id => {
const info = await getMOCEventInfoApi(Number(id), locale);
if (info) result[id] = info;
})
);
fs.mkdirSync(DATA_DIR, { recursive: true });
const filePath = getJsonFilePath(locale);
fs.writeFileSync(filePath, JSON.stringify(result), 'utf-8');
mocFileCache[locale] = result;
mocMap = result;
return result;
}

View File

@@ -1,51 +0,0 @@
import fs from 'fs';
import path from 'path';
import { MonsterDetail } from '@/types';
import { getMonsterDetailApi } from '../api';
const DATA_DIR = path.join(process.cwd(), 'data');
const monsterFileCache: Record<string, Record<string, MonsterDetail>> = {};
export let monsterMap: Record<string, MonsterDetail> = {};
function getJsonFilePath(locale: string): string {
return path.join(DATA_DIR, `monster.${locale}.json`);
}
function loadFromFileIfExists(locale: string): Record<string, MonsterDetail> | null {
if (monsterFileCache[locale]) return monsterFileCache[locale];
const filePath = getJsonFilePath(locale);
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, MonsterDetail>;
monsterFileCache[locale] = data;
return data;
}
return null;
}
export async function loadMonster(charIds: string[], locale: string): Promise<Record<string, MonsterDetail>> {
const fileData = loadFromFileIfExists(locale);
const fileIds = fileData ? Object.keys(fileData) : [];
if (fileData && charIds.every(id => fileIds.includes(id))) {
monsterMap = fileData;
return monsterMap;
}
const result: Record<string, MonsterDetail> = {};
await Promise.all(
charIds.map(async id => {
const info = await getMonsterDetailApi(Number(id), locale);
if (info) result[id] = info;
})
);
fs.mkdirSync(DATA_DIR, { recursive: true });
const filePath = getJsonFilePath(locale);
fs.writeFileSync(filePath, JSON.stringify(result), 'utf-8');
monsterFileCache[locale] = result;
monsterMap = result;
return result;
}

View File

@@ -1,51 +0,0 @@
import fs from 'fs';
import path from 'path';
import { PeakDetail } from '@/types';
import { getPeakEventInfoApi } from '../api';
const DATA_DIR = path.join(process.cwd(), 'data');
const peakFileCache: Record<string, Record<string, PeakDetail>> = {};
export let peakMap: Record<string, PeakDetail> = {};
function getJsonFilePath(locale: string): string {
return path.join(DATA_DIR, `peak.${locale}.json`);
}
function loadFromFileIfExists(locale: string): Record<string, PeakDetail> | null {
if (peakFileCache[locale]) return peakFileCache[locale];
const filePath = getJsonFilePath(locale);
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, PeakDetail>;
peakFileCache[locale] = data;
return data;
}
return null;
}
export async function loadPeak(charIds: string[], locale: string): Promise<Record<string, PeakDetail>> {
const fileData = loadFromFileIfExists(locale);
const fileIds = fileData ? Object.keys(fileData) : [];
if (fileData && charIds.every(id => fileIds.includes(id))) {
peakMap = fileData;
return peakMap;
}
const result: Record<string, PeakDetail> = {};
await Promise.all(
charIds.map(async id => {
const info = await getPeakEventInfoApi(Number(id), locale);
if (info) result[id] = info;
})
);
fs.mkdirSync(DATA_DIR, { recursive: true });
const filePath = getJsonFilePath(locale);
fs.writeFileSync(filePath, JSON.stringify(result), 'utf-8');
peakFileCache[locale] = result;
peakMap = result;
return result;
}

View File

@@ -1,51 +0,0 @@
import fs from 'fs';
import path from 'path';
import { PFDetail } from '@/types';
import { getPFEventInfoApi } from '../api';
const DATA_DIR = path.join(process.cwd(), 'data');
const pfFileCache: Record<string, Record<string, PFDetail>> = {};
export let pfMap: Record<string, PFDetail> = {};
function getJsonFilePath(locale: string): string {
return path.join(DATA_DIR, `pf.${locale}.json`);
}
function loadFromFileIfExists(locale: string): Record<string, PFDetail> | null {
if (pfFileCache[locale]) return pfFileCache[locale];
const filePath = getJsonFilePath(locale);
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, PFDetail>;
pfFileCache[locale] = data;
return data;
}
return null;
}
export async function loadPF(charIds: string[], locale: string): Promise<Record<string, PFDetail>> {
const fileData = loadFromFileIfExists(locale);
const fileIds = fileData ? Object.keys(fileData) : [];
if (fileData && charIds.every(id => fileIds.includes(id))) {
pfMap = fileData;
return pfMap;
}
const result: Record<string, PFDetail> = {};
await Promise.all(
charIds.map(async id => {
const info = await getPFEventInfoApi(Number(id), locale);
if (info) result[id] = info;
})
);
fs.mkdirSync(DATA_DIR, { recursive: true });
const filePath = getJsonFilePath(locale);
fs.writeFileSync(filePath, JSON.stringify(result), 'utf-8');
pfFileCache[locale] = result;
pfMap = result;
return result;
}

View File

@@ -1,62 +0,0 @@
import fs from 'fs';
import path from 'path';
import { RelicDetail } from '@/types';
import { getRelicInfoApi } from '../api';
const DATA_DIR = path.join(process.cwd(), 'data');
const relicFileCache: Record<string, Record<string, RelicDetail>> = {};
export let relicMap: Record<string, RelicDetail> = {};
export let relicBonusMap: Record<string, Record<string, { type: string, value: number }[]>> = {};
function getJsonFilePath(locale: string): string {
return path.join(DATA_DIR, `relics.${locale}.json`);
}
function loadRelicFromFileIfExists(locale: string): Record<string, RelicDetail> | null {
if (relicFileCache[locale]) return relicFileCache[locale];
const filePath = getJsonFilePath(locale);
const fileBonusPath = path.join(DATA_DIR, `relic_bonus.json`);
if (fs.existsSync(fileBonusPath)) {
const data = JSON.parse(fs.readFileSync(fileBonusPath, 'utf-8')) as Record<string, Record<string, { type: string, value: number }[]>>;
relicBonusMap = data;
}
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, RelicDetail>;
Object.keys(data).forEach((key) => {
data[key].Bonus = relicBonusMap[key] || {};
});
relicFileCache[locale] = data;
return data;
}
return null;
}
export async function loadRelics(charIds: string[], locale: string): Promise<Record<string, RelicDetail>> {
const fileData = loadRelicFromFileIfExists(locale);
const fileIds = fileData ? Object.keys(fileData) : [];
if (fileData && charIds.every(id => fileIds.includes(id))) {
relicMap = fileData;
return relicMap;
}
const result: Record<string, RelicDetail> = {};
await Promise.all(
charIds.map(async id => {
const info = await getRelicInfoApi(Number(id), locale);
if (info) {
info.Bonus = relicBonusMap[id] || {};
result[id] = info;
}
})
);
fs.mkdirSync(DATA_DIR, { recursive: true });
const filePath = getJsonFilePath(locale);
fs.writeFileSync(filePath, JSON.stringify(result), 'utf-8');
relicFileCache[locale] = result;
relicMap = result;
return result;
}

View File

@@ -16,4 +16,4 @@ export interface RelicDetail {
RequireNum: Record<string, RequireBonus>;
Bonus: Record<string, { type: string, value: number }[]>
}