dota2-dotawrapper 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Egezenn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # dota2-dotawrapper
2
+
3
+ A high-fidelity **Data Normalization & Enrichment Layer** for Dota 2. It seamlessly merges Valve's official live Datafeed API with the community-driven `dotaconstants` dataset to provide a single, consistent source of truth for heroes, items, abilities, and patches.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/dota2-dotawrapper.svg)](https://www.npmjs.com/package/dota2-datawrapper)
6
+
7
+ ## 🚀 Key Features
8
+
9
+ * **Unified Data Feed**: Consolidate disparate Valve endpoints into a single, clean API.
10
+ * **Deep Enrichment**: Injects missing metadata (stat gains, item costs, component trees) from `dotaconstants`.
11
+ * **Special Value Resolution**: Automatically parses complex in-game strings like `%bonus_damage%` and `{s:value}`, including Aghanim's Shard/Scepter overrides.
12
+ * **Auto-Normalization**: Fixes inconsistent API naming conventions and resolves legacy Valve placeholders.
13
+ * **Static-Site Ready**: Built-in utilities to fetch, bundle, and deploy data for serverless/static environments.
14
+ * **Type Safe**: Written in TypeScript with full definitions for the entire Dota 2 schema.
15
+
16
+ ## 📦 Installation
17
+
18
+ ```shell
19
+ npm install dota2-dotawrapper
20
+ ```
21
+
22
+ ## 🛠 Usage
23
+
24
+ ```typescript
25
+ import { Dota2Datafeed } from 'dota2-dotawrapper';
26
+
27
+ // Initialize with optional configuration
28
+ const api = new Dota2Datafeed({
29
+ language: 'english',
30
+ useJsonExtension: true // Useful for static JSON mirrors
31
+ });
32
+
33
+ async function getHeroDetails(heroId: number) {
34
+ // 1. Fetch community constants (cached/local/github)
35
+ const constantsHeroes = await api.getConstantsHeroes();
36
+
37
+ // 2. Fetch live Valve data and merge automatically
38
+ const hero = await api.getHeroDataWithConstants(heroId, constantsHeroes);
39
+
40
+ console.log(`Hero: ${hero.name_loc}`);
41
+ console.log(`Strength Gain: ${hero.str_gain}`); // Enriched from constants
42
+ }
43
+ ```
44
+
45
+ ## 📖 API Reference
46
+
47
+ ### Core Client: `Dota2Datafeed`
48
+
49
+ #### Enriched Methods (Recommended)
50
+
51
+ These methods combine live data with community metadata for the most complete dataset.
52
+
53
+ * `getHeroesWithConstants(constantsHeroes)`: Returns all heroes with merged stats.
54
+ * `getItemsWithConstants(constantsItems)`: Returns all items with gold costs and component data.
55
+ * `getHeroDataWithConstants(heroId, constantsHeroes)`: Detailed single hero data with merged attributes.
56
+
57
+ #### Live Valve Data Methods
58
+
59
+ Direct access to official Valve endpoints.
60
+
61
+ * `getHeroes()`: Raw list of all available heroes.
62
+ * `getHeroData(heroId)`: Raw detailed data (abilities, talents, etc.).
63
+ * `getItems()`: Base item list.
64
+ * `getAbilities()`: Master list of all abilities and item abilities.
65
+ * `getPatchList()`: Chronological list of game patches.
66
+ * `getPatchNotes(version)`: Specific changes for a given version.
67
+
68
+ #### Community Constants Helpers
69
+
70
+ Fetch the latest metadata from `dotaconstants`.
71
+
72
+ * `getConstantsHeroes()`: Raw hero metadata (stat gains, roles).
73
+ * `getConstantsItems()`: Raw item metadata (gold, components).
74
+ * `getConstantsAbilityLookup()`: Essential mapping for ability icons and innate status.
75
+
76
+ ### Utilities: `Dota2Datafeed.utils`
77
+
78
+ * `formatAbilityText(text, specials, hero?, ability?, upgrade?)`: Resolve `%param%` placeholders to their actual values.
79
+ * `normalizeHeroName(name)`: Strips `npc_dota_hero_` prefixes.
80
+ * `getAbilityBehaviorNames(behavior)`: Converts bitmasks to human-readable labels.
81
+
82
+ ## 🎨 Explorer
83
+
84
+ The repository includes a reference implementation under `docs/`. It is a high-performance, static-build explorer that demonstrates:
85
+
86
+ * Proof of concept.
87
+ * Complex ability rendering.
88
+ * Aghanim's Shard/Scepter upgrade visualization.
89
+ * Interactive hero grids and patch note histories.
90
+
91
+ [**View the Explorer Source**](docs/)
92
+
93
+ ## 📜 Scripts
94
+
95
+ Useful for CI/CD and data management:
96
+
97
+ * `npm run fetch-all`: Downloads all Valve JSONs and assets (images/videos) to local storage.
98
+ * `npm run docs:static-build`: Generates a fully-contained static version of the library and explorer.
@@ -0,0 +1,390 @@
1
+ interface Dota2Hero {
2
+ id: number;
3
+ name: string;
4
+ name_loc: string;
5
+ name_english_loc: string;
6
+ primary_attr: number;
7
+ complexity: number;
8
+ roles: number[];
9
+ }
10
+ interface Dota2Item {
11
+ id: number;
12
+ name: string;
13
+ name_loc: string;
14
+ name_english_loc: string;
15
+ cost: number;
16
+ desc_loc: string;
17
+ lore_loc: string;
18
+ notes_loc: string[];
19
+ attrib_loc: string[];
20
+ item_slot: number;
21
+ abilities?: any[];
22
+ attrib?: any[];
23
+ attributes?: any[];
24
+ lore?: string;
25
+ neutral_item_tier?: number;
26
+ qual?: string;
27
+ behavior?: string | string[];
28
+ }
29
+ interface Dota2Ability {
30
+ id: number;
31
+ name: string;
32
+ name_loc: string;
33
+ desc_loc: string;
34
+ lore_loc: string;
35
+ notes_loc: string[];
36
+ attrib_loc: string[];
37
+ }
38
+ interface DatafeedResponse<T> {
39
+ result: {
40
+ data: T[];
41
+ status: number;
42
+ };
43
+ }
44
+ interface HeroListResponse {
45
+ result: {
46
+ data: {
47
+ heroes: Dota2Hero[];
48
+ };
49
+ status: number;
50
+ };
51
+ }
52
+ interface ItemListResponse {
53
+ result: {
54
+ data: {
55
+ itemabilities: Dota2Item[];
56
+ };
57
+ status: number;
58
+ };
59
+ }
60
+ interface AbilityListResponse {
61
+ result: {
62
+ data: {
63
+ abilities?: Dota2Ability[];
64
+ itemabilities?: Dota2Ability[];
65
+ };
66
+ status: number;
67
+ };
68
+ }
69
+ interface PatchNotes {
70
+ patch_number: string;
71
+ patch_name: string;
72
+ patch_timestamp: number;
73
+ }
74
+ interface PatchNotesResponse {
75
+ result?: {
76
+ data: {
77
+ patches: PatchNotes[];
78
+ };
79
+ status: number;
80
+ };
81
+ patches?: PatchNotes[];
82
+ success?: boolean;
83
+ }
84
+ interface PatchNote {
85
+ indent_level: number;
86
+ note: string;
87
+ }
88
+ interface PatchAbilityChange {
89
+ ability_id: number;
90
+ ability_notes: PatchNote[];
91
+ }
92
+ interface PatchHeroChange {
93
+ hero_id: number;
94
+ hero_notes?: PatchNote[];
95
+ talent_notes?: PatchNote[];
96
+ abilities?: PatchAbilityChange[];
97
+ }
98
+ interface PatchItemChange {
99
+ ability_id: number;
100
+ ability_notes: PatchNote[];
101
+ }
102
+ interface PatchGeneralNote {
103
+ title?: string;
104
+ generic: PatchNote[];
105
+ }
106
+ interface PatchDetailsResponse {
107
+ patch_number: string;
108
+ patch_name: string;
109
+ patch_timestamp: number;
110
+ general_notes?: PatchGeneralNote[];
111
+ items: PatchItemChange[];
112
+ neutral_items?: PatchItemChange[];
113
+ heroes: PatchHeroChange[];
114
+ success?: boolean;
115
+ }
116
+ interface AbilityBonus {
117
+ name: string;
118
+ value: number;
119
+ operation: number;
120
+ }
121
+ interface AbilitySpecialValue {
122
+ name: string;
123
+ values_float: number[];
124
+ values_shard: number[];
125
+ values_scepter: number[];
126
+ is_percentage: boolean;
127
+ heading_loc: string;
128
+ bonuses: AbilityBonus[];
129
+ }
130
+ interface DetailedAbility {
131
+ id: number;
132
+ name: string;
133
+ name_loc: string;
134
+ desc_loc: string;
135
+ lore_loc: string;
136
+ notes_loc: string[];
137
+ shard_loc: string;
138
+ scepter_loc: string;
139
+ type: number;
140
+ behavior: string | number;
141
+ target_team: number;
142
+ target_type: number;
143
+ flags: number;
144
+ damage: number;
145
+ immunity: number;
146
+ dispellable: number;
147
+ max_level: number;
148
+ item_cost: number;
149
+ ability_has_scepter: boolean;
150
+ ability_has_shard: boolean;
151
+ ability_is_innate: boolean;
152
+ ability_is_granted_by_shard: boolean;
153
+ ability_is_granted_by_scepter: boolean;
154
+ cooldowns: number[];
155
+ mana_costs: number[];
156
+ special_values: AbilitySpecialValue[];
157
+ }
158
+ interface DetailedHero {
159
+ id: number;
160
+ name: string;
161
+ name_loc: string;
162
+ bio_loc: string;
163
+ hype_loc: string;
164
+ npe_desc_loc: string;
165
+ str_base: number;
166
+ str_gain: number;
167
+ agi_base: number;
168
+ agi_gain: number;
169
+ int_base: number;
170
+ int_gain: number;
171
+ primary_attr: number;
172
+ complexity: number;
173
+ attack_capability: number;
174
+ damage_min: number;
175
+ damage_max: number;
176
+ attack_rate: number;
177
+ attack_range: number;
178
+ projectile_speed: number;
179
+ armor: number;
180
+ magic_resistance: number;
181
+ movement_speed: number;
182
+ turn_rate: number;
183
+ sight_range_day: number;
184
+ sight_range_night: number;
185
+ max_health: number;
186
+ health_regen: number;
187
+ max_mana: number;
188
+ mana_regen: number;
189
+ abilities: DetailedAbility[];
190
+ talents: DetailedAbility[];
191
+ role_levels: number[];
192
+ }
193
+ interface HeroDataResponse {
194
+ result: {
195
+ data: {
196
+ heroes: DetailedHero[];
197
+ };
198
+ status: number;
199
+ };
200
+ }
201
+
202
+ /**
203
+ * Constants for various Dota 2 assets.
204
+ */
205
+ declare const ASSET_URLS: {
206
+ ITEM_IMAGE: (shortName: string) => string;
207
+ ABILITY_IMAGE: (shortName: string) => string;
208
+ HERO_IMAGE: (shortName: string) => string;
209
+ readonly TALENT_ICON: string;
210
+ readonly INNATE_ICON: string;
211
+ ATTRIBUTE_ICON: (attr: "strength" | "agility" | "intelligence" | "universal") => string;
212
+ ATTACK_TYPE_ICON: (type: "melee" | "ranged") => string;
213
+ readonly AGHS_SCEPTER: string;
214
+ readonly AGHS_SHARD: string;
215
+ readonly COOLDOWN: string;
216
+ readonly GOLD: string;
217
+ STAT_ICON: (stat: "damage" | "attack_time" | "attack_range" | "armor" | "magic_resist" | "movement_speed" | "turn_rate" | "vision") => string;
218
+ readonly FAVICON: string;
219
+ readonly VALVE_LOGO: string;
220
+ readonly DOTA_FOOTER_LOGO: string;
221
+ readonly DOTA_LOGO_HORIZ: string;
222
+ readonly STEAM_ICON: string;
223
+ readonly LANGUAGE_ICON: string;
224
+ readonly ARROW_OVER: string;
225
+ readonly SEARCH_ICON: string;
226
+ FILTER_ICON: (attr: "str" | "agi" | "int" | "uni") => string;
227
+ readonly FILTER_DIAMOND: string;
228
+ ABILITY_VIDEO_POSTER: (heroName: string, abilityName: string) => string;
229
+ ABILITY_VIDEO_WEBM: (heroName: string, abilityName: string) => string;
230
+ HERO_VIDEO_MOV: (heroName: string) => string;
231
+ HERO_VIDEO_WEBM: (heroName: string) => string;
232
+ HERO_RENDER_PNG: (heroName: string) => string;
233
+ FONT: (fontName: string) => string;
234
+ };
235
+ /**
236
+ * Helper utility for Dota 2 asset URLs.
237
+ */
238
+ declare class Dota2Urls {
239
+ static ASSET_URLS: {
240
+ ITEM_IMAGE: (shortName: string) => string;
241
+ ABILITY_IMAGE: (shortName: string) => string;
242
+ HERO_IMAGE: (shortName: string) => string;
243
+ readonly TALENT_ICON: string;
244
+ readonly INNATE_ICON: string;
245
+ ATTRIBUTE_ICON: (attr: "strength" | "agility" | "intelligence" | "universal") => string;
246
+ ATTACK_TYPE_ICON: (type: "melee" | "ranged") => string;
247
+ readonly AGHS_SCEPTER: string;
248
+ readonly AGHS_SHARD: string;
249
+ readonly COOLDOWN: string;
250
+ readonly GOLD: string;
251
+ STAT_ICON: (stat: "damage" | "attack_time" | "attack_range" | "armor" | "magic_resist" | "movement_speed" | "turn_rate" | "vision") => string;
252
+ readonly FAVICON: string;
253
+ readonly VALVE_LOGO: string;
254
+ readonly DOTA_FOOTER_LOGO: string;
255
+ readonly DOTA_LOGO_HORIZ: string;
256
+ readonly STEAM_ICON: string;
257
+ readonly LANGUAGE_ICON: string;
258
+ readonly ARROW_OVER: string;
259
+ readonly SEARCH_ICON: string;
260
+ FILTER_ICON: (attr: "str" | "agi" | "int" | "uni") => string;
261
+ readonly FILTER_DIAMOND: string;
262
+ ABILITY_VIDEO_POSTER: (heroName: string, abilityName: string) => string;
263
+ ABILITY_VIDEO_WEBM: (heroName: string, abilityName: string) => string;
264
+ HERO_VIDEO_MOV: (heroName: string) => string;
265
+ HERO_VIDEO_WEBM: (heroName: string) => string;
266
+ HERO_RENDER_PNG: (heroName: string) => string;
267
+ FONT: (fontName: string) => string;
268
+ };
269
+ static setBaseUrl(url: string): void;
270
+ static heroImage(heroName: string): string;
271
+ static itemImage(itemName: string): string;
272
+ static abilityImage(abilityName: string): string;
273
+ static abilityVideo(heroName: string, abilityName: string): {
274
+ poster: string;
275
+ webm: string;
276
+ };
277
+ static heroVideo(heroName: string): {
278
+ mov: string;
279
+ webm: string;
280
+ poster: string;
281
+ };
282
+ static attributeIcon(attr: number | string): string;
283
+ static toCloudflare(url: string): string;
284
+ }
285
+
286
+ declare const ROLE_NAMES: string[];
287
+ declare const ABILITY_BEHAVIORS: Record<string, bigint>;
288
+ /**
289
+ * Translates an ability behavior bitmask into an array of human-readable strings.
290
+ */
291
+ declare function getAbilityBehaviorNames(behavior: number | string | bigint): string[];
292
+ /**
293
+ * Formats Dota 2 ability/talent text by resolving placeholders like %param% and {s:bonus_name}.
294
+ */
295
+ declare function formatAbilityText(text: string, svs: AbilitySpecialValue[], hero?: DetailedHero, sourceAbility?: DetailedAbility, upgradeContext?: 'shard' | 'scepter'): string;
296
+ /**
297
+ * Normalizes a hero name by removing the 'npc_dota_hero_' prefix.
298
+ */
299
+ declare function normalizeHeroName(name: string): string;
300
+ /**
301
+ * Merges API hero data with dotaconstants.
302
+ */
303
+ declare function mergeHeroData(apiHero: DetailedHero, cHero?: any): DetailedHero;
304
+ /**
305
+ * Merges API item data with dotaconstants.
306
+ */
307
+ declare function mergeItemData(apiItem: Partial<Dota2Item>, cItem: any): Dota2Item;
308
+ /**
309
+ * Merges API ability data with dotaconstants.
310
+ */
311
+ declare function mergeAbilityData(apiAbility: Partial<DetailedAbility>, cAbility: any): DetailedAbility;
312
+
313
+ declare const utils_ABILITY_BEHAVIORS: typeof ABILITY_BEHAVIORS;
314
+ declare const utils_ROLE_NAMES: typeof ROLE_NAMES;
315
+ declare const utils_formatAbilityText: typeof formatAbilityText;
316
+ declare const utils_getAbilityBehaviorNames: typeof getAbilityBehaviorNames;
317
+ declare const utils_mergeAbilityData: typeof mergeAbilityData;
318
+ declare const utils_mergeHeroData: typeof mergeHeroData;
319
+ declare const utils_mergeItemData: typeof mergeItemData;
320
+ declare const utils_normalizeHeroName: typeof normalizeHeroName;
321
+ declare namespace utils {
322
+ export { utils_ABILITY_BEHAVIORS as ABILITY_BEHAVIORS, utils_ROLE_NAMES as ROLE_NAMES, utils_formatAbilityText as formatAbilityText, utils_getAbilityBehaviorNames as getAbilityBehaviorNames, utils_mergeAbilityData as mergeAbilityData, utils_mergeHeroData as mergeHeroData, utils_mergeItemData as mergeItemData, utils_normalizeHeroName as normalizeHeroName };
323
+ }
324
+
325
+ interface Dota2DatafeedConfig {
326
+ language?: string;
327
+ baseURL?: string;
328
+ dfBaseURL?: string;
329
+ constantsBaseURL?: string;
330
+ timeout?: number;
331
+ useJsonExtension?: boolean;
332
+ }
333
+ /**
334
+ * A normalization and enrichment layer for Dota 2 data feeds.
335
+ */
336
+ declare class Dota2Datafeed {
337
+ private clientDf;
338
+ private clientConstants;
339
+ private language;
340
+ static urls: typeof Dota2Urls;
341
+ static utils: typeof utils;
342
+ constructor(config?: Dota2DatafeedConfig);
343
+ /**
344
+ * Fetches the list of all Dota 2 heroes from Valve.
345
+ */
346
+ getHeroes(): Promise<Dota2Hero[]>;
347
+ /**
348
+ * Fetches detailed data for a specific hero from Valve.
349
+ */
350
+ getHeroData(heroId: number): Promise<DetailedHero | null>;
351
+ /**
352
+ * Fetches the list of all Dota 2 items from Valve.
353
+ */
354
+ getItems(): Promise<Dota2Item[]>;
355
+ /**
356
+ * Fetches the list of all Dota 2 abilities from Valve.
357
+ */
358
+ getAbilities(): Promise<Dota2Ability[]>;
359
+ /**
360
+ * Fetches the list of all Dota 2 patch notes from Valve.
361
+ */
362
+ getPatchList(): Promise<PatchNotes[]>;
363
+ /**
364
+ * Fetches specific patch details from Valve.
365
+ * @param version The patch version (e.g., '7.40b')
366
+ */
367
+ getPatchNotes(version: string): Promise<PatchDetailsResponse>;
368
+ getConstantsHeroes(): Promise<any>;
369
+ getConstantsAbilities(): Promise<any>;
370
+ getConstantsHeroAbilities(): Promise<any>;
371
+ getConstantsAghsDesc(): Promise<any>;
372
+ getConstantsItems(): Promise<any>;
373
+ getConstantsAbilityIds(): Promise<any>;
374
+ getConstantsAbilityLookup(): Promise<any>;
375
+ /**
376
+ * Fetches the hero list and merges with dotaconstants.
377
+ */
378
+ getHeroesWithConstants(constantsHeroes: any): Promise<Dota2Hero[]>;
379
+ /**
380
+ * Fetches the item list and merges with dotaconstants.
381
+ */
382
+ getItemsWithConstants(constantsItems: any): Promise<Dota2Item[]>;
383
+ /**
384
+ * Fetches detailed hero data and merges with dotaconstants.
385
+ */
386
+ getHeroDataWithConstants(heroId: number, constantsHeroes: any): Promise<DetailedHero | null>;
387
+ private handleError;
388
+ }
389
+
390
+ export { ASSET_URLS, type AbilityBonus, type AbilityListResponse, type AbilitySpecialValue, type DatafeedResponse, type DetailedAbility, type DetailedHero, type Dota2Ability, Dota2Datafeed, type Dota2DatafeedConfig, type Dota2Hero, type Dota2Item, Dota2Urls, type HeroDataResponse, type HeroListResponse, type ItemListResponse, type PatchAbilityChange, type PatchDetailsResponse, type PatchGeneralNote, type PatchHeroChange, type PatchItemChange, type PatchNote, type PatchNotes, type PatchNotesResponse, utils };