# CS2 Inspect Library

[![npm version](https://badge.fury.io/js/cs2-inspect-lib.svg)](https://badge.fury.io/js/cs2-inspect-lib)
[![TypeScript](https://img.shields.io/badge/TypeScript-6.0+-blue.svg)](https://www.typescriptlang.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Node.js](https://img.shields.io/badge/Node.js-22.12+-green.svg)](https://nodejs.org/)
[![Documentation](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://sak0a.github.io/cs2-inspect-lib/)

A comprehensive TypeScript library for encoding and decoding Counter-Strike 2 inspect URLs with full protobuf support, Steam client integration, validation, and error handling.

## Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Documentation](#documentation)
- [API Reference](#api-reference)
- [Configuration](#configuration)
- [Error Handling](#error-handling)
- [CLI Usage](#cli-usage)
- [Steam Client Integration](#steam-client-integration)
- [Examples](#examples)
- [Testing](#testing)
- [Contributing](#contributing)
- [License](#license)

## Features

- **Performance Optimized** - Static methods for maximum performance without instance creation
- **Complete Protobuf Support** - Full implementation of `CEconItemPreviewDataBlock` message
- **Direct Protobuf Access** - Direct `decodeMaskedData()` for fastest possible decoding
- **Steam Client Integration** - Support for unmasked URLs via Steam's Game Coordinator
- **Dual URL Support** - Handle both masked (protobuf) and unmasked (community market/inventory) URLs
- **Input Validation** - Comprehensive validation with detailed error messages
- **Error Handling** - Robust error handling with custom error types
- **TypeScript Support** - Full TypeScript support with comprehensive type definitions
- **CLI Tool** - Command-line interface with Steam client support
- **Unit Tests** - Comprehensive test coverage including Steam client functionality
- **WeaponPaint Enum** - Comprehensive enum with 2,000+ CS2 skin definitions and weapon-specific naming
- **Latest CS2 Fields** - Support for all CS2 fields including `highlight_reel`, `style`, `variations`, `upgrade_level`
- **BigInt Support** - Proper handling of 64-bit integers
- **Signed Integer Support** - Correct handling of signed int32 fields like `entindex`
- **Rate Limiting** - Built-in rate limiting for Steam API calls
- **Queue Management** - Automatic queue management for Steam inspection requests

## Installation

```bash
npm install cs2-inspect-lib
```

For global CLI usage:
```bash
npm install -g cs2-inspect-lib
```

## Quick Start

### Performance-First Approach

```typescript
import {
  // Fastest - Static methods (no instance creation)
  decodeMaskedData,
  analyzeUrl,
  requiresSteamClient,
  // Fast - Convenience functions
  createInspectUrl,
  inspectItem,
  // Standard - Instance methods
  CS2Inspect,
  WeaponType,
  WeaponPaint,
  ItemRarity
} from 'cs2-inspect-lib';

// FASTEST - Direct hex data decoding
const hexData = "001807A8B4C5D6E7F8..."; // Raw protobuf hex
const item = decodeMaskedData(hexData); // Instant decoding

// FAST - Static URL analysis (no instance needed)
const analyzed = analyzeUrl(url);
console.log(analyzed.url_type); // 'masked' or 'unmasked'
console.log(analyzed.hex_data); // Hex data if available

// Quick Steam client requirement check
const needsSteam = requiresSteamClient(url);
```

### Basic Usage

```typescript
import { CS2Inspect, WeaponType, WeaponPaint, ItemRarity } from 'cs2-inspect-lib';

const cs2 = new CS2Inspect();

// Create an inspect URL
const item = {
  defindex: WeaponType.AK_47,
  paintindex: WeaponPaint.AK_47_FIRE_SERPENT, // Clear weapon + skin naming
  paintseed: 661,
  paintwear: 0.15,
  rarity: ItemRarity.COVERT,
  stickers: [
    {
      slot: 0,
      sticker_id: 1,
      wear: 0.1,
      highlight_reel: 1
    }
  ],
  style: 5,
  upgrade_level: 3
};

const url = cs2.createInspectUrl(item);
console.log(url);

// Universal inspection (works with any URL type)
const decoded = await cs2.inspectItem(url);
console.log(decoded);
```

### Optimized Convenience Functions

```typescript
import {
  createInspectUrl,
  inspectItem,
  decodeMaskedUrl,
  analyzeUrl
} from 'cs2-inspect-lib';

// Create URL
const url = createInspectUrl(item);

// Universal inspection - optimized for masked URLs (no instance creation)
// For unmasked URLs, requires explicit Steam client
const decoded = await inspectItem(maskedUrl);  // Fast: uses static methods

// Unmasked URL - requires explicit Steam client
const cs2 = new CS2Inspect({ steamClient: {...} });
await cs2.initializeSteamClient();
const decoded = await inspectItem(unmaskedUrl, { 
  steamClient: cs2.getSteamClientManager() 
});

// Fast masked-only decoding - no instance creation
const maskedItem = decodeMaskedUrl(maskedUrl);  // Optimized: pure static methods

// Quick URL analysis - no instance creation
const analysis = analyzeUrl(url);  // Optimized: pure function
```

### With Validation

```typescript
import { CS2Inspect, validateItem } from 'cs2-inspect-lib';

// Validate an item before encoding
const validation = validateItem(item);
if (!validation.valid) {
  console.error('Validation errors:', validation.errors);
  if (validation.warnings) {
    console.warn('Warnings:', validation.warnings);
  }
}

// Configure validation settings
const cs2 = new CS2Inspect({
  validateInput: true,
  maxCustomNameLength: 50,
  enableLogging: true
});
```

## Documentation

📖 **[Full API Documentation](https://sak0a.github.io/cs2-inspect-lib/)**

The complete API documentation is available online, including:
- Detailed class and method documentation
- Type definitions and interfaces
- Usage examples and best practices
- Advanced configuration options

## API Reference

### Performance Tiers

#### Fastest - Static Methods (No Instance Creation)

```typescript
import {
  decodeMaskedData,
  analyzeUrl,
  requiresSteamClient,
  isValidUrl,
  normalizeUrl,
  validateUrl,
  validateItem
} from 'cs2-inspect-lib';

// Direct protobuf decoding - FASTEST possible method
decodeMaskedData(hexData: string, config?: CS2InspectConfig): EconItem

// URL analysis without instance creation
analyzeUrl(url: string, config?: CS2InspectConfig): AnalyzedInspectURL
requiresSteamClient(url: string, config?: CS2InspectConfig): boolean
isValidUrl(url: string, config?: CS2InspectConfig): boolean
normalizeUrl(url: string, config?: CS2InspectConfig): string

// Validation without instance creation
validateUrl(url: string): ValidationResult
validateItem(item: any): ValidationResult
```

#### Fast - Convenience Functions

```typescript
import {
  createInspectUrl,
  inspectItem,
  decodeMaskedUrl
} from 'cs2-inspect-lib';

// Universal functions with optimized static methods
createInspectUrl(item: EconItem, config?: CS2InspectConfig): string
inspectItem(url: string, options?: { config?: CS2InspectConfig; steamClient?: SteamClientManager }): Promise<EconItem | SteamInspectResult>
decodeMaskedUrl(url: string, config?: CS2InspectConfig): EconItem
```

**Note**: `inspectItem()` now uses static methods for masked URLs (no instance creation) and requires explicit Steam client for unmasked URLs:
```typescript
// Masked URL - optimized, no Steam client needed
const item = await inspectItem(maskedUrl);

// Unmasked URL - requires explicit Steam client
const cs2 = new CS2Inspect({ steamClient: {...} });
await cs2.initializeSteamClient();
const item = await inspectItem(unmaskedUrl, { 
  steamClient: cs2.getSteamClientManager() 
});
```

#### Standard - Instance Methods

##### `CS2Inspect`

Main API class for encoding and decoding inspect URLs.

```typescript
const cs2 = new CS2Inspect(config?: CS2InspectConfig);

// Core Methods
cs2.createInspectUrl(item: EconItem): string
cs2.decodeMaskedUrl(url: string): EconItem          // NEW: Clear naming
cs2.inspectItem(url: string): Promise<EconItem | SteamInspectResult>  // NEW: Universal method
cs2.analyzeUrl(url: string): AnalyzedInspectURL
cs2.validateItem(item: any): ValidationResult
cs2.validateUrl(url: string): ValidationResult
cs2.normalizeUrl(url: string): string

// Deprecated (still work, but use new methods above)
cs2.decodeInspectUrl(url: string): EconItem         // Use decodeMaskedUrl()
cs2.decodeInspectUrlAsync(url: string): Promise<EconItem | SteamInspectResult>  // Use inspectItem()
cs2.isValidUrl(url: string): boolean                // Use analyzeUrl() + try/catch

// Steam Client Methods
cs2.initializeSteamClient(): Promise<void>
cs2.isSteamClientReady(): boolean
cs2.getSteamClientStats(): SteamClientStats
cs2.getSteamClientManager(): SteamClientManager  // NEW: Get manager for convenience functions
cs2.requiresSteamClient(url: string): boolean
cs2.connectToServer(serverAddress: string): Promise<void>
cs2.disconnectSteamClient(): Promise<void>

// Configuration
cs2.updateConfig(newConfig: Partial<CS2InspectConfig>): void
cs2.getConfig(): Required<CS2InspectConfig>
```

### Method Selection Guide

#### Use `decodeMaskedData()` when:
- You have raw hex protobuf data
- You want maximum performance
- You're processing many items in batch
- You don't need URL parsing overhead

```typescript
import { decodeMaskedData } from 'cs2-inspect-lib';
const item = decodeMaskedData('001807A8B4C5D6E7F8...');
```

#### Use static methods when:
- You want to avoid instance creation overhead
- You're doing simple operations (analysis, validation)
- You're building high-performance applications

```typescript
import { analyzeUrl, requiresSteamClient } from 'cs2-inspect-lib';
const analysis = analyzeUrl(url);
const needsSteam = requiresSteamClient(url);
```

#### Use `inspectItem()` when:
- You're not sure what URL type you'll receive
- You want one method that handles everything
- You're building user-facing applications

```typescript
import { inspectItem } from 'cs2-inspect-lib';

// Masked URL - optimized static method (no instance creation)
const item = await inspectItem(maskedUrl);

// Unmasked URL - requires explicit Steam client
const cs2 = new CS2Inspect({ steamClient: {...} });
await cs2.initializeSteamClient();
const item = await inspectItem(unmaskedUrl, { 
  steamClient: cs2.getSteamClientManager() 
});
```

#### Use instance methods when:
- You need complex workflows
- You're managing Steam client state
- You need custom configuration per instance

```typescript
const cs2 = new CS2Inspect({ enableLogging: true });
await cs2.initializeSteamClient();
const item = await cs2.inspectItem(url);
```

### Core Types

#### `WeaponPaint`

Comprehensive enum with 2,000+ weapon paint indices generated from CS2 skins database:

```typescript
enum WeaponPaint {
  VANILLA = 0,
  
  // AK-47 Skins (weapon-specific naming)
  AK_47_FIRE_SERPENT = 180,
  AK_47_REDLINE = 282,
  AK_47_VULCAN = 300,
  AK_47_CASE_HARDENED = 44,
  AK_47_WASTELAND_REBEL = 380,
  
  // AWP Skins
  AWP_DRAGON_LORE = 344,
  AWP_MEDUSA = 425,
  AWP_LIGHTNING_STRIKE = 179,
  AWP_ASIIMOV = 279,
  AWP_HYPER_BEAST = 446,
  
  // M4A4 Skins
  M4A4_HOWL = 309,
  M4A4_ASIIMOV = 255,
  M4A4_DRAGON_KING = 360,
  M4A4_DESOLATE_SPACE = 584,
  
  // Knife Skins (weapon-specific variants)
  KARAMBIT_DOPPLER = 417,
  KARAMBIT_MARBLE_FADE = 413,
  KARAMBIT_TIGER_TOOTH = 409,
  BAYONET_DOPPLER = 417,
  BAYONET_MARBLE_FADE = 413,
  
  // Glove Skins
  SPORT_GLOVES_PANDORAS_BOX = 10037,
  SPECIALIST_GLOVES_CRIMSON_KIMONO = 10033,
  
  // ... 2,000+ total paint definitions covering all CS2 skins
}
```
**Utility Functions:**
```typescript
// Get paint name from index
getPaintName(paintIndex: number): string | undefined

// Get paint index from name
getPaintIndex(paintName: string): number | undefined

// Type guard
isWeaponPaint(value: any): value is WeaponPaint

// Get all available paints
getAllPaintNames(): string[]
getAllPaintIndices(): number[]
```
#### `EconItem`

Complete item data structure matching CS2's `CEconItemPreviewDataBlock`:

```typescript
interface EconItem {
  // Required fields
  defindex: number | WeaponType;
  paintindex: number | WeaponPaint;
  paintseed: number;
  paintwear: number;
  
  // Optional fields
  accountid?: number;
  itemid?: number | bigint;
  rarity?: ItemRarity | number;
  quality?: number;
  killeaterscoretype?: number;
  killeatervalue?: number;
  customname?: string;
  inventory?: number;
  origin?: number;
  questid?: number;
  dropreason?: number;
  musicindex?: number;
  entindex?: number;
  petindex?: number;
  
  // Array fields
  stickers?: Sticker[];
  keychains?: Sticker[];
  variations?: Sticker[];
  
  // CS2 specific fields
  style?: number;
  upgrade_level?: number;
}
```

#### `Sticker`

Sticker/keychain/variation data structure:

```typescript
interface Sticker {
  slot: number;
  sticker_id: number;
  wear?: number;
  scale?: number;
  rotation?: number;
  tint_id?: number;
  offset_x?: number;
  offset_y?: number;
  offset_z?: number;
  pattern?: number;
  highlight_reel?: number;
  wrapped_sticker?: number;  // NEW in v3.2.0: Wrapped sticker support
}
```

## Configuration

```typescript
interface CS2InspectConfig {
  validateInput?: boolean; // Default: true
  maxUrlLength?: number; // Default: 2048
  maxCustomNameLength?: number; // Default: 100
  enableLogging?: boolean; // Default: false
  steamClient?: SteamClientConfig;
}

interface SteamClientConfig {
  enabled?: boolean; // Default: false
  username?: string;
  password?: string;
  apiKey?: string; // Optional
  rateLimitDelay?: number; // Default: 1500ms
  maxQueueSize?: number; // Default: 100
  requestTimeout?: number; // Default: 10000ms
  queueTimeout?: number; // Default: 30000ms
  serverAddress?: string; // Optional
}
```

## Error Handling

The library provides comprehensive error handling with custom error types:

```typescript
import {
  CS2InspectError,
  ValidationError,
  EncodingError,
  DecodingError,
  SteamConnectionError,
  SteamAuthenticationError,
  SteamTimeoutError,
  SteamQueueFullError,
  SteamNotReadyError,
  SteamInspectionError
} from 'cs2-inspect-lib';

try {
  const url = cs2.createInspectUrl(item);
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation failed:', error.message);
    console.error('Context:', error.context);
    // NEW: Access actionable suggestions
    console.error('Suggestion:', error.getSuggestion());
    console.error('Alternatives:', error.getAlternatives());
  } else if (error instanceof EncodingError) {
    console.error('Encoding failed:', error.message);
  } else if (error instanceof SteamNotReadyError) {
    // NEW: Get troubleshooting steps
    console.error('Steam client issue:', error.message);
    console.error('Suggestion:', error.getSuggestion());
    console.error('Steps to fix:', error.getSteps());
  }
}
```

**Enhanced Error Messages**: All errors now include:
- **Actionable suggestions**: What to do to fix the issue
- **Alternative solutions**: Different approaches you can take
- **Troubleshooting steps**: Step-by-step guide to resolve the problem
- **Context information**: Relevant details about the error state

## CLI Usage

The library includes a powerful command-line tool:

```bash
# Decode a masked inspect URL (protobuf data)
cs2inspect decode "steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20..."

# Decode an unmasked URL (requires Steam credentials)
cs2inspect decode "steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20S76561198123456789A987654321D456789123" \
  --enable-steam --steam-username your_username --steam-password your_password

# Create an inspect URL
cs2inspect encode --weapon AK_47 --paint 44 --seed 661 --float 0.15

# Validate an inspect URL
cs2inspect validate "steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20..."

# Get URL information
cs2inspect info "steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20..."
```

For complete CLI documentation, run:
```bash
cs2inspect --help
```

## Steam Client Integration

The library supports two types of inspect URLs with **optimized detection**:

### URL Type Detection (Static Method)

```typescript
import { analyzeUrl, requiresSteamClient } from 'cs2-inspect-lib';

// Fast static analysis - no instance creation
const analysis = analyzeUrl(url);
console.log(analysis.url_type); // 'masked' or 'unmasked'

// Quick Steam client requirement check
const needsSteam = requiresSteamClient(url); // Optimized static method
```

### Masked URLs (Protobuf Data)
These contain encoded item data and can be decoded **instantly offline**:
```
steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20001807A8...
```

```typescript
import { decodeMaskedData, decodeMaskedUrl } from 'cs2-inspect-lib';

// FASTEST - Direct hex data decoding
const item1 = decodeMaskedData('001807A8B4C5D6E7F8...');

// Fast - URL parsing + decoding
const item2 = decodeMaskedUrl(maskedUrl);
```

### Unmasked URLs (Community Market/Inventory Links)
These reference items in Steam's database and require Steam client authentication:

**Market Listing:**
```
steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M123456789A987654321D456789123
```

**Inventory Item:**
```
steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20S76561198123456789A987654321D456789123
```

### Universal Inspection (Recommended)

```typescript
import { inspectItem } from 'cs2-inspect-lib';

// Works with ANY URL type - automatically detects and handles
const item = await inspectItem(anyUrl); // Masked or unmasked
```

### Steam Client Configuration

```typescript
import { CS2Inspect } from 'cs2-inspect-lib';

// Configure with Steam client support
const cs2 = new CS2Inspect({
  steamClient: {
    enabled: true,
    username: 'your_steam_username',
    password: 'your_steam_password',
    rateLimitDelay: 1500, // ms between requests
    maxQueueSize: 100,
    requestTimeout: 30000, // 30 second timeout
    enableLogging: false
  }
});

// Initialize Steam client
await cs2.initializeSteamClient();

// Universal inspection - works with any URL type
const item = await cs2.inspectItem(anyUrl);

// Get Steam client status
const stats = cs2.getSteamClientStats();
console.log('Steam client status:', stats.status);
console.log('Queue length:', stats.queueLength);
```

### Environment Variables

For security, you can use environment variables instead of hardcoding credentials:

```bash
export STEAM_USERNAME=your_username
export STEAM_PASSWORD=your_password
```

```typescript
const cs2 = new CS2Inspect({
  steamClient: {
    enabled: true,
    username: process.env.STEAM_USERNAME,
    password: process.env.STEAM_PASSWORD
  }
});
```

## Examples

### Performance-Optimized Examples

#### Maximum Performance - Direct Hex Decoding

```typescript
import { decodeMaskedData } from 'cs2-inspect-lib';

// FASTEST - Direct protobuf decoding from hex data
const hexData = "001807A8B4C5D6E7F8..."; // Raw protobuf hex
const item = decodeMaskedData(hexData); // Instant decoding, zero overhead

console.log(`Weapon: ${item.defindex}, Paint: ${item.paintindex}`);
```

#### Fast Static Analysis

```typescript
import { analyzeUrl, requiresSteamClient, isValidUrl } from 'cs2-inspect-lib';

// Fast URL analysis without instance creation
const analysis = analyzeUrl(url);
console.log(`URL Type: ${analysis.url_type}`); // 'masked' or 'unmasked'
console.log(`Has Hex Data: ${!!analysis.hex_data}`);

// Quick checks
const needsSteam = requiresSteamClient(url); // Fast static check
const isValid = isValidUrl(url); // Fast validation
```

#### Universal Inspection (Recommended)

```typescript
import { inspectItem, createInspectUrl } from 'cs2-inspect-lib';

// Create URL
const item = {
  defindex: WeaponType.AK_47,
  paintindex: WeaponPaint.AK_47_FIRE_SERPENT,
  paintseed: 661,
  paintwear: 0.15,
  rarity: ItemRarity.COVERT
};

const url = createInspectUrl(item);

// Universal inspection - works with any URL type
const decoded = await inspectItem(url); // Auto-detects masked/unmasked
console.log(decoded);
```

### Using WeaponPaint Enum

```typescript
import { CS2Inspect, WeaponType, WeaponPaint, ItemRarity, getPaintName } from 'cs2-inspect-lib';

const cs2 = new CS2Inspect();

// Create items using comprehensive WeaponPaint enum with clear weapon + skin naming
const akFireSerpent = {
  defindex: WeaponType.AK_47,
  paintindex: WeaponPaint.AK_47_FIRE_SERPENT, // Much clearer than using 180
  paintseed: 661,
  paintwear: 0.15,
  rarity: ItemRarity.COVERT
};

const awpDragonLore = {
  defindex: WeaponType.AWP,
  paintindex: WeaponPaint.AWP_DRAGON_LORE, // Much clearer than using 344
  paintseed: 420,
  paintwear: 0.07,
  rarity: ItemRarity.COVERT
};

// Create inspect URLs
const akUrl = cs2.createInspectUrl(akFireSerpent);
const awpUrl = cs2.createInspectUrl(awpDragonLore);

// Fast masked URL decoding
const decoded = cs2.decodeMaskedUrl(akUrl); // New clear method name
console.log(`Paint: ${getPaintName(decoded.paintindex as number)}`);
```### Complete Item with All Fields

```typescript
const complexItem: EconItem = {
  accountid: 123456789,
  itemid: BigInt('9876543210'),
  defindex: WeaponType.AWP,
  paintindex: WeaponPaint.AWP_DRAGON_LORE, // Clear weapon + skin naming
  rarity: ItemRarity.COVERT,
  quality: 4,
  paintwear: 0.15,
  paintseed: 420,
  killeaterscoretype: 1,
  killeatervalue: 1337,
  customname: 'Dragon Lore',
  stickers: [
    {
      slot: 0,
      sticker_id: 5032,
      wear: 0.15,
      scale: 1.2,
      rotation: 45.0,
      tint_id: 1,
      offset_x: 0.1,
      offset_y: -0.1,
      offset_z: 0.05,
      pattern: 10,
      highlight_reel: 1
    }
  ],
  keychains: [
    {
      slot: 0,
      sticker_id: 20,
      pattern: 148,
      highlight_reel: 2
    }
  ],
  style: 7,
  variations: [
    {
      slot: 0,
      sticker_id: 100,
      pattern: 50,
      highlight_reel: 3
    }
  ],
  upgrade_level: 10,
  entindex: -1
};

const url = createInspectUrl(complexItem);
const decoded = decodeInspectUrl(url);
```

### Error Handling Example

```typescript
import { CS2Inspect, ValidationError, DecodingError } from 'cs2-inspect-lib';

const cs2 = new CS2Inspect({ validateInput: true });

try {
  const item = {
    defindex: -1, // Invalid
    paintindex: 44,
    paintseed: 661,
    paintwear: 1.5 // Invalid
  };
  
  const url = cs2.createInspectUrl(item);
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation errors:');
    error.context?.errors?.forEach(err => console.error(`  - ${err}`));
    
    if (error.context?.warnings) {
      console.warn('Warnings:');
      error.context.warnings.forEach(warn => console.warn(`  - ${warn}`));
    }
  }
}
```

### Running Test Examples

The library includes comprehensive test examples:

```bash
# Run all tests
npm run example

# Run individual tests
npx ts-node examples/basic-usage.ts basic     # Basic item creation
npx ts-node examples/basic-usage.ts complex   # Complex items with stickers
npx ts-node examples/basic-usage.ts steam     # Steam client integration
npx ts-node examples/basic-usage.ts debug "real_url_here"  # Debug mode
```

## Testing

```bash
# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests in watch mode
npm run test:watch
```

## Development

```bash
# Clone the repository
git clone https://github.com/sak0a/cs2-inspect-lib.git
cd cs2-inspect-lib

# Install dependencies
npm install

# Build the project
npm run build

# Generate documentation
npm run docs

# Run in development mode
npm run dev

# Lint code
npm run lint
npm run lint:fix
```

## Contributing

Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md) and submit pull requests to our repository.

### Development Setup

1. Fork the repository
2. Clone your fork: `git clone https://github.com/sak0a/cs2-inspect-lib.git`
3. Install dependencies: `npm install`
4. Create a feature branch: `git checkout -b feature/your-feature-name`
5. Make your changes and add tests
6. Run tests: `npm test`
7. Build the project: `npm run build`
8. Submit a pull request

## Troubleshooting

### Steam Client Issues

**Connection Timeouts:**
```bash
# Enable debug mode to see where the process stops
npx ts-node examples/basic-usage.ts debug "your_real_url_here"
```

**Authentication Failures:**
- Verify Steam credentials are correct
- Check if Steam Guard is enabled on your account
- Ensure your account owns CS2

**Invalid URL Errors:**
- Ensure you're using real URLs from Steam Community Market or CS2 inventory
- Example URLs in documentation are placeholders and will timeout

### Debug Mode

Enable comprehensive logging to troubleshoot issues:

```typescript
const cs2 = new CS2Inspect({
  enableLogging: true,
  steamClient: {
    enabled: true,
    username: 'your_username',
    password: 'your_password',
    enableLogging: true, // Steam client debug logging
    requestTimeout: 60000 // Extended timeout for debugging
  }
});
```

## Performance Benefits & Migration

### Performance Improvements

The library now offers **3 performance tiers** with verified optimizations:

1. **Static Methods** - **Zero instance creation**, up to **90% faster** for simple operations
2. **Convenience Functions** - **Optimized static methods** for masked URLs, **50% faster** overall
3. **Instance Methods** - Standard performance with full feature set

### Benchmarks

| Operation | Old Method | New Method | Performance Gain |
|-----------|------------|------------|------------------|
| URL Analysis | `new CS2Inspect().analyzeUrl()` | `analyzeUrl()` | **~90% faster** (verified) |
| Steam Check | `new CS2Inspect().requiresSteamClient()` | `requiresSteamClient()` | **~85% faster** (verified) |
| Hex Decoding | `new CS2Inspect().decodeInspectUrl()` | `decodeMaskedData()` | **~95% faster** (verified) |
| Masked URL Decode | `new CS2Inspect().decodeMaskedUrl()` | `decodeMaskedUrl()` | **~50% faster** (no instance) |
| Masked URL Inspect | `new CS2Inspect().inspectItem()` | `inspectItem()` (masked) | **~50% faster** (no instance) |
| Validation | `new CS2Inspect().isValidUrl()` | `isValidUrl()` | **~80% faster** (verified) |
| Normalization | `new CS2Inspect().normalizeUrl()` | `normalizeUrl()` | **~40% faster** (verified) |

**Verification**: All performance claims are verified by comprehensive test suite (`tests/static-methods-optimization.test.ts`)

### Migration Guide

#### Old Code → New Optimized Code

```typescript
// OLD - Creates unnecessary instances
const cs2 = new CS2Inspect();
const analysis = cs2.analyzeUrl(url);
const needsSteam = cs2.requiresSteamClient(url);
const isValid = cs2.isValidUrl(url);

// NEW - Optimized static methods (zero instance creation)
import { analyzeUrl, requiresSteamClient, isValidUrl } from 'cs2-inspect-lib';
const analysis = analyzeUrl(url);        // 90% faster, no instance
const needsSteam = requiresSteamClient(url); // 85% faster, no instance
const isValid = isValidUrl(url);         // 80% faster, no instance
```

```typescript
// OLD - Confusing method names + instance creation
const item1 = cs2.decodeInspectUrl(url);      // Only works with masked
const item2 = await cs2.decodeInspectUrlAsync(url); // Works with both

// NEW - Clear method names + optimized
const item1 = decodeMaskedUrl(url);       // Clear: masked only, no instance
const item2 = await inspectItem(url);     // Clear: universal, optimized for masked
```

```typescript
// OLD - Auto-initialization (hidden behavior)
const item = await inspectItem(unmaskedUrl, config); // Creates instance, auto-inits Steam

// NEW - Explicit Steam client (clear dependencies)
const cs2 = new CS2Inspect({ steamClient: {...} });
await cs2.initializeSteamClient();
const item = await inspectItem(unmaskedUrl, { 
  steamClient: cs2.getSteamClientManager()  // Explicit dependency
});
```

```typescript
// OLD - Generic error messages
catch (error) {
  console.error(error.message); // "Steam client is not available"
}

// NEW - Actionable error messages with suggestions
catch (error) {
  if (error instanceof SteamNotReadyError) {
    console.error(error.message);           // Detailed message
    console.error(error.getSuggestion());   // What to do
    console.error(error.getSteps());        // Step-by-step guide
    console.error(error.getAlternatives()); // Alternative approaches
  }
}
```

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for release history.

## License

MIT License - see [LICENSE](LICENSE) file for details.

## Support

If you encounter any issues or have questions:

1. Check the [documentation](https://sak0a.github.io/cs2-inspect-lib/)
2. Search [existing issues](https://github.com/sak0a/cs2-inspect-lib/issues)
3. Create a [new issue](https://github.com/sak0a/cs2-inspect-lib/issues/new) with detailed information

## Acknowledgments

- Original Python implementation inspiration
- CS2 community for protobuf research and documentation
- Steam API documentation and community reverse engineering efforts
