uesp-eso-build-wrapper 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +63 -257
  2. package/README.pt-BR.md +122 -0
  3. package/dist/lib/eso-engine/calculator.d.ts +26 -16
  4. package/dist/lib/eso-engine/calculator.d.ts.map +1 -1
  5. package/dist/lib/eso-engine/calculator.js +235 -202
  6. package/dist/lib/eso-engine/calculator.js.map +1 -1
  7. package/dist/lib/eso-engine/cp-gate.d.ts +70 -0
  8. package/dist/lib/eso-engine/cp-gate.d.ts.map +1 -0
  9. package/dist/lib/eso-engine/cp-gate.js +124 -0
  10. package/dist/lib/eso-engine/cp-gate.js.map +1 -0
  11. package/dist/lib/eso-engine/cp-tree.d.ts +24 -0
  12. package/dist/lib/eso-engine/cp-tree.d.ts.map +1 -0
  13. package/dist/lib/eso-engine/cp-tree.js +165 -0
  14. package/dist/lib/eso-engine/cp-tree.js.map +1 -0
  15. package/dist/lib/eso-engine/debug.d.ts +18 -15
  16. package/dist/lib/eso-engine/debug.d.ts.map +1 -1
  17. package/dist/lib/eso-engine/debug.js +17 -19
  18. package/dist/lib/eso-engine/debug.js.map +1 -1
  19. package/dist/lib/eso-engine/engine-globals.d.ts +176 -0
  20. package/dist/lib/eso-engine/engine-globals.d.ts.map +1 -0
  21. package/dist/lib/eso-engine/engine-globals.js +24 -0
  22. package/dist/lib/eso-engine/engine-globals.js.map +1 -0
  23. package/dist/lib/eso-engine/env-setup.d.ts +15 -15
  24. package/dist/lib/eso-engine/env-setup.d.ts.map +1 -1
  25. package/dist/lib/eso-engine/env-setup.js +42 -58
  26. package/dist/lib/eso-engine/env-setup.js.map +1 -1
  27. package/dist/lib/eso-engine/index.d.ts +33 -9
  28. package/dist/lib/eso-engine/index.d.ts.map +1 -1
  29. package/dist/lib/eso-engine/index.js +38 -64
  30. package/dist/lib/eso-engine/index.js.map +1 -1
  31. package/dist/lib/eso-engine/input-stats.js +2 -5
  32. package/dist/lib/eso-engine/input-stats.js.map +1 -1
  33. package/dist/lib/eso-engine/loader.d.ts +15 -15
  34. package/dist/lib/eso-engine/loader.d.ts.map +1 -1
  35. package/dist/lib/eso-engine/loader.js +116 -132
  36. package/dist/lib/eso-engine/loader.js.map +1 -1
  37. package/dist/lib/eso-engine/types.d.ts +189 -92
  38. package/dist/lib/eso-engine/types.d.ts.map +1 -1
  39. package/dist/lib/eso-engine/types.js +2 -3
  40. package/dist/lib/eso-engine/types.js.map +1 -1
  41. package/dist/lib/uesp-data/extract.d.ts +29 -0
  42. package/dist/lib/uesp-data/extract.d.ts.map +1 -0
  43. package/dist/lib/uesp-data/extract.js +348 -0
  44. package/dist/lib/uesp-data/extract.js.map +1 -0
  45. package/dist/lib/uesp-data/index.d.ts +14 -0
  46. package/dist/lib/uesp-data/index.d.ts.map +1 -0
  47. package/dist/lib/uesp-data/index.js +11 -0
  48. package/dist/lib/uesp-data/index.js.map +1 -0
  49. package/dist/lib/uesp-data/mariadb-dump.d.ts +32 -0
  50. package/dist/lib/uesp-data/mariadb-dump.d.ts.map +1 -0
  51. package/dist/lib/uesp-data/mariadb-dump.js +222 -0
  52. package/dist/lib/uesp-data/mariadb-dump.js.map +1 -0
  53. package/dist/lib/uesp-data/seed.d.ts +43 -0
  54. package/dist/lib/uesp-data/seed.d.ts.map +1 -0
  55. package/dist/lib/uesp-data/seed.js +450 -0
  56. package/dist/lib/uesp-data/seed.js.map +1 -0
  57. package/package.json +37 -13
package/README.md CHANGED
@@ -1,21 +1,53 @@
1
1
  # uesp-eso-build-wrapper
2
2
 
