@classytic/bd-logistics
v1.0.3
Published
Production-grade Bangladesh logistics SDK - RedX, Pathao, Steadfast with unified API, circuit breaker, and retries
Maintainers
Readme
@classytic/bd-logistics
Production-grade Bangladesh logistics SDK with unified API for RedX, Pathao, and Steadfast. Features circuit breaker, automatic retries, and webhook handling.
Installation
npm install @classytic/bd-logisticsFeatures
- Multi-Provider: RedX (more providers coming soon)
- Unified API: Same interface across all providers
- Circuit Breaker: Automatic failure detection and recovery
- Retry Logic: Exponential backoff with configurable attempts
- TypeScript First: Full type definitions
- Webhook Parsing: Normalized status updates
Quick Start
import { createLogisticsClient } from '@classytic/bd-logistics';
const client = createLogisticsClient({
provider: 'redx',
apiUrl: 'https://openapi.redx.com.bd/v1.0.0-beta',
apiKey: 'your-api-key',
});
// Create shipment
const { trackingId } = await client.createShipment(order, {
deliveryAreaId: 1,
deliveryAreaName: 'Mohammadpur',
pickupStoreId: 1,
cashCollectionAmount: 1500,
weight: 500,
});
// Track shipment
const tracking = await client.trackShipment(trackingId);
console.log(tracking.status); // 'in-transit', 'delivered', etc.API Reference
Client Creation
import { createLogisticsClient } from '@classytic/bd-logistics';
const client = createLogisticsClient({
provider: 'redx',
apiUrl: 'https://openapi.redx.com.bd/v1.0.0-beta',
apiKey: 'your-jwt-token',
settings: {
timeout: 15000, // Request timeout (ms)
maxRetries: 3, // Retry attempts
retryDelay: 1000, // Base retry delay (ms)
circuitBreakerThreshold: 5,
circuitBreakerResetTimeout: 30000,
},
});Shipment Operations
| Method | Description |
|--------|-------------|
| createShipment(order, options) | Create a new shipment |
| trackShipment(trackingId) | Get tracking timeline |
| getShipmentDetails(trackingId) | Get full shipment details |
| cancelShipment(trackingId, reason?) | Cancel a shipment |
Area & Store Operations
| Method | Description |
|--------|-------------|
| getAreas(filters?) | Get delivery areas |
| getPickupStores() | List pickup stores |
| createPickupStore(data) | Create pickup store |
| getPickupStoreDetails(storeId) | Get store details |
Charge Calculation
const charge = await client.calculateCharge({
deliveryAreaId: 1,
pickupAreaId: 10,
cashCollectionAmount: 1500,
weight: 500, // grams
});
console.log(charge);
// { deliveryCharge: 60, codCharge: 15, totalCharge: 75 }Webhook Handling
// In your webhook endpoint
app.post('/webhooks/redx', (req, res) => {
const payload = client.parseWebhook(req.body);
console.log(payload.trackingId); // 'REDX12345678'
console.log(payload.status); // 'delivered' (normalized)
console.log(payload.providerStatus); // 'delivered' (raw)
console.log(payload.message); // 'Parcel delivered'
// Update your order status
await updateOrderStatus(payload.merchantInvoiceId, payload.status);
res.sendStatus(200);
});Unified Status Mapping
Provider statuses are normalized to a unified format:
| Unified Status | RedX Status |
|----------------|-------------|
| pickup-requested | pickup-pending |
| picked-up | ready-for-delivery |
| out-for-delivery | delivery-in-progress |
| delivered | delivered |
| in-transit | agent-hold, agent-area-change |
| returning | agent-returning |
| returned | returned |
| cancelled | cancelled |
Error Handling
import {
LogisticsError,
ProviderAPIError,
ValidationError,
CircuitOpenError,
} from '@classytic/bd-logistics';
try {
await client.createShipment(order, options);
} catch (error) {
if (error instanceof ValidationError) {
console.log('Validation failed:', error.errors);
} else if (error instanceof ProviderAPIError) {
console.log('API error:', error.status, error.message);
} else if (error instanceof CircuitOpenError) {
console.log('Service temporarily unavailable');
}
}Circuit Breaker
Monitor and reset circuit breaker state:
// Check circuit status
const status = client.getCircuitStatus();
console.log(status);
// { name: 'redx', state: 'closed', failureCount: 0, lastFailureTime: null }
// Reset circuit after fixing issues
client.resetCircuit();
// Get all circuit statuses (for monitoring)
import { getAllCircuitStatuses } from '@classytic/bd-logistics';
const allStatuses = getAllCircuitStatuses();With @classytic/bd-areas
Use with the companion area package for complete integration:
import { getArea, getAreaByProvider } from '@classytic/bd-areas';
import { createLogisticsClient } from '@classytic/bd-logistics';
// Get area from your database
const area = getArea(savedAddress.areaId);
// Create shipment with provider-specific area ID
await client.createShipment(order, {
deliveryAreaId: area.providers.redx!,
deliveryAreaName: area.name,
// ...
});Environment Variables
# Sandbox
REDX_API_URL=https://sandbox.redx.com.bd/v1.0.0-beta
REDX_API_KEY=your-sandbox-jwt-token
# Production
REDX_API_URL=https://openapi.redx.com.bd/v1.0.0-beta
REDX_API_KEY=your-production-jwt-tokenLicense
MIT © Classytic
