Guides
Query builder basics
The query builder API lets you filter and look up the data of any module with readable, chainable method calls.
How it works
Every factory function (heroes(), buildings(), pets(), and so on) returns a query builder that wraps an array of typed data. Calling a filter method returns a new query builder with only the matching items. You finish the chain with a terminal method (get(), first(), find(), findByName(), search(), or count()) to extract results.
import { heroes } from 'whiteout-survival-data'
const results = heroes()
.byRarity('Legendary') // Filter to Legendary heroes
.byClass('Marksman') // Filter to Marksmen
.get() // Extract the array
Common filter patterns
Filter method names are specific to each module, but a few shapes repeat:
Filtering by category
Many modules group their entries by a category and expose byCategory():
import { buildings, items, research } from 'whiteout-survival-data'
const innerCity = buildings().byCategory('Inner City').get()
const speedups = items().byCategory('Speedups').get()
const battleResearch = research().byCategory('Battle').get()
Filtering by rarity
Heroes and pets filter by rarity:
import { heroes, pets } from 'whiteout-survival-data'
const legendaryHeroes = heroes().byRarity('Legendary').get()
const epicPets = pets().byRarity('Epic').get()
Filtering by troop type or class
import { heroes } from 'whiteout-survival-data'
const lancers = heroes().byClass('Lancer').get()
Filtering by level or tier
Tables that hold one row for each level or tier expose byLevel() or byTier():
import { heroWidgets, research } from 'whiteout-survival-data'
const levelThreeWidgets = heroWidgets().byLevel(3).get()
const tierOneResearch = research().byTier(1).get()
Filtering by server age
The server timeline filters by the age of a server in days:
import { serverTimeline } from 'whiteout-survival-data'
const unlockedAtDay100 = serverTimeline().unlockedAt(100).get()
const stillLockedAtDay100 = serverTimeline().lockedAt(100).get()
See each module page for its exact filter list.
Sorting
The query builders have no sort methods. Call get() and use the array sort method on a copy of the result:
import { heroes } from 'whiteout-survival-data'
const newestFirst = [...heroes().get()].sort(
(a, b) => b.generation - a.generation,
)
Combining operations
Branching from a shared base
Since every filter method returns a new instance, you can branch from any intermediate query without affecting the original:
import { heroes } from 'whiteout-survival-data'
const epicHeroes = heroes().byRarity('Epic')
const epicLancers = epicHeroes.byClass('Lancer').get()
const firstEpic = epicHeroes.first()
const total = epicHeroes.count()
// `epicHeroes` itself is unchanged and still holds all Epic heroes
Passing a custom source
Every factory function accepts an optional array, so you can wrap your own subset in the same query builder and keep chaining:
import { heroes, type Hero } from 'whiteout-survival-data'
const recentHeroes: Hero[] = heroes()
.get()
.filter((hero) => hero.generation >= 10)
const recentInfantry = heroes(recentHeroes).byClass('Infantry').get()
Collecting results
As an array
const allHeroes = heroes().get() // Hero[]
const names = heroes()
.get()
.map((hero) => hero.name) // string[]
First item only
const first = heroes().byClass('Lancer').first() // Hero | undefined
By ID, exact name, or partial name
const byId = heroes().find('smith') // Hero | undefined
const exact = heroes().findByName('Smith') // Hero | undefined
const partial = heroes().search('sm') // Hero[]
Count
const total = heroes().byRarity('Epic').count() // number
Common patterns
Building a lookup table
import { heroes } from 'whiteout-survival-data'
const heroMap = new Map(
heroes()
.get()
.map((hero) => [hero.id, hero]),
)
const smith = heroMap.get('smith')
Conditional filtering
import { heroes, type HeroClass, type HeroQuery } from 'whiteout-survival-data'
function queryHeroes(heroClass?: HeroClass, legendaryOnly?: boolean) {
let query: HeroQuery = heroes()
if (heroClass) {
query = query.byClass(heroClass)
}
if (legendaryOnly) {
query = query.byRarity('Legendary')
}
return query.get()
}
Nested level data
Buildings, research nodes, pets, and heroes carry their levels on the entity. Read them straight off the result, with no separate query:
import { buildings } from 'whiteout-survival-data'
const furnace = buildings().findByName('Furnace')!
const fireCrystalTen = furnace.levels.find((level) => level.label === 'FC 10')!
for (const cost of fireCrystalTen.cost) {
console.log(`${cost.count}x ${cost.name}`)
}
Next steps
- See TypeScript integration for type-safe querying
- Read the core concepts page for the
QueryBasepattern in depth - Browse individual module pages (for example Heroes and Buildings) for module-specific filters