@mixxtor/currencyx-js
Version:
Modern TypeScript currency converter with type inference and multiple providers (Google Finance, Fixer.io). Framework agnostic with clean architecture.
389 lines (291 loc) • 9.99 kB
Markdown
# CurrencyX
> Modern TypeScript currency converter with type inference and multiple exchanges. Framework agnostic with clean architecture and minimal dependencies.
[](https://badge.fury.io/js/@mixxtor%2Fcurrencyx-js)
[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
## ✨ Features
- 🚀 **Modern TypeScript** - Full type safety with intelligent inference
- 🔄 **Multiple Exchanges** - Google Finance, Fixer.io, and extensible architecture
- 🎯 **Type Inference** - Smart exchange and configuration type inference
- 🧩 **Framework Agnostic** - Works with any JavaScript/TypeScript project
- 📦 **Minimal Dependencies** - Only axios and cheerio for web scraping
- 🔧 **Extensible** - Easy to add custom exchanges
- 🌐 **Clean APIs** - Intuitive object-based and positional parameter APIs
- ⚡ **High Performance** - Optimized for speed and memory efficiency
## 📦 Installation
```bash
npm install @mixxtor/currencyx-js
```
## 🚀 Quick Start
```typescript
import { createCurrency, exchanges } from '@mixxtor/currencyx-js'
// Create currency service with multiple exchanges
const currency = createCurrency({
default: 'google',
exchanges: {
google: exchanges.google({ base: 'USD' }),
fixer: exchanges.fixer({ accessKey: 'your-api-key' }),
},
})
// Convert currency
const result = await currency.convert({
amount: 100,
from: 'USD',
to: 'EUR',
})
if (result.success) {
console.log(`$100 USD = €${result.result} EUR`)
console.log(`Exchange rate: ${result.info.rate}`)
}
```
## 📚 API Reference
### Core Methods (Object Parameters)
#### `convert(params: ConvertParams)`
Convert currency with explicit object parameters:
```typescript
const result = await currency.convert({
amount: 100,
from: 'USD',
to: 'EUR',
})
// Result structure
interface ConversionResult {
success: boolean
query: { amount: number; from: string; to: string }
result?: number
info?: { rate: number; timestamp: number }
date: string
error?: { info: string; type?: string }
}
```
#### `getExchangeRates(params: ExchangeRatesParams)`
Get exchange rates with object parameters:
```typescript
const rates = await currency.getExchangeRates({
base: 'USD',
codes: ['EUR', 'GBP', 'JPY'],
})
// Result structure
interface ExchangeRatesResult {
success: boolean
base: string
rates: Record<string, number>
timestamp: number
date: string
error?: { info: string; type?: string }
}
```
### Convenience Methods (Positional Parameters)
#### `latestRates({ base, codes })`
Shorthand for getting rates:
```typescript
const rates = await currency.latestRates({ base: 'USD', codes: ['EUR', 'GBP'] })
```
### Exchange Management
```typescript
// Switch exchanges
currency.use('fixer')
// Get current exchange provider
const current = currency.getCurrentExchange() // 'fixer'
// List available exchanges
const exchanges = currency.getAvailableExchanges() // ['google', 'fixer']
```
### Utility Methods
```typescript
// Format currency (object parameters)
const formatted = currency.formatCurrency({ amount: 1234.56, code: 'USD', locale: 'en-US' })
// Result: "$1,234.56"
// Round values
const rounded = currency.round(123.456789, { precision: 2, direction: 'up' })
// Result: 123.46
// Get supported currencies
const currencies = await currency.getSupportedCurrencies()
// Result: ['USD', 'EUR', 'GBP', 'JPY', ...]
// Get current exchange provider
const currentProvider = currency.getCurrentExchange()
// Result: 'google' | 'fixer' | etc.
// Get all available exchanges
const exchanges = currency.getAvailableExchanges()
// Result: ['google', 'fixer']
// Currency information utilities
const allCurrencies = currency.getList()
// Get all available currency information
const usdInfo = currency.getByCode('USD')
// Get currency info by ISO code
const dollarCurrencies = currency.getBySymbol('$')
// Get currency info by symbol
const usCurrency = currency.getByCountry('US')
// Get currency by country code
const euroCurrencies = currency.filterByName('Euro')
// Filter currencies by name
const usCurrencies = currency.filterByCountry('US')
// Filter currencies by country
// Round money according to currency rules
const rounded = currency.roundMoney(123.456, 'USD')
// Automatically rounds according to USD rounding rules
```
## 🔌 Exchanges
### Google Finance Exchange
Free provider, no API key required:
```typescript
const currency = createCurrency({
default: 'google',
exchanges: {
google: exchanges.google({
base: 'USD', // Base currency (default: 'USD')
timeout: 5000, // Request timeout in ms (optional)
}),
},
})
```
### Fixer.io Exchange
Requires API key from [fixer.io](https://fixer.io):
```typescript
const currency = createCurrency({
default: 'fixer',
exchanges: {
fixer: exchanges.fixer({
accessKey: 'your-api-key', // Required: Your Fixer.io API key
base: 'USD', // Base currency (default: 'USD' for this library, Fixer default: 'EUR')
timeout: 10000, // Request timeout in ms (optional)
}),
},
})
```
## ⚙️ Configuration
### Multiple Exchanges Setup
Configure multiple exchanges and switch between them:
```typescript
const currency = createCurrency({
default: 'google',
exchanges: {
google: exchanges.google({ base: 'USD' }),
fixer: exchanges.fixer({ accessKey: 'your-key' }),
},
})
// Use Google Finance
currency.use('google')
const googleResult = await currency.convert({ amount: 100, from: 'USD', to: 'EUR' })
// Switch to Fixer.io
currency.use('fixer')
const fixerResult = await currency.convert({ amount: 100, from: 'USD', to: 'EUR' })
```
### Type Safety
Full TypeScript support with intelligent type inference:
```typescript
// Exchange names are type-safe
const currency = createCurrency({
default: 'google', // ✅ Type-safe
exchanges: {
google: exchanges.google({ base: 'USD' }),
fixer: exchanges.fixer({ accessKey: 'key' }),
},
})
// Only valid exchange names are allowed
currency.use('google') // ✅ Valid
currency.use('invalid') // ❌ TypeScript error
```
## 🛡️ Error Handling
All methods return result objects with success indicators:
```typescript
const result = await currency.convert({
amount: 100,
from: 'USD',
to: 'EUR',
})
if (result.success) {
console.log(`Converted: ${result.result}`)
console.log(`Rate: ${result.info.rate}`)
console.log(`Timestamp: ${result.info.timestamp}`)
} else {
console.error(`Error: ${result.error?.info}`)
console.error(`Type: ${result.error?.type}`)
}
```
## 🔧 Custom Exchanges
Extend the system with custom exchanges:
```typescript
import { BaseCurrencyExchange } from '@mixxtor/currencyx-js'
import type { ConvertParams, ExchangeRatesParams } from '@mixxtor/currencyx-js'
class CustomExchange extends BaseCurrencyExchange {
readonly name = 'custom'
constructor(config: { base: string; apiKey?: string }) {
super()
this.base = config.base || 'USD'
// Initialize with your config
}
async convert(params: ConvertParams) {
try {
// Your custom conversion logic
const rate = await this.getConvertRate(params.from, params.to)
const result = params.amount * rate
return this.createConversionResult(params.amount, params.from, params.to, result, rate)
} catch (error) {
return this.createConversionResult(params.amount, params.from, params.to, undefined, undefined, {
info: error.message,
type: 'custom_error',
})
}
}
async latestRates(params: ExchangeRatesParams) {
try {
// Your custom rates logic
const rates = await this.fetchRatesFromAPI(params)
return this.createExchangeRatesResult(params.base, rates)
} catch (error) {
return this.createExchangeRatesResult(params.base, {}, { info: error.message, type: 'custom_error' })
}
}
async getConvertRate(from: string, to: string): Promise<number> {
// Implement your rate fetching logic
return 0.85 // Example rate
}
private async fetchRatesFromAPI(params: { base: string; codes?: string[] }) {
// Implement your API call logic
return { EUR: 0.85, GBP: 0.73 }
}
}
// Use your custom exchange
const currency = createCurrency({
default: 'custom',
exchanges: {
custom: new CustomExchange({ base: 'USD', apiKey: 'your-key' }),
},
})
```
## 📖 Examples
Check the [examples](./examples) directory for more usage patterns:
- [Selective API Demo](./examples/selective-api-demo.ts) - Demonstrates the API design principles
## 🔄 Migration Guide
### From v0.x to v1.x
The API has been simplified and modernized:
```typescript
// Old API (v0.x)
const currency = new CurrencyService()
currency.addProvider('google', new GoogleProvider())
const result = await currency.convert(100, 'USD', 'EUR')
// New API (v1.x)
const currency = createCurrency({
default: 'google',
exchanges: {
google: exchanges.google({ base: 'USD' }),
},
})
const result = await currency.convert({ amount: 100, from: 'USD', to: 'EUR' })
```
## 📋 Requirements
- **Node.js** >= 18.0.0
- **TypeScript** >= 4.5.0 (for TypeScript projects)
## Dependencies
- **axios** - For HTTP requests to currency APIs
- **cheerio** - For HTML parsing (Google Finance web scraping)
## 🤝 Contributing
Contributions are welcome! Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
## 📄 License
MIT License - see [LICENSE](./LICENSE) file for details.
## 📝 Changelog
See [CHANGELOG.md](./CHANGELOG.md) for version history and changes.
---
<div align="center">
**[Documentation](https://github.com/mixxtor/currencyx-js#readme)** • **[Examples](./examples)** • **[Issues](https://github.com/mixxtor/currencyx-js/issues)** • **[Contributing](./CONTRIBUTING.md)**
</div>