Introduction

Core concepts

Every standard module in dinkum-data follows the same pattern: once you learn it here, you can use any module without reading its docs first.


One factory function per module

dinkum-data is organized into roughly 40 modules, each covering one category of Dinkum data: crops, animals, furniture, tools, and so on. Every module exports a factory function that returns a chainable query builder:

import { animals, crops, furniture } from 'dinkum-data'

animals() // AnimalQuery
crops() // CropQuery
furniture() // FurnitureQuery

Calling the factory with no arguments wraps the module's full dataset. You can also pass a pre-filtered array back in, which is how you branch a query without losing the original:

import { crops } from 'dinkum-data'

const summerCrops = crops().bySeason('Summer').get()

// Wrap an already-filtered array to keep chaining
const cheapSummerCrops = crops(summerCrops).sortByBaseSellPrice('asc').get()

The QueryBase pattern

Every standard query builder extends the QueryBase<T> abstract class. It provides six terminal methods that work identically across every module, plus module-specific filter and sort methods layered on top.

abstract class QueryBase<T extends { id: string; name: string }> {
  constructor(protected readonly data: T[])

  get(): T[]
  first(): T | undefined
  find(id: string): T | undefined
  findByName(name: string): T | undefined
  search(query: string): T[]
  count(): number
}

The generic constraint { id: string; name: string } means every item has at least an id and name field, which is what makes find(), findByName(), and search() work identically everywhere.


Terminal methods

Terminal methods end a query chain and return results.

get(): T[]

Returns all matching results as an array. This is the most common terminal method.

import { furniture } from 'dinkum-data'

const allFurniture = furniture().get()
const catalogueOnly = furniture().melvinsCatalogue().get()

first(): T | undefined

Returns the first result, or undefined if the query is empty.

import { animals } from 'dinkum-data'

const firstDomesticable = animals().domesticable().first()

find(id: string): T | undefined

Finds an item by its exact id field.

import { tools } from 'dinkum-data'

const byId = tools().find('metal_detector')

findByName(name: string): T | undefined

Finds an item by name using a case-insensitive exact match.

import { fish } from 'dinkum-data'

const sturgeon = fish().findByName('Sturgeon')

search(query: string): T[]

Filters to items whose name contains the given text, case-insensitive. Unlike findByName, this returns every partial match rather than a single exact one.

import { clothing } from 'dinkum-data'

const hats = clothing().search('hat').get()

count(): number

Returns the number of results without needing to separately measure the array.

import { crops } from 'dinkum-data'

const summerCropCount = crops().bySeason('Summer').count()

Immutable chaining

Every filter and sort method returns a new instance of that module's query builder. The original is never mutated, so you can safely branch from any point in a chain:

import { fish } from 'dinkum-data'

const rareFish = fish().byRarity('Rare')

// These two queries are completely independent
const rareInOcean = rareFish.byBiome('Ocean').get()
const mostValuable = rareFish.sortByBaseSellPrice().first()

// The original `rareFish` query is unchanged
const allRare = rareFish.get()

Modules without a query builder

Four modules don't follow this pattern, because their source data isn't a flat, filterable list:

  • Calendar: a fixed 112-day structure, accessed via calendar()
  • Daily Milestones: a fixed set of category-grouped arrays, accessed via dailyMilestones(), dailyMilestonesByCategory(), and allDailyMilestones()
  • Clothing Slots: a lookup table via clothingSlots() and clothingTypesForSlot()
  • Buff Icons: a lookup table via buffIcons()

Each of these still returns plain, fully-typed data. They just don't have .get(), .first(), and friends, since there's nothing to filter.


Putting it all together

Here's a complete example demonstrating factory functions, chaining, and terminal methods together:

import { animals, crops, furniture } from 'dinkum-data'

// Farm animals sorted by sell price
const bestFarmAnimals = animals()
  .byType('Farm Animal')
  .sortByBaseSellPrice()
  .get()

// A single crop, looked up by name
const watermelon = crops().findByName('Watermelon')!

// Everything in Melvin's Catalogue from a specific set
const cabinFurniture = furniture().melvinsCatalogue().bySet('Cabin Set').get()

console.log(`Best farm animal: ${bestFarmAnimals[0]?.name}`)
console.log(`Watermelon sells for ${watermelon.baseSellPrice} Dinks`)
console.log(`Cabin Set has ${cabinFurniture.length} catalogue pieces`)

Next steps

Previous
Installation