add character/summon series to entity adapter and queries

This commit is contained in:
Justin Edmund 2025-12-14 11:59:31 -08:00
parent d921d37362
commit 50ee6b80ff
3 changed files with 251 additions and 5 deletions

View file

@ -91,7 +91,11 @@ describe('EntityAdapter', () => {
},
rarity: 5,
element: 0,
series: 2,
series: {
id: 'series-1',
slug: 'optimus',
name: { en: 'Optimus Series', ja: 'オプティマスシリーズ' }
},
minHp: 200,
maxHp: 1000,
minAttack: 300,

View file

@ -17,6 +17,18 @@ import type {
CreateWeaponSeriesPayload,
UpdateWeaponSeriesPayload
} from '$lib/types/api/weaponSeries'
import type {
CharacterSeriesRef,
CharacterSeries,
CreateCharacterSeriesPayload,
UpdateCharacterSeriesPayload
} from '$lib/types/api/characterSeries'
import type {
SummonSeriesRef,
SummonSeries,
CreateSummonSeriesPayload,
UpdateSummonSeriesPayload
} from '$lib/types/api/summonSeries'
/**
* Canonical weapon data from the game
@ -132,8 +144,8 @@ export interface Character {
season?: number | null
/** Human-readable season name */
seasonName?: string | null
/** Series integer array (1=Standard, 2=Grand, 3=Zodiac, etc.) */
series?: number[]
/** Series - array of objects with slug/name or legacy integers */
series?: CharacterSeriesRef[] | number[]
/** Human-readable series names */
seriesNames?: string[]
/** Whether character can be pulled from gacha */
@ -228,7 +240,8 @@ export interface Summon {
}
rarity: number
element: number
series?: number
/** Series - object with slug/name or null */
series?: SummonSeriesRef | null
/** Gacha promotions (1=Premium, 2=Classic, 3=ClassicII, 4=Flash, 5=Legend, etc.) */
promotions?: number[]
/** Human-readable promotion names */
@ -1297,6 +1310,171 @@ export class EntityAdapter extends BaseAdapter {
clearWeaponSeriesCache() {
this.clearCache('/weapon_series')
}
// ============================================================
// CHARACTER SERIES METHODS
// ============================================================
/**
* Gets all character series, sorted by order
* Returns list view with basic info (no character count)
*/
async getCharacterSeriesList(): Promise<CharacterSeries[]> {
return this.request<CharacterSeries[]>('/character_series', {
method: 'GET',
cacheTTL: 3600000 // Cache for 1 hour - rarely changes
})
}
/**
* Gets a single character series by ID or slug
* Returns full view with character count
*
* @param idOrSlug - UUID or slug (e.g., 'grand')
*/
async getCharacterSeries(idOrSlug: string): Promise<CharacterSeries> {
return this.request<CharacterSeries>(`/character_series/${idOrSlug}`, {
method: 'GET',
cacheTTL: 3600000 // Cache for 1 hour
})
}
/**
* Creates a new character series
* Requires editor role (>= 7)
*/
async createCharacterSeries(payload: CreateCharacterSeriesPayload): Promise<CharacterSeries> {
const result = await this.request<CharacterSeries>('/character_series', {
method: 'POST',
body: { character_series: payload }
})
// Clear character series cache
this.clearCache('/character_series')
return result
}
/**
* Updates an existing character series
* Requires editor role (>= 7)
*
* @param id - Character series UUID
* @param payload - Fields to update
*/
async updateCharacterSeries(
id: string,
payload: UpdateCharacterSeriesPayload
): Promise<CharacterSeries> {
const result = await this.request<CharacterSeries>(`/character_series/${id}`, {
method: 'PATCH',
body: { character_series: payload }
})
// Clear character series cache
this.clearCache('/character_series')
return result
}
/**
* Deletes a character series
* Requires editor role (>= 7)
* Will fail if series has associated characters
*
* @param id - Character series UUID
*/
async deleteCharacterSeries(id: string): Promise<void> {
await this.request<void>(`/character_series/${id}`, {
method: 'DELETE'
})
// Clear character series cache
this.clearCache('/character_series')
}
/**
* Clears character series cache
*/
clearCharacterSeriesCache() {
this.clearCache('/character_series')
}
// ============================================================
// SUMMON SERIES METHODS
// ============================================================
/**
* Gets all summon series, sorted by order
* Returns list view with basic info (no summon count)
*/
async getSummonSeriesList(): Promise<SummonSeries[]> {
return this.request<SummonSeries[]>('/summon_series', {
method: 'GET',
cacheTTL: 3600000 // Cache for 1 hour - rarely changes
})
}
/**
* Gets a single summon series by ID or slug
* Returns full view with summon count
*
* @param idOrSlug - UUID or slug (e.g., 'magna')
*/
async getSummonSeries(idOrSlug: string): Promise<SummonSeries> {
return this.request<SummonSeries>(`/summon_series/${idOrSlug}`, {
method: 'GET',
cacheTTL: 3600000 // Cache for 1 hour
})
}
/**
* Creates a new summon series
* Requires editor role (>= 7)
*/
async createSummonSeries(payload: CreateSummonSeriesPayload): Promise<SummonSeries> {
const result = await this.request<SummonSeries>('/summon_series', {
method: 'POST',
body: { summon_series: payload }
})
// Clear summon series cache
this.clearCache('/summon_series')
return result
}
/**
* Updates an existing summon series
* Requires editor role (>= 7)
*
* @param id - Summon series UUID
* @param payload - Fields to update
*/
async updateSummonSeries(id: string, payload: UpdateSummonSeriesPayload): Promise<SummonSeries> {
const result = await this.request<SummonSeries>(`/summon_series/${id}`, {
method: 'PATCH',
body: { summon_series: payload }
})
// Clear summon series cache
this.clearCache('/summon_series')
return result
}
/**
* Deletes a summon series
* Requires editor role (>= 7)
* Will fail if series has associated summons
*
* @param id - Summon series UUID
*/
async deleteSummonSeries(id: string): Promise<void> {
await this.request<void>(`/summon_series/${id}`, {
method: 'DELETE'
})
// Clear summon series cache
this.clearCache('/summon_series')
}
/**
* Clears summon series cache
*/
clearSummonSeriesCache() {
this.clearCache('/summon_series')
}
}
/**

View file

@ -115,6 +115,64 @@ export const entityQueries = {
enabled: !!idOrSlug,
staleTime: 1000 * 60 * 60, // 1 hour
gcTime: 1000 * 60 * 60 * 24 // 24 hours
}),
/**
* All character series query options
* Returns list ordered by display order
*
* @returns Query options for fetching all character series
*/
characterSeriesList: () =>
queryOptions({
queryKey: ['characterSeries', 'list'] as const,
queryFn: () => entityAdapter.getCharacterSeriesList(),
staleTime: 1000 * 60 * 60, // 1 hour - rarely changes
gcTime: 1000 * 60 * 60 * 24 // 24 hours
}),
/**
* Single character series query options
*
* @param idOrSlug - Character series UUID or slug (e.g., 'grand')
* @returns Query options for fetching a single character series with full details
*/
characterSeries: (idOrSlug: string) =>
queryOptions({
queryKey: ['characterSeries', idOrSlug] as const,
queryFn: () => entityAdapter.getCharacterSeries(idOrSlug),
enabled: !!idOrSlug,
staleTime: 1000 * 60 * 60, // 1 hour
gcTime: 1000 * 60 * 60 * 24 // 24 hours
}),
/**
* All summon series query options
* Returns list ordered by display order
*
* @returns Query options for fetching all summon series
*/
summonSeriesList: () =>
queryOptions({
queryKey: ['summonSeries', 'list'] as const,
queryFn: () => entityAdapter.getSummonSeriesList(),
staleTime: 1000 * 60 * 60, // 1 hour - rarely changes
gcTime: 1000 * 60 * 60 * 24 // 24 hours
}),
/**
* Single summon series query options
*
* @param idOrSlug - Summon series UUID or slug (e.g., 'magna')
* @returns Query options for fetching a single summon series with full details
*/
summonSeries: (idOrSlug: string) =>
queryOptions({
queryKey: ['summonSeries', idOrSlug] as const,
queryFn: () => entityAdapter.getSummonSeries(idOrSlug),
enabled: !!idOrSlug,
staleTime: 1000 * 60 * 60, // 1 hour
gcTime: 1000 * 60 * 60 * 24 // 24 hours
})
}
@ -146,5 +204,11 @@ export const entityKeys = {
['weaponKeys', params?.seriesSlug, params?.slot, params?.group] as const,
weaponSeriesList: () => ['weaponSeries', 'list'] as const,
weaponSeries: (idOrSlug: string) => ['weaponSeries', idOrSlug] as const,
allWeaponSeries: () => ['weaponSeries'] as const
allWeaponSeries: () => ['weaponSeries'] as const,
characterSeriesList: () => ['characterSeries', 'list'] as const,
characterSeries: (idOrSlug: string) => ['characterSeries', idOrSlug] as const,
allCharacterSeries: () => ['characterSeries'] as const,
summonSeriesList: () => ['summonSeries', 'list'] as const,
summonSeries: (idOrSlug: string) => ['summonSeries', idOrSlug] as const,
allSummonSeries: () => ['summonSeries'] as const
}