3
3
  [![CI](https://github.com/srtomy/uesp-eso-build-wrapper/actions/workflows/ci.yml/badge.svg)](https://github.com/srtomy/uesp-eso-build-wrapper/actions/workflows/ci.yml)
4
+ [![codecov](https://codecov.io/gh/srtomy/uesp-eso-build-wrapper/graph/badge.svg)](https://codecov.io/gh/srtomy/uesp-eso-build-wrapper)
4
5
  [![npm](https://img.shields.io/npm/v/uesp-eso-build-wrapper.svg)](https://www.npmjs.com/package/uesp-eso-build-wrapper)
6
+ [![Docs](https://img.shields.io/badge/docs-online-2564eb)](https://srtomy.github.io/uesp-eso-build-wrapper/)
7
+ [![Bundlephobia](https://img.shields.io/bundlephobia/minzip/uesp-eso-build-wrapper)](https://bundlephobia.com/package/uesp-eso-build-wrapper)
5
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
- [![Node >=20.12](https://img.shields.io/badge/node-%3E%3D20.12-brightgreen)](https://nodejs.org/en/download/)
9
+ [![Node >=24](https://img.shields.io/badge/node-%3E%3D24-brightgreen)](https://nodejs.org/en/download/)
10
+
11
+ > **Leia em [Português (BR)](README.pt-BR.md).**
7
12
 
8
13
  A Node.js/TypeScript wrapper around the [UESP ESO Build Editor](https://github.com/uesp/uesp-esochardata) math engine.
9
14
 
10
15
  Calculate Elder Scrolls Online **Computed Character Statistics** — Health, Magicka, Stamina, mitigation, crit chance, regeneration, and 200+ more — using UESP's own formulas. No formula reimplementation.
11
16
 
12
- ## Features
17
+ ## What is this?
18
+
19
+ This is **not an HTTP client for UESP**. It runs the vendored UESP build calculation engine **locally, inside your Node.js process**, and exposes the results through a typed API:
20
+
21
+ ```text
22
+ Application
23
+
24
+ uesp-eso-build-wrapper (TypeScript API)
25
+
26
+ Node.js compatibility layer (browser-like globals + minimal DOM)
27
+
28
+ UESP esoEditBuild.js (executed in-process via vm.runInThisContext)
29
+
30
+ UESP calculation functions → ComputedStats
31
+ ```
32
+
33
+ You inject the inputs, UESP's own code computes every stat, you read back one typed object.
34
+
35
+ ## Why this library?
13
36
 
14
- - **100% UESP formulas** — same engine powering [esobuilds.uesp.net](https://esobuilds.uesp.net)
15
- - **221 computed stats** — all `Computed Character Statistics` from the build editor
16
- - **Zero runtime dependencies** — pure Node.js
17
- - **Full TypeScript types** — typed inputs and outputs
18
- - **Singleton loader** — loads the engine once per process, fast on subsequent calls
37
+ - **Reference accuracy** — same `esoEditBuild.js` engine that powers [esobuilds.uesp.net](https://esobuilds.uesp.net), kept up to date by UESP every patch.
38
+ - **No formula reimplementation** — the wrapper contains zero ESO math. When a stat looks wrong after a patch, the fix is always in the game *data* fed to the engine, never in wrapper code. That is what keeps it correct across patches.
39
+ - **Local and synchronous** — `calculateBuild()` performs no network requests. The engine runs in-process; game data and items are supplied by your application (file, database, generated data).
40
+ - **Accepts UESP item data directly** — gear in the [`exportJson.php?table=minedItem`](https://esolog.uesp.net) format plugs straight into `BuildInput.items`.
41
+ - **TypeScript-native** — typed inputs/outputs, TSDoc-documented [API Reference](https://srtomy.github.io/uesp-eso-build-wrapper/api/), plus runtime catalog functions (`listAvailableBuffs`, `listRacialPassives`, …) to discover valid names.
42
+
43
+ ## Key properties
44
+
45
+ - Runs the vendored UESP calculation engine locally (`vendor/uesp-esochardata`)
46
+ - **No network required for build calculations** — see [Does it require an internet connection?](https://srtomy.github.io/uesp-eso-build-wrapper/architecture#does-it-require-an-internet-connection)
47
+ - Does not reimplement ESO stat formulas
48
+ - Synchronous API; engine initializes once per process (singleton, subsequent calls are no-ops)
49
+ - Zero runtime dependencies — pure Node.js
50
+ - 221 computed stats per build
19
51
 
20
52
  ## Installation
21
53
 
@@ -25,21 +57,18 @@ npm install uesp-eso-build-wrapper
25
57
 
26
58
  ## Quick Start
27
59
 
28
- Game data is not bundled in the npm package — you supply it via `initEsoEngineFromData`.
29
- The bundled `vendor/uesp-data/uesp-game-data.json` (committed to this repo) is the canonical source.
60
+ Game data is not bundled in the npm package — you supply it via `initEsoEngineFromData` (see [Getting Started](https://srtomy.github.io/uesp-eso-build-wrapper/getting-started)).
30
61
 
31
62
  ```ts
32
63
  import fs from 'fs';
33
64
  import { initEsoEngineFromData, calculateBuild } from 'uesp-eso-build-wrapper';
34
65
  import type { UespInitData } from 'uesp-eso-build-wrapper';
35
66
 
36
- // Load game data generated by: npm run generate-data -- --db /path/to/local.db
37
67
  const initData = JSON.parse(
38
- fs.readFileSync('vendor/uesp-data/uesp-game-data.json', 'utf-8')
68
+ fs.readFileSync('uesp-game-data.json', 'utf-8'),
39
69
  ) as UespInitData;
40
70
 
41
- // Initialize once per process (no-op on subsequent calls)
42
- initEsoEngineFromData({ initData });
71
+ initEsoEngineFromData({ initData }); // once per process
43
72
 
44
73
  const stats = calculateBuild({
45
74
  character: {
@@ -52,260 +81,37 @@ const stats = calculateBuild({
52
81
 
53
82
  console.log(stats.Health); // 16000
54
83
  console.log(stats.Magicka); // 19104
55
- console.log(stats.MagickaRegen); // 514
56
84
  console.log(stats.SpellDamage); // 1000
57
85
  ```
58
86
 
59
- ## With Equipped Items
60
-
61
- Items are passed directly as returned by the [UESP public item API](https://esolog.uesp.net/exportJson.php?table=minedItem&id=70&level=50&quality=5).
62
-
63
- ```ts
64
- const res = await fetch(
65
- 'https://esolog.uesp.net/exportJson.php?table=minedItem&id=70&level=50&quality=5',
66
- );
67
- const data = await res.json();
68
- const item = data.minedItem[0];
69
-
70
- const stats = calculateBuild({
71
- character: {
72
- race: 'Nord',
73
- class: 'Dragonknight',
74
- level: 50,
75
- attributes: { health: 64, magicka: 0, stamina: 0 },
76
- },
77
- items: {
78
- Chest: item,
79
- },
80
- });
81
-
82
- console.log(stats.Health); // includes item enchant + set bonus
83
- ```
84
-
85
- ## With Passives, Buffs, and Skill Bars
86
-
87
- ```ts
88
- const stats = calculateBuild({
89
- character: {
90
- race: 'High Elf',
91
- class: 'Sorcerer',
92
- level: 50,
93
- attributes: { health: 0, magicka: 64, stamina: 0 },
94
- mundusStone: 'The Apprentice',
95
- championPoints: 160,
96
- },
97
- // Auto-inject all racial passives at highest rank (mirrors UESP "Auto Purchase Racial Passives")
98
- autoPassives: true,
99
- // Named buffs from the UESP buff catalog
100
- activeBuffs: ['Major Prophecy', 'Minor Slayer', 'Major Sorcery'],
101
- // Active skills slotted on bars (affects conditional set bonuses and skill-line passives)
102
- skillBars: {
103
- bar1: [
104
- { skillId: 28807, morphIndex: 2 }, // Crystal Fragments
105
- { skillId: 24322 }, // Mages' Fury
106
- ],
107
- },
108
- });
109
- ```
110
-
111
- ## API
112
-
113
- ### `initEsoEngineFromData(options)`
114
-
115
- Initializes the UESP math engine from a `UespInitData` object. **Must be called once** before `calculateBuild()`.
87
+ ## How it works
116
88
 
117
- Safe to call multiple times only executes on the first call.
89
+ 1. `initEsoEngineFromData({ initData })` prepares browser-like globals, seeds the engine with your game data, and executes the vendored UESP scripts via `vm.runInThisContext` — once per process.
90
+ 2. `calculateBuild(input)` writes your build into the engine state, runs the engine's own `UpdateEsoComputedStatsList_Real()`, and reads results from `g_EsoComputedStats` into a typed `ComputedStats` object.
118
91
 
119
- | Option | Type | Description |
120
- | ---------- | -------------- | ---------------------------------------------- |
121
- | `initData` | `UespInitData` | Parsed game data (see `vendor/uesp-data/`) |
122
-
123
- ---
124
-
125
- ### `calculateBuild(input: BuildInput): ComputedStats`
126
-
127
- Runs the UESP engine and returns the computed stats.
128
-
129
- #### `BuildInput`
130
-
131
- ```ts
132
- interface BuildInput {
133
- character: {
134
- race: string; // "High Elf" | "Nord" | "Breton" | "Khajiit" | ...
135
- class: string; // "Sorcerer" | "Dragonknight" | "Nightblade" | ...
136
- level: number; // 1–50
137
- attributes: {
138
- health: number; // attribute points (max 64 total)
139
- magicka: number;
140
- stamina: number;
141
- };
142
- mundusStone?: string; // "The Thief" | "The Apprentice" | ...
143
- mundusStone2?: string; // second Mundus Stone (requires Twice-Born Star set)
144
- cyrodiil?: boolean; // Battle Spirit (PvP)
145
- vampireStage?: number; // 0–4
146
- werewolfStage?: number; // 0 or 1
147
- championPoints?: number; // 0–3600
148
- rulesVersion?: string; // "Live" (default) | "PTS"
149
- };
150
- items?: Partial<Record<EquipSlot, UespItemApiData>>;
151
- championPointNodes?: Record<string | number, ChampionPointNode>;
152
- activeBuffs?: string[]; // named buffs — see listAvailableBuffs()
153
- toggleSkills?: string[]; // toggled skills — see listAvailableToggleSkills()
154
- skillBars?: {
155
- bar1?: SkillSlot[];
156
- bar2?: SkillSlot[];
157
- };
158
- activeWeaponBar?: 1 | 2; // which weapon bar is active (default: 1)
159
- passiveSkills?: number[]; // ability IDs of unlocked passive skills
160
- autoPassives?: boolean; // auto-inject racial passives (default: false)
161
- enchantOverrides?: Partial<Record<string, { enchantDesc: string; enchantName?: string }>>;
162
- toggledSetBonuses?: string[];
163
- }
164
- ```
165
-
166
- #### `EquipSlot`
167
-
168
- ```
169
- Head | Shoulders | Chest | Hands | Legs | Waist | Feet |
170
- Neck | Ring1 | Ring2 |
171
- MainHand1 | OffHand1 | MainHand2 | OffHand2 |
172
- Poison1 | Poison2 | Food | Potion
173
- ```
92
+ Details: [Architecture](https://srtomy.github.io/uesp-eso-build-wrapper/architecture) · [Getting Started](https://srtomy.github.io/uesp-eso-build-wrapper/getting-started) · [Reading the Output](https://srtomy.github.io/uesp-eso-build-wrapper/output).
174
93
 
175
- #### `ComputedStats`
94
+ ## Documentation
176
95
 
177
- Key stats returned (see [`types.ts`](src/lib/eso-engine/types.ts) for the full list):
96
+ Full documentation is available in **English** and **Português (BR)** at
97
+ [**srtomy.github.io/uesp-eso-build-wrapper**](https://srtomy.github.io/uesp-eso-build-wrapper/):
178
98
 
179
- | Property | Description |
180
- | ------------------------------------------------------ | ----------------------------------------- |
181
- | `Health` / `Magicka` / `Stamina` | Maximum resource pools |
182
- | `HealthRegen` / `MagickaRegen` / `StaminaRegen` | Out-of-combat regeneration |
183
- | `WeaponDamage` / `SpellDamage` | Base damage |
184
- | `WeaponCrit` / `SpellCrit` | Critical chance |
185
- | `PhysicalResist` / `SpellResist` / `CritResist` | Resistances |
186
- | `PhysicalPenetration` / `SpellPenetration` | Armor penetration |
187
- | `DefensePhysicalMitigation` / `DefenseSpellMitigation` | Effective mitigation % |
188
- | `HealingDone` / `HealingTaken` | Healing modifiers |
189
- | `RunSpeed` / `SprintSpeed` | Movement speed |
190
- | `raw` | All 221 stats as `Record<string, number>` |
191
-
192
- > All stat IDs match `g_EsoComputedStats` from the UESP engine (version 49+).
193
-
194
- ---
195
-
196
- ### Catalog Functions
197
-
198
- | Function | Returns | Description |
199
- |---|---|---|
200
- | `listAvailableBuffs(group?)` | `BuffInfo[]` | 164 named buffs; filter by group `"Major"` \| `"Minor"` \| `"Set"` \| `"Target"` \| … |
201
- | `listRacialPassives(race)` | `PassiveSkillInfo[]` | All passive ranks for a given race |
202
- | `listClassPassives(cls)` | `PassiveSkillInfo[]` | All passive ranks for a given class (3 skill lines) |
203
- | `listPassivesBySkillLine(line)` | `PassiveSkillInfo[]` | Passives for any skill line (Heavy Armor, Undaunted, etc.) |
204
- | `listAvailableSkillLines()` | `string[]` | All available skill line names |
205
- | `listAvailableToggleSkills()` | `ToggleSkillInfo[]` | 105 toggle skills; `requiresCyrodiil` marks PvP-only |
206
-
207
- ```ts
208
- // Example: see all Major buffs
209
- const buffs = listAvailableBuffs('Major');
210
- // Example: find racial passive IDs for a High Elf build
211
- const passives = listRacialPassives('High Elf');
212
- const ids = passives.map(p => p.abilityId);
213
- ```
214
-
215
- ---
216
-
217
- ## Game Data
218
-
219
- Game data (`UespInitData`) is extracted from the UESP SQL dumps and stored in `vendor/uesp-data/uesp-game-data.json`.
220
- This file is committed to the repo but **not bundled in the npm package** — consumers are expected to supply their own copy or generate it.
221
-
222
- ### Generating game data
223
-
224
- Requires Node.js ≥ 22 (uses `node:sqlite`).
225
-
226
- ```bash
227
- npm run generate-data -- --db /path/to/local.db [--version 50]
228
- ```
229
-
230
- The script reads from `local.db` and writes to `vendor/uesp-data/uesp-game-data.json`.
231
- To populate `local.db`, use the seed script from [eso-build-editor](https://github.com/srtomy/eso-build-editor).
232
-
233
- ### Scripts
234
-
235
- | Command | Description |
236
- |---|---|
237
- | `npm run generate-data -- --db <path>` | Generate `vendor/uesp-data/uesp-game-data.json` from a SQLite DB |
238
- | `npm run test:db-init [json] [db] [version]` | Validate committed JSON matches a live DB |
239
- | `npm run test:build <export.json>` | Print all computed stats for a UESP build export |
240
- | `npm run test:explore` | Interactive engine exploration script |
241
-
242
- ---
243
-
244
- ## Validating Against the UESP Browser
245
-
246
- The `scripts/browser-export-build.js` script runs inside the UESP Build Editor DevTools console and exports the full build — inputs and expected stats — as a JSON file.
247
-
248
- **How to use:**
249
-
250
- 1. Open [esobuilds.uesp.net](https://esobuilds.uesp.net), configure your build
251
- 2. Open DevTools (F12) → Console, paste and run `browser-export-build.js`
252
- 3. A `uesp-build-export.json` file is downloaded
253
-
254
- **Explore stats interactively:**
255
-
256
- ```bash
257
- npm run test:build path/to/uesp-build-export.json
258
- ```
259
-
260
- **Add as a golden regression fixture:**
261
-
262
- ```bash
263
- cp path/to/uesp-build-export.json tests/fixtures/my-build.json
264
- npm test
265
- ```
266
-
267
- `tests/build-fixtures.test.ts` auto-discovers all `.json` files in `tests/fixtures/` and asserts every stat in `expectedStats` against the wrapper output.
268
-
269
- ---
270
-
271
- ## Updating Formulas After a New ESO Patch
272
-
273
- ```bash
274
- # 1. Update the UESP engine submodule
275
- cd vendor/uesp-esochardata
276
- git fetch upstream && git merge upstream/master
277
- cd ../..
278
-
279
- # 2. Regenerate game data from an up-to-date local.db
280
- # (populate local.db first via eso-build-editor's npm run db:seed)
281
- npm run generate-data -- --db /path/to/local.db --version <patch>
282
-
283
- # 3. Commit the updated game data
284
- git add vendor/uesp-data/uesp-game-data.json
285
-
286
- # 4. Run tests — update any golden values that changed intentionally
287
- npm test
288
- ```
289
-
290
- ## Framework Integration
291
-
292
- ### Next.js (Vercel / serverless)
293
-
294
- The vendor JS files (`esobuilddata.js`, `esoEditBuild.js`) are loaded at runtime via `fs.readFileSync` with a dynamic path. Next.js's output file tracer (`@vercel/nft`) cannot detect them automatically, so they must be declared explicitly in `next.config.ts`:
295
-
296
- ```ts
297
- // next.config.ts
298
- const nextConfig: NextConfig = {
299
- serverExternalPackages: ['uesp-eso-build-wrapper'],
300
- outputFileTracingIncludes: {
301
- '/**': ['./node_modules/uesp-eso-build-wrapper/vendor/**'],
302
- },
303
- };
304
- ```
99
+ | Section | Description |
100
+ | --- | --- |
101
+ | [Introduction](https://srtomy.github.io/uesp-eso-build-wrapper/) | What it is, why it exists, key properties |
102
+ | [Architecture](https://srtomy.github.io/uesp-eso-build-wrapper/architecture) | Local engine, network policy, data flow |
103
+ | [Getting Started](https://srtomy.github.io/uesp-eso-build-wrapper/getting-started) | Install, game data, first calculation |
104
+ | [Guides](https://srtomy.github.io/uesp-eso-build-wrapper/guides/character) | Character, items, Champion Points, buffs, skills |
105
+ | [Reading the Output](https://srtomy.github.io/uesp-eso-build-wrapper/output) | All 221 computed stats, `debugBuild()` |
106
+ | [API Reference](https://srtomy.github.io/uesp-eso-build-wrapper/api/) | Generated from source TSDoc |
107
+ | [Troubleshooting](https://srtomy.github.io/uesp-eso-build-wrapper/troubleshooting) | Common integration issues (Next.js/serverless, wrong stats...) |
108
+ | [Contributing](https://srtomy.github.io/uesp-eso-build-wrapper/contributing) | Dev setup, tests, updating after an ESO patch |
305
109
 
306
- Without this, the engine will throw at runtime in any serverless environment (Vercel, AWS Lambda, etc.) because the vendor files are not included in the deployment bundle.
110
+ ## Limitations
307
111
 
308
- ---
112
+ - Behavior follows the vendored UESP engine version — updating ESO patch support means updating the vendored scripts + game data and running the tests.
113
+ - The engine was written for browsers around global state; the wrapper adapts it to Node.js (singleton init, synchronous calls). No concurrency guarantees beyond what the engine itself provides — see [Troubleshooting](https://srtomy.github.io/uesp-eso-build-wrapper/troubleshooting).
114
+ - Requires Node.js >= 24. Bundlers/serverless need explicit `vendor/**` inclusion (documented in Troubleshooting).
309
115
 
310
116
  ## License
311
117
 
@@ -0,0 +1,122 @@
1
+ # uesp-eso-build-wrapper
2
+
3
+ [![CI](https://github.com/srtomy/uesp-eso-build-wrapper/actions/workflows/ci.yml/badge.svg)](https://github.com/srtomy/uesp-eso-build-wrapper/actions/workflows/ci.yml)
4
+ [![codecov](https://codecov.io/gh/srtomy/uesp-eso-build-wrapper/graph/badge.svg)](https://codecov.io/gh/srtomy/uesp-eso-build-wrapper)
5
+ [![npm](https://img.shields.io/npm/v/uesp-eso-build-wrapper.svg)](https://www.npmjs.com/package/uesp-eso-build-wrapper)
6
+ [![Docs](https://img.shields.io/badge/docs-online-2564eb)](https://srtomy.github.io/uesp-eso-build-wrapper/pt/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
+ [![Node >=24](https://img.shields.io/badge/node-%3E%3D24-brightgreen)](https://nodejs.org/en/download/)
9
+
10
+ > **Read in [English](README.md).**
11
+
12
+ Um wrapper Node.js/TypeScript em torno do motor de cálculo do [UESP ESO Build Editor](https://github.com/uesp/uesp-esochardata).
13
+
14
+ Calcule as **Computed Character Statistics** de Elder Scrolls Online — Health, Magicka, Stamina, mitigação, chance de crítico, regeneração e mais de 200 — usando as fórmulas da própria UESP. Sem reimplementar nenhuma fórmula.
15
+
16
+ ## O que é?
17
+
18
+ Isto **não é um cliente HTTP da UESP**. A biblioteca executa o motor de cálculo da UESP **localmente, dentro do seu processo Node.js**, e expõe os resultados numa API tipada:
19
+
20
+ ```text
21
+ Aplicação
22
+
23
+ uesp-eso-build-wrapper (API TypeScript)
24
+
25
+ Camada de compatibilidade Node.js (globals de browser + DOM mínimo)
26
+
27
+ UESP esoEditBuild.js (executado in-process via vm.runInThisContext)
28
+
29
+ Funções de cálculo UESP → ComputedStats
30
+ ```
31
+
32
+ Você injeta os inputs, o próprio código da UESP calcula cada stat, você lê de volta um objeto tipado.
33
+
34
+ ## Por que esta biblioteca?
35
+
36
+ - **Precisão de referência** — o mesmo motor `esoEditBuild.js` do [esobuilds.uesp.net](https://esobuilds.uesp.net), mantido pela UESP e atualizado a cada patch.
37
+ - **Sem reimplementar fórmulas** — o wrapper contém zero matemática de ESO. Quando um stat parece errado depois de um patch, a correção está sempre nos *dados* do jogo alimentados ao motor, nunca no código do wrapper. É isso que mantém a precisão entre patches.
38
+ - **Local e síncrono** — `calculateBuild()` não faz nenhuma requisição de rede. O motor roda in-process; os dados do jogo e os itens são fornecidos pela sua aplicação (arquivo, banco de dados, dados gerados).
39
+ - **Aceita item data da UESP diretamente** — equipamentos no formato [`exportJson.php?table=minedItem`](https://esolog.uesp.net) plugam direto em `BuildInput.items`.
40
+ - **Nativo TypeScript** — inputs/outputs tipados, [API Reference](https://srtomy.github.io/uesp-eso-build-wrapper/api/) documentada com TSDoc, além de funções de catálogo em runtime (`listAvailableBuffs`, `listRacialPassives`, …) para descobrir nomes válidos.
41
+
42
+ ## Propriedades principais
43
+
44
+ - Executa o motor de cálculo UESP vendored localmente (`vendor/uesp-esochardata`)
45
+ - **Sem rede para calcular builds** — ver [Precisa de internet?](https://srtomy.github.io/uesp-eso-build-wrapper/pt/architecture#precisa-de-conexao-com-a-internet)
46
+ - Não reimplementa as fórmulas de stats do ESO
47
+ - API síncrona; o motor inicializa uma vez por processo (singleton, chamadas seguintes são no-op)
48
+ - Zero dependências de runtime — Node.js puro
49
+ - 221 computed stats por build
50
+
51
+ ## Instalação
52
+
53
+ ```bash
54
+ npm install uesp-eso-build-wrapper
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ Os game data não vêm no pacote npm — você os fornece via `initEsoEngineFromData` (ver [Primeiros Passos](https://srtomy.github.io/uesp-eso-build-wrapper/pt/getting-started)).
60
+
61
+ ```ts
62
+ import fs from 'fs';
63
+ import { initEsoEngineFromData, calculateBuild } from 'uesp-eso-build-wrapper';
64
+ import type { UespInitData } from 'uesp-eso-build-wrapper';
65
+
66
+ const initData = JSON.parse(
67
+ fs.readFileSync('uesp-game-data.json', 'utf-8'),
68
+ ) as UespInitData;
69
+
70
+ initEsoEngineFromData({ initData }); // uma vez por processo
71
+
72
+ const stats = calculateBuild({
73
+ character: {
74
+ race: 'High Elf',
75
+ class: 'Sorcerer',
76
+ level: 50,
77
+ attributes: { health: 0, magicka: 64, stamina: 0 },
78
+ },
79
+ });
80
+
81
+ console.log(stats.Health); // 16000
82
+ console.log(stats.Magicka); // 19104
83
+ console.log(stats.SpellDamage); // 1000
84
+ ```
85
+
86
+ ## Como funciona
87
+
88
+ 1. `initEsoEngineFromData({ initData })` prepara globals de browser, semeia o motor com seus game data e executa os scripts vendored da UESP via `vm.runInThisContext` — uma vez por processo.
89
+ 2. `calculateBuild(input)` escreve sua build no estado do motor, roda o próprio `UpdateEsoComputedStatsList_Real()` do motor e lê os resultados de `g_EsoComputedStats` num objeto tipado `ComputedStats`.
90
+
91
+ Detalhes: [Arquitetura](https://srtomy.github.io/uesp-eso-build-wrapper/pt/architecture) · [Primeiros Passos](https://srtomy.github.io/uesp-eso-build-wrapper/pt/getting-started) · [Lendo o Resultado](https://srtomy.github.io/uesp-eso-build-wrapper/pt/output).
92
+
93
+ ## Documentação
94
+
95
+ Documentação completa em **Português (BR)** e **English** em
96
+ [**srtomy.github.io/uesp-eso-build-wrapper**](https://srtomy.github.io/uesp-eso-build-wrapper/pt/):
97
+
98
+ | Seção | Descrição |
99
+ | --- | --- |
100
+ | [Introdução](https://srtomy.github.io/uesp-eso-build-wrapper/pt/) | O que é, por que existe, propriedades principais |
101
+ | [Arquitetura](https://srtomy.github.io/uesp-eso-build-wrapper/pt/architecture) | Motor local, política de rede, fluxo de dados |
102
+ | [Primeiros Passos](https://srtomy.github.io/uesp-eso-build-wrapper/pt/getting-started) | Instalação, game data, primeiro cálculo |
103
+ | [Guias](https://srtomy.github.io/uesp-eso-build-wrapper/pt/guides/character) | Personagem, itens, Champion Points, buffs, skills |
104
+ | [Lendo o Resultado](https://srtomy.github.io/uesp-eso-build-wrapper/pt/output) | Os 221 computed stats, `debugBuild()` |
105
+ | [API Reference](https://srtomy.github.io/uesp-eso-build-wrapper/api/) | Gerada a partir do TSDoc (em inglês) |
106
+ | [Solução de Problemas](https://srtomy.github.io/uesp-eso-build-wrapper/pt/troubleshooting) | Problemas comuns (Next.js/serverless, stats errados...) |
107
+ | [Contribuindo](https://srtomy.github.io/uesp-eso-build-wrapper/pt/contributing) | Setup dev, testes, atualização após patch do ESO |
108
+
109
+ ## Limitações
110
+
111
+ - O comportamento segue a versão vendored do motor UESP — suportar um patch novo do ESO significa atualizar os scripts vendored + game data e rodar os testes.
112
+ - O motor foi escrito para browsers em torno de estado global; o wrapper adapta isso para Node.js (init singleton, chamadas síncronas). Sem garantias de concorrência além das que o próprio motor oferece — ver [Solução de Problemas](https://srtomy.github.io/uesp-eso-build-wrapper/pt/troubleshooting).
113
+ - Requer Node.js >= 24. Bundlers/serverless precisam incluir `vendor/**` explicitamente (documentado em Solução de Problemas).
114
+
115
+ ## Licença
116
+
117
+ MIT © srtomy
118
+
119
+ Este pacote inclui arquivos de [uesp/uesp-esochardata](https://github.com/uesp/uesp-esochardata) (MIT).
120
+ Ver [THIRD_PARTY_NOTICES](THIRD_PARTY_NOTICES) para detalhes.
121
+
122
+ Elder Scrolls Online é marca registrada de ZeniMax Media Inc. Este projeto não é afiliado nem endossado pela ZeniMax Media Inc.
@@ -1,39 +1,49 @@
1
1
  /**
2
- * Motor de cálculo de builds do ESO.
2
+ * ESO build calculation engine.
3
3
  *
4
- * Implementa a ideia central da arquitetura:
4
+ * Implements the core architecture idea:
5
5
  *
6
- * 1. Injetar dados do personagem nos elementos mock do DOM
7
- * (jQuery vai ler via $("#esotbRace").val(), etc.)
6
+ * 1. Inject character data into the mock DOM elements
7
+ * (jQuery will read via $("#esotbRace").val(), etc.)
8
8
  *
9
- * 2. Injetar dados dos itens DIRETAMENTE em g_EsoBuildItemData[slot]
10
- * — sem precisar mockar jQuery para cada campo de item.
11
- * Os campos vêm exatamente no formato da API pública da UESP:
9
+ * 2. Inject item data DIRECTLY into g_EsoBuildItemData[slot]
10
+ * — no need to mock jQuery for each item field.
11
+ * Fields come exactly in the UESP public API format:
12
12
  * GET https://esolog.uesp.net/exportJson.php?table=minedItem&id=<id>&level=<lv>&quality=<q>
13
13
  *
14
- * 3. Chamar UpdateEsoComputedStatsList_Real(null, true)
15
- * — o parâmetro `noUpdate=true` faz o motor calcular tudo mas pular
16
- * as atualizações de DOM (DisplayEsoAllComputedStats, UpdateReadOnlyStats, etc.)
14
+ * 3. Call UpdateEsoComputedStatsList_Real(null, true)
15
+ * — the `noUpdate=true` parameter makes the engine compute everything but skip
16
+ * the DOM updates (DisplayEsoAllComputedStats, UpdateReadOnlyStats, etc.)
17
17
  *
18
- * 4. Ler os resultados de g_EsoComputedStats[statId].value
18
+ * 4. Read the results from g_EsoComputedStats[statId].value
19
19
  */
20
- import type { BuffInfo, BuildInput, ComputedStats, PassiveSkillInfo, ToggleSkillInfo } from './types';
20
+ import type { BuffInfo, BuildInput, ComputedStats, PassiveSkillInfo, ToggleSkillInfo } from './types.js';
21
21
  export declare function cacheStatObjects(): void;
22
22
  /**
23
- * Calcula os Computed Character Statistics para a build fornecida.
23
+ * Calculates the Computed Character Statistics for the given build.
24
+ *
25
+ * Each call starts from a clean engine state (previous items, buffs, CP nodes
26
+ * and skill bars are reset), so builds never bleed into each other.
27
+ *
28
+ * @param input - The build to calculate: character sheet, items, champion
29
+ * point nodes, buffs, toggle skills, skill bars and passives.
30
+ * @returns All computed stats — named keys (Health, Magicka, SpellDamage, ...)
31
+ * plus `raw` with the full 221-stat `g_EsoComputedStats` record.
32
+ * @throws If the engine has not been initialized with
33
+ * `initEsoEngineFromData()` first.
24
34
  *
25
35
  * @example
26
36
  * ```ts
27
- * import { calculateBuild } from './src/lib/eso-engine';
37
+ * import { calculateBuild } from 'uesp-eso-build-wrapper';
28
38
  *
29
39
  * const stats = calculateBuild({
30
40
  * character: { race: 'High Elf', class: 'Sorcerer', level: 50,
31
41
  * attributes: { health: 0, magicka: 64, stamina: 0 } },
32
42
  * items: {
33
- * Chest: chestItemFromUespApi, // objeto retornado por esolog.uesp.net/exportJson.php
43
+ * Chest: chestItemFromUespApi, // object returned by esolog.uesp.net/exportJson.php
34
44
  * },
35
45
  * });
36
- * console.log(stats.MaxMagicka, stats.SpellDamage);
46
+ * console.log(stats.Magicka, stats.SpellDamage);
37
47
  * ```
38
48
  */
39
49
  export declare function calculateBuild(input: BuildInput): ComputedStats;
@@ -1 +1 @@
1
- {"version":3,"file":"calculator.d.ts","sourceRoot":"","sources":["../../../src/lib/eso-engine/calculator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EAEV,aAAa,EAEb,gBAAgB,EAEhB,eAAe,EAEhB,MAAM,SAAS,CAAC;AAMjB,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC;AAqCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,CAwf/D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CA6B7D;AA2BD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAKnE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAKvE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAK7E;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,EAAE,CASlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,IAAI,eAAe,EAAE,CA6B7D"}
1
+ {"version":3,"file":"calculator.d.ts","sourceRoot":"","sources":["../../../src/lib/eso-engine/calculator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EAEV,aAAa,EAEb,gBAAgB,EAEhB,eAAe,EAEhB,MAAM,YAAY,CAAC;AAMpB,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC;AAwDD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,CAygB/D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CA6B7D;AA2BD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAKnE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAKvE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAK7E;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,EAAE,CASlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,IAAI,eAAe,EAAE,CA6B7D"}