diff --git a/server/src/modules/leveling/lib/types.ts b/server/src/modules/leveling/lib/types.ts new file mode 100644 index 0000000..0d94ec4 --- /dev/null +++ b/server/src/modules/leveling/lib/types.ts @@ -0,0 +1,88 @@ +/** + * Shared types for the Level-Up pure-function library. + * No runtime dependencies — types only. + */ +import type { AbilityAbbreviation } from './apply-attribute-boost'; + +export type { AbilityAbbreviation }; + +/** PF2e proficiency ranks (mirrors Prisma `Proficiency` enum). */ +export type Proficiency = 'UNTRAINED' | 'TRAINED' | 'EXPERT' | 'MASTER' | 'LEGENDARY'; + +/** Numeric proficiency bonus per rank, for use in proficiencyBonus(rank, level) calculation. */ +export const PROFICIENCY_BASE_BONUS: Record = { + UNTRAINED: 0, + TRAINED: 2, + EXPERT: 4, + MASTER: 6, + LEGENDARY: 8, +}; + +/** Discriminated union for prereq evaluation result. */ +export type EvalResult = + | { ok: true } + | { ok: false; reason: string } + | { unknown: true; raw: string }; + +/** Ordered union of wizard step kinds (UI-SPEC + RESEARCH §Pattern 1). */ +export type StepKind = + | 'class-features' + | 'class-feature-choice' + | 'boost' + | 'skill-increase' + | 'feat-class' + | 'feat-skill' + | 'feat-general' + | 'feat-ancestry' + | 'feat-archetype' + | 'spellcaster' + | 'review'; + +/** Snapshot a character's mechanical state for prereq evaluation and recompute. */ +export interface CharacterContext { + level: number; + className: string; + ancestryName: string; + heritageName?: string; + abilities: Record; + skills: Record; + feats: Set; +} + +/** Output of recomputeDerivedStats — never includes hpCurrent (Pitfall #9). */ +export interface DerivedStats { + level: number; + hpMax: number; + ac: number; + classDc: number; + perception: number; + fortitude: number; + reflex: number; + will: number; +} + +/** ClassProgression row shape — read-only input to recompute pipeline. */ +export interface ClassProgressionRow { + className: string; + level: number; + grants: string[]; + proficiencyChanges: Partial>; + spellSlotIncrement?: { tradition: string; spellLevel: number; count: number } | null; + cantripIncrement?: number | null; + repertoireIncrement?: number | null; + choiceType?: string | null; + choiceOptionsRef?: string | null; +} + +/** Wizard choices subset — what the user picked across the wizard. */ +export interface WizardChoices { + boostTargets?: AbilityAbbreviation[]; + skillIncrease?: { skillName: string; toRank: Proficiency }; + featClassId?: string; + featSkillId?: string; + featGeneralId?: string; + featAncestryId?: string; + featArchetypeId?: string; + classFeatureChoices?: Record; + spellcasterRepertoirePicks?: string[]; +}