dragon-item-parser: introduce item parser library
This commit is contained in:
49
.gitea/workflows/dragon-item-parser.yml
Normal file
49
.gitea/workflows/dragon-item-parser.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
name: Dragon Item Parser CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'dragon-item-parser/**'
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'dragon-item-parser/**'
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: dragon-item-parser
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Check formatting
|
||||||
|
run: npm run format:check
|
||||||
|
|
||||||
|
- name: Run linting
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Verify build output
|
||||||
|
run: |
|
||||||
|
test -f dist/index.js
|
||||||
|
test -f dist/index.d.ts
|
||||||
|
test -f dist/item.js
|
||||||
|
test -f dist/item.d.ts
|
||||||
3
dragon-item-parser/.gitignore
vendored
Normal file
3
dragon-item-parser/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
*.log
|
||||||
10
dragon-item-parser/.prettierrc
Normal file
10
dragon-item-parser/.prettierrc
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"printWidth": 100,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"endOfLine": "lf"
|
||||||
|
}
|
||||||
19
dragon-item-parser/eslint.config.js
Normal file
19
dragon-item-parser/eslint.config.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { defineConfig } from 'eslint/config'
|
||||||
|
import js from '@eslint/js'
|
||||||
|
import tseslint from 'typescript-eslint'
|
||||||
|
import prettier from 'eslint-config-prettier'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
js.configs.recommended,
|
||||||
|
tseslint.configs.recommended,
|
||||||
|
prettier,
|
||||||
|
{
|
||||||
|
ignores: ['dist/**', 'node_modules/**']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
semi: 'off',
|
||||||
|
'prefer-const': 'error'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
2886
dragon-item-parser/package-lock.json
generated
Normal file
2886
dragon-item-parser/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
53
dragon-item-parser/package.json
Normal file
53
dragon-item-parser/package.json
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"name": "dragon-item-parser",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Parse League of Legends item stats from CommunityDragon data",
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"dev": "tsc --watch",
|
||||||
|
"test": "vitest run",
|
||||||
|
"test:watch": "vitest",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"lint:fix": "eslint --fix .",
|
||||||
|
"format": "prettier --write .",
|
||||||
|
"format:check": "prettier --check .",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"league-of-legends",
|
||||||
|
"cdragon",
|
||||||
|
"communitydragon",
|
||||||
|
"item",
|
||||||
|
"parser",
|
||||||
|
"lol"
|
||||||
|
],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": ""
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.39.2",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.53.1",
|
||||||
|
"@typescript-eslint/parser": "^8.53.1",
|
||||||
|
"eslint": "^9.39.2",
|
||||||
|
"eslint-config-prettier": "^10.1.8",
|
||||||
|
"prettier": "^3.8.3",
|
||||||
|
"typescript": "^5.0.0",
|
||||||
|
"typescript-eslint": "^8.53.1",
|
||||||
|
"vitest": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
2
dragon-item-parser/src/index.ts
Normal file
2
dragon-item-parser/src/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export type { ItemStats, CDragonItem, ItemWithStats } from './item.js'
|
||||||
|
export { parseItemStats, parseItem, parseItems } from './item.js'
|
||||||
202
dragon-item-parser/src/item.ts
Normal file
202
dragon-item-parser/src/item.ts
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/**
|
||||||
|
* Item stats parsed from CommunityDragon item description HTML
|
||||||
|
*/
|
||||||
|
export interface ItemStats {
|
||||||
|
// Offensive stats
|
||||||
|
attackDamage?: number
|
||||||
|
abilityPower?: number
|
||||||
|
attackSpeed?: number
|
||||||
|
criticalStrikeChance?: number
|
||||||
|
lifeSteal?: number
|
||||||
|
omnivamp?: number
|
||||||
|
physicalVamp?: number
|
||||||
|
spellVamp?: number
|
||||||
|
|
||||||
|
// Defensive stats
|
||||||
|
health?: number
|
||||||
|
armor?: number
|
||||||
|
magicResist?: number
|
||||||
|
|
||||||
|
// Resource stats
|
||||||
|
mana?: number
|
||||||
|
baseManaRegen?: number
|
||||||
|
baseHealthRegen?: number
|
||||||
|
|
||||||
|
// Movement stats
|
||||||
|
moveSpeed?: number
|
||||||
|
|
||||||
|
// Ability stats
|
||||||
|
abilityHaste?: number
|
||||||
|
|
||||||
|
// Penetration stats (usually percentages)
|
||||||
|
armorPenetration?: number
|
||||||
|
magicPenetration?: number
|
||||||
|
lethality?: number
|
||||||
|
magicPenetrationFlat?: number
|
||||||
|
|
||||||
|
// Other percentage stats
|
||||||
|
healAndShieldPower?: number
|
||||||
|
tenacity?: number
|
||||||
|
slowResist?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stat name mappings from CDragon description text to stat keys
|
||||||
|
*/
|
||||||
|
const STAT_MAPPINGS: Record<string, keyof ItemStats> = {
|
||||||
|
'Attack Damage': 'attackDamage',
|
||||||
|
'Ability Power': 'abilityPower',
|
||||||
|
'Attack Speed': 'attackSpeed',
|
||||||
|
'Critical Strike Chance': 'criticalStrikeChance',
|
||||||
|
'Life Steal': 'lifeSteal',
|
||||||
|
Omnivamp: 'omnivamp',
|
||||||
|
'Physical Vamp': 'physicalVamp',
|
||||||
|
'Spell Vamp': 'spellVamp',
|
||||||
|
Health: 'health',
|
||||||
|
Armor: 'armor',
|
||||||
|
'Magic Resist': 'magicResist',
|
||||||
|
Mana: 'mana',
|
||||||
|
'Base Mana Regen': 'baseManaRegen',
|
||||||
|
'Base Health Regen': 'baseHealthRegen',
|
||||||
|
'Move Speed': 'moveSpeed',
|
||||||
|
'Ability Haste': 'abilityHaste',
|
||||||
|
'Armor Penetration': 'armorPenetration',
|
||||||
|
'Magic Penetration': 'magicPenetration',
|
||||||
|
Lethality: 'lethality',
|
||||||
|
'Heal and Shield Power': 'healAndShieldPower',
|
||||||
|
Tenacity: 'tenacity',
|
||||||
|
'Slow Resist': 'slowResist'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a stat value string to a number
|
||||||
|
* Handles both flat values (e.g., "25") and percentages (e.g., "25%")
|
||||||
|
*/
|
||||||
|
function parseStatValue(valueStr: string): { value: number; isPercentage: boolean } {
|
||||||
|
const trimmed = valueStr.trim()
|
||||||
|
const isPercentage = trimmed.includes('%')
|
||||||
|
const numStr = trimmed.replace('%', '').replace(',', '').trim()
|
||||||
|
const value = parseFloat(numStr)
|
||||||
|
return { value, isPercentage }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract stats section from the description HTML
|
||||||
|
*/
|
||||||
|
function extractStatsSection(description: string): string | null {
|
||||||
|
const statsMatch = description.match(/<stats>(.*?)<\/stats>/s)
|
||||||
|
return statsMatch ? statsMatch[1] : null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse individual stat lines from the stats section
|
||||||
|
* Format: <attention> value </attention> statName
|
||||||
|
*/
|
||||||
|
function parseStatLines(
|
||||||
|
statsSection: string
|
||||||
|
): Array<{ value: number; isPercentage: boolean; statName: string }> {
|
||||||
|
const results: Array<{ value: number; isPercentage: boolean; statName: string }> = []
|
||||||
|
|
||||||
|
// Match patterns like: <attention> 25</attention> Move Speed
|
||||||
|
// or: <attention> 25%</attention> Attack Speed
|
||||||
|
const statRegex = /<attention>\s*([^<]+)<\/attention>\s*([^<]+)/g
|
||||||
|
let match
|
||||||
|
|
||||||
|
while ((match = statRegex.exec(statsSection)) !== null) {
|
||||||
|
const valueStr = match[1]
|
||||||
|
const statName = match[2].trim()
|
||||||
|
|
||||||
|
const { value, isPercentage } = parseStatValue(valueStr)
|
||||||
|
|
||||||
|
if (!isNaN(value) && statName) {
|
||||||
|
results.push({ value, isPercentage, statName })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse item stats from CDragon description HTML
|
||||||
|
*
|
||||||
|
* @param description - The HTML description string from CDragon items.json
|
||||||
|
* @returns Parsed ItemStats object with all recognized stats
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const stats = parseItemStats(
|
||||||
|
* '<mainText><stats><attention> 25</attention> Move Speed</stats><br><br></mainText>'
|
||||||
|
* )
|
||||||
|
* // Returns: { moveSpeed: 25 }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function parseItemStats(description: string): ItemStats {
|
||||||
|
const stats: ItemStats = {}
|
||||||
|
|
||||||
|
if (!description) {
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
|
const statsSection = extractStatsSection(description)
|
||||||
|
if (!statsSection) {
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
|
const statLines = parseStatLines(statsSection)
|
||||||
|
|
||||||
|
for (const { value, statName } of statLines) {
|
||||||
|
const statKey = STAT_MAPPINGS[statName]
|
||||||
|
|
||||||
|
if (statKey) {
|
||||||
|
// For percentage stats that are stored as decimals (e.g., 25% -> 25)
|
||||||
|
// We store the percentage value as-is for consistency with game data
|
||||||
|
stats[statKey] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item data structure from CDragon
|
||||||
|
*/
|
||||||
|
export interface CDragonItem {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
active?: boolean
|
||||||
|
inStore?: boolean
|
||||||
|
from?: number[]
|
||||||
|
to?: number[]
|
||||||
|
categories?: string[]
|
||||||
|
maxStacks?: number
|
||||||
|
requiredChampion?: string
|
||||||
|
requiredAlly?: string
|
||||||
|
price?: number
|
||||||
|
priceTotal?: number
|
||||||
|
iconPath: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item with parsed stats
|
||||||
|
*/
|
||||||
|
export interface ItemWithStats extends CDragonItem {
|
||||||
|
stats: ItemStats
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a CDragon item and add parsed stats
|
||||||
|
*/
|
||||||
|
export function parseItem(item: CDragonItem): ItemWithStats {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
stats: parseItemStats(item.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an array of CDragon items and add parsed stats
|
||||||
|
*/
|
||||||
|
export function parseItems(items: CDragonItem[]): ItemWithStats[] {
|
||||||
|
return items.map(parseItem)
|
||||||
|
}
|
||||||
235
dragon-item-parser/test/item.test.ts
Normal file
235
dragon-item-parser/test/item.test.ts
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
import { describe, it, expect } from 'vitest'
|
||||||
|
import { parseItemStats, parseItem, parseItems } from '../src/item.js'
|
||||||
|
|
||||||
|
describe('parseItemStats', () => {
|
||||||
|
describe('basic stats', () => {
|
||||||
|
it('should parse Move Speed', () => {
|
||||||
|
// Boots (id: 1001)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 25</attention> Move Speed</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.moveSpeed).toBe(25)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Attack Damage', () => {
|
||||||
|
// Long Sword (id: 1036)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 10</attention> Attack Damage</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.attackDamage).toBe(10)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Ability Power', () => {
|
||||||
|
// Amplifying Tome (id: 1052)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 20</attention> Ability Power</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.abilityPower).toBe(20)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Health', () => {
|
||||||
|
// Ruby Crystal (id: 1028)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 150</attention> Health</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.health).toBe(150)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Armor', () => {
|
||||||
|
// Cloth Armor (id: 1029)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 15</attention> Armor</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.armor).toBe(15)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Magic Resist', () => {
|
||||||
|
// Null-Magic Mantle (id: 1033)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 20</attention> Magic Resist</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.magicResist).toBe(20)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Mana', () => {
|
||||||
|
// Sapphire Crystal (id: 1027)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 300</attention> Mana</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.mana).toBe(300)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('percentage stats', () => {
|
||||||
|
it('should parse Attack Speed percentage', () => {
|
||||||
|
// Dagger (id: 1042)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 10%</attention> Attack Speed</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.attackSpeed).toBe(10)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Critical Strike Chance', () => {
|
||||||
|
// Cloak of Agility (id: 1018)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 15%</attention> Critical Strike Chance</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.criticalStrikeChance).toBe(15)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Life Steal', () => {
|
||||||
|
// Vampiric Scepter (id: 1053)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 15</attention> Attack Damage<br><attention> 7%</attention> Life Steal</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.attackDamage).toBe(15)
|
||||||
|
expect(stats.lifeSteal).toBe(7)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Base Mana Regen percentage', () => {
|
||||||
|
// Faerie Charm (id: 1004)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 50%</attention> Base Mana Regen</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.baseManaRegen).toBe(50)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse Base Health Regen percentage', () => {
|
||||||
|
// Rejuvenation Bead (id: 1006)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 100%</attention> Base Health Regen</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.baseHealthRegen).toBe(100)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('multiple stats', () => {
|
||||||
|
it("should parse multiple stats from Doran's Blade", () => {
|
||||||
|
// Doran's Blade (id: 1055)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 10</attention> Attack Damage<br><attention> 80</attention> Health<br><attention> 2.5%</attention> Omnivamp</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.attackDamage).toBe(10)
|
||||||
|
expect(stats.health).toBe(80)
|
||||||
|
expect(stats.omnivamp).toBe(2.5)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should parse multiple stats from Doran's Ring", () => {
|
||||||
|
// Doran's Ring (id: 1056)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 18</attention> Ability Power<br><attention> 90</attention> Health</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.abilityPower).toBe(18)
|
||||||
|
expect(stats.health).toBe(90)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should parse multiple stats from Seeker's Armguard", () => {
|
||||||
|
// Seeker's Armguard (id: 2420)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 40</attention> Ability Power<br><attention> 25</attention> Armor</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.abilityPower).toBe(40)
|
||||||
|
expect(stats.armor).toBe(25)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse complex item with many stats', () => {
|
||||||
|
// Overlord's Bloodmail (id: 2501)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 30</attention> Attack Damage<br><attention> 550</attention> Health</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.attackDamage).toBe(30)
|
||||||
|
expect(stats.health).toBe(550)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse item with Ability Haste', () => {
|
||||||
|
// Unending Despair (id: 2502)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 400</attention> Health<br><attention> 50</attention> Armor<br><attention> 15</attention> Ability Haste</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.health).toBe(400)
|
||||||
|
expect(stats.armor).toBe(50)
|
||||||
|
expect(stats.abilityHaste).toBe(15)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should parse item with Mana and Ability Haste', () => {
|
||||||
|
// Blackfire Torch (id: 2503)
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 80</attention> Ability Power<br><attention> 600</attention> Mana<br><attention> 20</attention> Ability Haste</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.abilityPower).toBe(80)
|
||||||
|
expect(stats.mana).toBe(600)
|
||||||
|
expect(stats.abilityHaste).toBe(20)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('edge cases', () => {
|
||||||
|
it('should return empty object for empty description', () => {
|
||||||
|
const stats = parseItemStats('')
|
||||||
|
expect(stats).toEqual({})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return empty object for description without stats', () => {
|
||||||
|
const description = '<mainText><stats></stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats).toEqual({})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle description with only passive text', () => {
|
||||||
|
// Emberknife (id: 1035) - no stats, only passives
|
||||||
|
const description =
|
||||||
|
'<mainText><stats></stats><br><br> <passive>7%</passive> Omnivamp against jungle monsters<br><li><passive>Sear:</passive> Damaging jungle monsters burns them for <magicDamage> magic damage</magicDamage> over 5 seconds.</mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats).toEqual({})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle decimal values', () => {
|
||||||
|
const description =
|
||||||
|
'<mainText><stats><attention> 2.5%</attention> Omnivamp</stats><br><br></mainText>'
|
||||||
|
const stats = parseItemStats(description)
|
||||||
|
expect(stats.omnivamp).toBe(2.5)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('parseItem', () => {
|
||||||
|
it('should parse item and add stats', () => {
|
||||||
|
const item = {
|
||||||
|
id: 1001,
|
||||||
|
name: 'Boots',
|
||||||
|
description:
|
||||||
|
'<mainText><stats><attention> 25</attention> Move Speed</stats><br><br></mainText>',
|
||||||
|
iconPath: '/path/to/icon.png'
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = parseItem(item)
|
||||||
|
expect(result.id).toBe(1001)
|
||||||
|
expect(result.name).toBe('Boots')
|
||||||
|
expect(result.stats.moveSpeed).toBe(25)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('parseItems', () => {
|
||||||
|
it('should parse multiple items', () => {
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
id: 1001,
|
||||||
|
name: 'Boots',
|
||||||
|
description:
|
||||||
|
'<mainText><stats><attention> 25</attention> Move Speed</stats><br><br></mainText>',
|
||||||
|
iconPath: '/path/to/boots.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1036,
|
||||||
|
name: 'Long Sword',
|
||||||
|
description:
|
||||||
|
'<mainText><stats><attention> 10</attention> Attack Damage</stats><br><br></mainText>',
|
||||||
|
iconPath: '/path/to/sword.png'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const results = parseItems(items)
|
||||||
|
expect(results).toHaveLength(2)
|
||||||
|
expect(results[0].stats.moveSpeed).toBe(25)
|
||||||
|
expect(results[1].stats.attackDamage).toBe(10)
|
||||||
|
})
|
||||||
|
})
|
||||||
17
dragon-item-parser/tsconfig.json
Normal file
17
dragon-item-parser/tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules", "dist", "test"]
|
||||||
|
}
|
||||||
7
dragon-item-parser/vitest.config.ts
Normal file
7
dragon-item-parser/vitest.config.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
include: ['test/**/*.test.ts']
|
||||||
|
}
|
||||||
|
})
|
||||||
9078
frontend/package-lock.json
generated
9078
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@
|
|||||||
"format:check": "prettier --check ."
|
"format:check": "prettier --check ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"dragon-item-parser": "file:../dragon-item-parser",
|
||||||
"@nuxt/eslint": "^1.12.1",
|
"@nuxt/eslint": "^1.12.1",
|
||||||
"@nuxt/fonts": "^0.11.3",
|
"@nuxt/fonts": "^0.11.3",
|
||||||
"@nuxt/image": "^1.10.0",
|
"@nuxt/image": "^1.10.0",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { readFile, existsSync } from 'fs'
|
import { readFile, existsSync } from 'fs'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { promisify } from 'util'
|
import { promisify } from 'util'
|
||||||
|
import { parseItemStats, type ItemStats } from 'dragon-item-parser'
|
||||||
|
|
||||||
const readFileAsync = promisify(readFile)
|
const readFileAsync = promisify(readFile)
|
||||||
|
|
||||||
@@ -78,14 +79,20 @@ async function fetchFromCache<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get items data from cache
|
* Get items data from cache with parsed stats
|
||||||
*/
|
*/
|
||||||
async function getItems(patch?: string): Promise<CDragonItem[]> {
|
async function getItems(patch?: string): Promise<CDragonItemWithStats[]> {
|
||||||
return fetchFromCache<CDragonItem[]>(
|
const items = await fetchFromCache<CDragonItem[]>(
|
||||||
'items.json',
|
'items.json',
|
||||||
'plugins/rcp-be-lol-game-data/global/default/v1/items.json',
|
'plugins/rcp-be-lol-game-data/global/default/v1/items.json',
|
||||||
{ patch }
|
{ patch }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Parse stats from description for each item
|
||||||
|
return items.map(item => ({
|
||||||
|
...item,
|
||||||
|
stats: parseItemStats(item.description || '')
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,6 +155,10 @@ interface CDragonItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CDragonItemWithStats extends CDragonItem {
|
||||||
|
stats: ItemStats
|
||||||
|
}
|
||||||
|
|
||||||
interface CDragonPerk {
|
interface CDragonPerk {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
@@ -197,6 +208,7 @@ export {
|
|||||||
|
|
||||||
export type {
|
export type {
|
||||||
CDragonItem,
|
CDragonItem,
|
||||||
|
CDragonItemWithStats,
|
||||||
CDragonPerk,
|
CDragonPerk,
|
||||||
CDragonPerkStyle,
|
CDragonPerkStyle,
|
||||||
CDragonPerkStyles,
|
CDragonPerkStyles,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import type { ItemStats } from 'dragon-item-parser'
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
type ChampionsResponse = {
|
type ChampionsResponse = {
|
||||||
data: Ref<Array<Champion>>
|
data: Ref<Array<Champion>>
|
||||||
@@ -29,6 +31,7 @@ declare global {
|
|||||||
from?: number[]
|
from?: number[]
|
||||||
price?: number
|
price?: number
|
||||||
priceTotal?: number
|
priceTotal?: number
|
||||||
|
stats?: ItemStats
|
||||||
}
|
}
|
||||||
type SummonerSpell = {
|
type SummonerSpell = {
|
||||||
id: number
|
id: number
|
||||||
|
|||||||
127
match_collector/package-lock.json
generated
127
match_collector/package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"dragon-item-parser": "file:../dragon-item-parser",
|
||||||
"mongodb": "^7.2.0"
|
"mongodb": "^7.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -468,19 +469,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/config-array": {
|
"node_modules/@eslint/config-array": {
|
||||||
"version": "0.21.1",
|
"version": "0.21.2",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
|
||||||
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
|
"integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/object-schema": "^2.1.7",
|
"@eslint/object-schema": "^2.1.7",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"minimatch": "^3.1.2"
|
"minimatch": "^3.1.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@eslint/config-array/node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@eslint/config-array/node_modules/brace-expansion": {
|
"node_modules/@eslint/config-array/node_modules/brace-expansion": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.14",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
||||||
@@ -528,19 +535,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc": {
|
"node_modules/@eslint/eslintrc": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
|
||||||
"integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
|
"integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.12.4",
|
"ajv": "^6.14.0",
|
||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
"espree": "^10.0.1",
|
"espree": "^10.0.1",
|
||||||
"globals": "^14.0.0",
|
"globals": "^14.0.0",
|
||||||
"ignore": "^5.2.0",
|
"ignore": "^5.2.0",
|
||||||
"import-fresh": "^3.2.1",
|
"import-fresh": "^3.2.1",
|
||||||
"js-yaml": "^4.1.1",
|
"js-yaml": "^4.1.1",
|
||||||
"minimatch": "^3.1.2",
|
"minimatch": "^3.1.5",
|
||||||
"strip-json-comments": "^3.1.1"
|
"strip-json-comments": "^3.1.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -550,6 +557,12 @@
|
|||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@eslint/eslintrc/node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
|
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.14",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
||||||
@@ -582,9 +595,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.39.2",
|
"version": "9.39.4",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
|
||||||
"integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
|
"integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -616,27 +629,40 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanfs/core": {
|
"node_modules/@humanfs/core": {
|
||||||
"version": "0.19.1",
|
"version": "0.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
|
||||||
"integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
|
"integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@humanfs/types": "^0.15.0"
|
||||||
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.18.0"
|
"node": ">=18.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanfs/node": {
|
"node_modules/@humanfs/node": {
|
||||||
"version": "0.16.7",
|
"version": "0.16.8",
|
||||||
"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
|
"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz",
|
||||||
"integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
|
"integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@humanfs/core": "^0.19.1",
|
"@humanfs/core": "^0.19.2",
|
||||||
|
"@humanfs/types": "^0.15.0",
|
||||||
"@humanwhocodes/retry": "^0.4.0"
|
"@humanwhocodes/retry": "^0.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.18.0"
|
"node": ">=18.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@humanfs/types": {
|
||||||
|
"version": "0.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz",
|
||||||
|
"integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/module-importer": {
|
"node_modules/@humanwhocodes/module-importer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
|
||||||
@@ -928,9 +954,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.15.0",
|
"version": "8.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
|
||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
@@ -986,10 +1012,13 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "18 || 20 || >=22"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "5.0.5",
|
"version": "5.0.5",
|
||||||
@@ -1003,15 +1032,6 @@
|
|||||||
"node": "18 || 20 || >=22"
|
"node": "18 || 20 || >=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion/node_modules/balanced-match": {
|
|
||||||
"version": "4.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
|
||||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/bson": {
|
"node_modules/bson": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz",
|
||||||
@@ -1106,6 +1126,11 @@
|
|||||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/dragon-item-parser": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "file:../dragon-item-parser",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.27.7",
|
"version": "0.27.7",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
|
||||||
@@ -1160,24 +1185,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.39.2",
|
"version": "9.39.4",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
|
||||||
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.8.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
"@eslint/config-array": "^0.21.1",
|
"@eslint/config-array": "^0.21.2",
|
||||||
"@eslint/config-helpers": "^0.4.2",
|
"@eslint/config-helpers": "^0.4.2",
|
||||||
"@eslint/core": "^0.17.0",
|
"@eslint/core": "^0.17.0",
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.5",
|
||||||
"@eslint/js": "9.39.2",
|
"@eslint/js": "9.39.4",
|
||||||
"@eslint/plugin-kit": "^0.4.1",
|
"@eslint/plugin-kit": "^0.4.1",
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@humanwhocodes/retry": "^0.4.2",
|
"@humanwhocodes/retry": "^0.4.2",
|
||||||
"@types/estree": "^1.0.6",
|
"@types/estree": "^1.0.6",
|
||||||
"ajv": "^6.12.4",
|
"ajv": "^6.14.0",
|
||||||
"chalk": "^4.0.0",
|
"chalk": "^4.0.0",
|
||||||
"cross-spawn": "^7.0.6",
|
"cross-spawn": "^7.0.6",
|
||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
@@ -1196,7 +1221,7 @@
|
|||||||
"is-glob": "^4.0.0",
|
"is-glob": "^4.0.0",
|
||||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
"minimatch": "^3.1.2",
|
"minimatch": "^3.1.5",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"optionator": "^0.9.3"
|
"optionator": "^0.9.3"
|
||||||
},
|
},
|
||||||
@@ -1261,6 +1286,12 @@
|
|||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint/node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/eslint/node_modules/brace-expansion": {
|
"node_modules/eslint/node_modules/brace-expansion": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.14",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
||||||
@@ -1463,7 +1494,6 @@
|
|||||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
@@ -1473,11 +1503,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/get-tsconfig": {
|
"node_modules/get-tsconfig": {
|
||||||
"version": "4.8.1",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
|
||||||
"integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
|
"integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"resolve-pkg-maps": "^1.0.0"
|
"resolve-pkg-maps": "^1.0.0"
|
||||||
},
|
},
|
||||||
@@ -1858,7 +1887,6 @@
|
|||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
@@ -1877,7 +1905,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "",
|
"description": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"dragon-item-parser": "file:../dragon-item-parser",
|
||||||
"mongodb": "^7.2.0"
|
"mongodb": "^7.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
Reference in New Issue
Block a user