UNPKG

autotrader-connect-api

Version:

Production-ready TypeScript wrapper for Auto Trader UK Connect APIs

844 lines (655 loc) โ€ข 20.1 kB
# autotrader-connect-api [![NPM Version](https://img.shields.io/npm/v/autotrader-connect-api.svg)](https://www.npmjs.com/package/autotrader-connect-api) [![Build Status](https://github.com/your-org/autotrader-connect/workflows/CI/badge.svg)](https://github.com/your-org/autotrader-connect/actions) [![Coverage Status](https://codecov.io/gh/your-org/autotrader-connect/branch/main/graph/badge.svg)](https://codecov.io/gh/your-org/autotrader-connect) [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) A production-ready TypeScript wrapper for the Auto Trader UK Connect APIs. This package provides a comprehensive, type-safe interface to interact with AutoTrader's vehicle data, stock management, search, and other automotive services. ## Features - ๐Ÿš€ **Production Ready**: Built with enterprise-grade error handling, retry logic, and rate limiting - ๐Ÿ”’ **Type Safe**: Full TypeScript support with comprehensive type definitions - ๐Ÿ” **Secure Authentication**: Automatic OAuth2 token management with refresh capabilities - โšก **Performance Optimized**: Built-in rate limiting and request batching - ๐Ÿ›ก๏ธ **Robust Error Handling**: Comprehensive error types and retry strategies - ๐Ÿ“Š **Rich Data Models**: Extensive type definitions for all API responses - ๐Ÿงช **Well Tested**: High test coverage with unit and integration tests - ๐Ÿ“š **Comprehensive Documentation**: Full API documentation with examples ## Table of Contents - [Installation](#installation) - [Quick Start](#quick-start) - [Configuration](#configuration) - [Authentication](#authentication) - [API Modules](#api-modules) - [Usage Examples](#usage-examples) - [Error Handling](#error-handling) - [Rate Limiting](#rate-limiting) - [Testing](#testing) - [Next.js Integration](#nextjs-integration) - [Contributing](#contributing) - [API Reference](#api-reference) - [License](#license) ## Installation ```bash npm install autotrader-connect-api ``` Or with yarn: ```bash yarn add autotrader-connect-api ``` ## Quick Start ```typescript import { initializeClient, getVehicle, searchVehicles } from 'autotrader-connect-api'; // Initialize the client const client = initializeClient({ apiKey: 'your-api-key', apiSecret: 'your-api-secret', baseURL: 'https://api.autotrader.co.uk', // optional }); // Search for vehicles const vehicles = await searchVehicles({ make: 'BMW', model: '3 Series', priceRange: { min: 15000, max: 30000 }, yearRange: { min: 2018 }, postcode: 'SW1A 1AA', radius: 50, }); console.log(`Found ${vehicles.data.length} vehicles`); // Get a specific vehicle const vehicle = await getVehicle('ABC123', 12345); console.log(`Vehicle: ${vehicle.make} ${vehicle.model} - ยฃ${vehicle.price}`); ``` ## ๐Ÿงช Sandbox Environment Support The package includes comprehensive sandbox support for testing and development. The API automatically detects your environment and switches between sandbox and production endpoints. ### Environment Detection - **Development**: `NODE_ENV=development` โ†’ Uses sandbox automatically - **Test**: `NODE_ENV=test` โ†’ Uses sandbox automatically - **Production**: `NODE_ENV=production` โ†’ Uses production API - **Manual Override**: `AT_USE_SANDBOX=true/false` โ†’ Explicit control ### Environment Variables ```bash # Production API AT_BASE_URL=https://api.autotrader.co.uk AT_API_KEY=your_production_key AT_API_SECRET=your_production_secret # Sandbox API AT_SANDBOX_BASE_URL=https://sandbox-api.autotrader.co.uk AT_SANDBOX_API_KEY=your_sandbox_key AT_SANDBOX_API_SECRET=your_sandbox_secret # Environment control NODE_ENV=development AT_USE_SANDBOX=true ``` ### Quick Setup Methods ```typescript import { quickSetup, setupSandbox, setupProduction } from 'autotrader-connect-api'; // 1. Automatic environment detection const client = quickSetup(); // Uses sandbox in development, production otherwise // 2. Force sandbox mode const sandboxClient = setupSandbox(); // Always uses sandbox // 3. Force production mode const prodClient = setupProduction(); // Always uses production // 4. Override environment detection const testClient = quickSetup({ forceSandbox: true // Force sandbox regardless of NODE_ENV }); ``` ### Explicit Configuration ```typescript import { initializeClient } from 'autotrader-connect-api'; // Sandbox configuration const sandboxClient = initializeClient({ apiKey: 'sandbox-key', apiSecret: 'sandbox-secret', baseURL: 'https://sandbox-api.autotrader.co.uk', useSandbox: true, debug: true // Helpful for development }); // Production configuration const prodClient = initializeClient({ apiKey: 'prod-key', apiSecret: 'prod-secret', baseURL: 'https://api.autotrader.co.uk', useSandbox: false, debug: false }); ``` ### Testing Best Practices ```typescript // In your test files import { setupSandbox } from 'autotrader-connect-api'; describe('Vehicle API Tests', () => { let client; beforeAll(() => { // Always use sandbox for tests client = setupSandbox({ debug: true // See all API calls in test output }); }); it('should search for vehicles', async () => { const results = await searchVehicles({ make: 'BMW' }); expect(results.data).toBeDefined(); }); }); ``` ### Development Workflow ```typescript // .env.development NODE_ENV=development AT_SANDBOX_API_KEY=your_dev_key AT_SANDBOX_API_SECRET=your_dev_secret AT_USE_SANDBOX=true AT_DEBUG=true // .env.production NODE_ENV=production AT_API_KEY=your_prod_key AT_API_SECRET=your_prod_secret AT_USE_SANDBOX=false AT_DEBUG=false ``` ### Sandbox Features โœ… Automatic environment detection โœ… Separate credentials for sandbox vs production โœ… Debug mode enabled by default in sandbox โœ… Same API interface as production โœ… Perfect for CI/CD testing pipelines โœ… No accidental production API calls during development ## ๐Ÿข Advertiser ID Management The package now includes comprehensive advertiser ID support for proper multi-tenant operations: ### Key Features โœ… **Consistent Advertiser Context**: Use `advertiserId` (number) throughout the API โœ… **Legacy Support**: Backward compatible with `dealerId` (string) โœ… **Advertiser-Scoped Clients**: Automatic advertiser context injection โœ… **Validation Utilities**: Verify advertiser IDs before API calls โœ… **Multi-Advertiser Support**: Manage multiple dealers in one application โœ… **Comprehensive Advertiser Management**: Full CRUD operations for advertiser data ### Quick Examples ```typescript import { getVehicle, searchVehicles, createAdvertiserClient, getCurrentAdvertiser } from 'autotrader-connect-api'; // Get vehicle with advertiser context const vehicle = await getVehicle('ABC123', 12345); console.log(`Vehicle from ${vehicle.advertiser.name}`); // Search with advertiser filtering const results = await searchVehicles({ make: 'BMW', advertiserId: [12345, 67890], // Multiple advertisers priceRange: { min: 15000, max: 30000 } }); // Create advertiser-scoped client const dealerClient = createAdvertiserClient(12345); // All requests now include advertiser context automatically // Get current advertiser information const advertiser = await getCurrentAdvertiser(); console.log(`Logged in as: ${advertiser.name} (ID: ${advertiser.id})`); ``` For comprehensive examples, see [`advertiser-examples.md`](./advertiser-examples.md). ## Configuration ### Environment Variables Create a `.env` file in your project root: ```bash # Required AT_API_KEY=your_autotrader_api_key AT_API_SECRET=your_autotrader_api_secret # Optional AT_BASE_URL=https://api.autotrader.co.uk AT_TIMEOUT=30000 AT_RATE_LIMIT_REQUESTS=100 AT_RATE_LIMIT_WINDOW=60000 AT_DEBUG=false ``` ### Programmatic Configuration ```typescript import { initializeClient } from 'autotrader-connect-api'; const client = initializeClient({ apiKey: process.env.AT_API_KEY!, apiSecret: process.env.AT_API_SECRET!, baseURL: 'https://api.autotrader.co.uk', timeout: 30000, maxRetries: 3, rateLimitRequests: 100, rateLimitWindow: 60000, debug: false, }); ``` ### Quick Setup (Environment-based) ```typescript import { quickSetup } from 'autotrader-connect-api'; // Uses environment variables automatically const client = quickSetup({ debug: process.env.NODE_ENV === 'development', timeout: 30000, }); ``` ## Authentication The package handles OAuth2 authentication automatically: ```typescript import { getToken, getAuthManager } from 'autotrader-connect-api'; // Get current token (automatically refreshes if needed) const token = await getToken(); // Manual auth management const authManager = getAuthManager(); const isAuthenticated = authManager.isAuthenticated(); const authState = authManager.getAuthState(); // Force token refresh await authManager.refreshToken(); // Clear cached token authManager.clearToken(); ``` ## API Modules ### Vehicles ```typescript import { getVehicle, getVehicleById, searchVehicles, getFeaturedVehicles, getSimilarVehicles, getVehicleSpecifications } from 'autotrader-connect-api'; // Get vehicle by registration and advertiser ID const vehicle = await getVehicle('ABC123', 12345); // Get vehicle by ID const vehicle = await getVehicleById('vehicle-id'); // Search vehicles with comprehensive filters const results = await searchVehicles({ make: ['BMW', 'Audi'], bodyType: ['Hatchback', 'Saloon'], fuelType: ['Petrol', 'Hybrid'], priceRange: { min: 15000, max: 40000 }, yearRange: { min: 2018 }, mileageRange: { max: 50000 }, postcode: 'M1 1AA', radius: 25, sortBy: 'price', sortOrder: 'asc', }); // Get featured vehicles const featured = await getFeaturedVehicles(10); // Get similar vehicles const similar = await getSimilarVehicles('vehicle-id', 5); // Get detailed specifications const specs = await getVehicleSpecifications('vehicle-id'); ``` ### Stock Management ```typescript import { searchStock, createStock, updateStock, publishStock, getStockStatistics } from 'autotrader-connect-api'; // Search stock with filters const stock = await searchStock({ status: ['Available', 'Reserved'], make: 'BMW', siteId: 'site-123', minDaysInStock: 7, sortBy: 'stockedDate', }); // Create new stock item const newStock = await createStock({ make: 'BMW', model: '3 Series', year: 2020, mileage: 25000, fuelType: 'Petrol', transmission: 'Automatic', bodyType: 'Saloon', doors: 4, seats: 5, colour: 'Black', retailPrice: 25000, description: 'Excellent condition BMW 3 Series', }); // Update stock item const updated = await updateStock('stock-id', { retailPrice: 24000, status: 'Available', }); // Publish stock to AutoTrader const result = await publishStock(['stock-id-1', 'stock-id-2']); // Get stock statistics const stats = await getStockStatistics({ siteId: 'site-123', dateFrom: '2024-01-01', }); ``` ### Search & Discovery ```typescript import { searchVehicles, quickSearch, saveSearch, compareVehicles, getPopularSearches } from 'autotrader-connect-api'; // Enhanced search with facets const searchResults = await searchVehicles({ make: 'BMW', priceRange: { min: 20000, max: 40000 }, includeFacets: true, includeMarketInsights: true, }); // Quick search for autocomplete const quick = await quickSearch({ query: 'BMW 3 Series', postcode: 'M1 1AA', maxPrice: 30000, limit: 5, }); // Save search for alerts const savedSearch = await saveSearch({ name: 'My BMW Search', filters: { make: 'BMW', priceRange: { max: 30000 } }, alertSettings: { enabled: true, frequency: 'Daily', email: 'user@example.com', }, }); // Compare multiple vehicles const comparison = await compareVehicles(['vehicle-1', 'vehicle-2', 'vehicle-3']); // Get popular searches const popular = await getPopularSearches('Make'); ``` ### Valuations ```typescript import { getValuation, getQuickValuation, getBatchValuations, getHistoricalValuation } from 'autotrader-connect-api'; // Get vehicle valuation const valuation = await getValuation({ make: 'BMW', model: '3 Series', year: 2020, mileage: 25000, condition: 'Good', postcode: 'M1 1AA', }); // Quick valuation by registration const quickVal = await getQuickValuation('ABC123', 25000, 'M1 1AA'); // Batch valuations const batchResults = await getBatchValuations([ { make: 'BMW', model: '3 Series', year: 2020, mileage: 25000 }, { make: 'Audi', model: 'A4', year: 2019, mileage: 30000 }, ]); // Historical valuation data const historical = await getHistoricalValuation({ make: 'BMW', model: '3 Series', year: 2020, mileage: 25000, }, '1y'); ``` ### Taxonomy ```typescript import { getVehicleMakes, getVehicleModels, getBodyTypes, searchTaxonomy } from 'autotrader-connect-api'; // Get all vehicle makes const makes = await getVehicleMakes(); // Get models for a make const models = await getVehicleModels('bmw'); // Get body types const bodyTypes = await getBodyTypes(); // Search taxonomy const results = await searchTaxonomy('BMW 3', 'all'); ``` ## Usage Examples ### Next.js API Route ```typescript // pages/api/vehicles/search.ts import type { NextApiRequest, NextApiResponse } from 'next'; import { searchVehicles } from 'autotrader-connect-api'; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { try { const { make, model, maxPrice } = req.query; const vehicles = await searchVehicles({ make: make as string, model: model as string, priceRange: maxPrice ? { max: Number(maxPrice) } : undefined, }); res.status(200).json(vehicles); } catch (error) { console.error('Search error:', error); res.status(500).json({ error: 'Failed to search vehicles' }); } } ``` ### React Component with SWR ```typescript // components/VehicleSearch.tsx import useSWR from 'swr'; import { VehicleSearchParams } from 'autotrader-connect-api'; const fetcher = (url: string) => fetch(url).then(r => r.json()); export function VehicleSearch({ filters }: { filters: VehicleSearchParams }) { const { data, error, isLoading } = useSWR( `/api/vehicles/search?${new URLSearchParams(filters)}`, fetcher ); if (error) return <div>Error loading vehicles</div>; if (isLoading) return <div>Loading...</div>; return ( <div> {data?.data?.map((vehicle: any) => ( <div key={vehicle.id}> <h3>{vehicle.make} {vehicle.model}</h3> <p>ยฃ{vehicle.price.toLocaleString()}</p> </div> ))} </div> ); } ``` ### Express.js Server ```typescript import express from 'express'; import { quickSetup, searchVehicles } from 'autotrader-connect-api'; const app = express(); const client = quickSetup(); app.get('/api/vehicles', async (req, res) => { try { const vehicles = await searchVehicles(req.query); res.json(vehicles); } catch (error) { res.status(500).json({ error: error.message }); } }); app.listen(3000); ``` ## Error Handling The package provides comprehensive error handling: ```typescript import { searchVehicles } from 'autotrader-connect-api'; try { const vehicles = await searchVehicles({ make: 'BMW' }); } catch (error) { if (error.status === 401) { console.error('Authentication failed'); } else if (error.status === 429) { console.error('Rate limit exceeded'); } else if (error.status >= 500) { console.error('Server error'); } else { console.error('Request failed:', error.message); } } ``` ### Health Check ```typescript import { healthCheck } from 'autotrader-connect-api'; const health = await healthCheck(); console.log('API Health:', health); // { // status: 'healthy', // timestamp: '2024-01-01T12:00:00Z', // version: '1.0.0', // auth: true, // latency: 145 // } ``` ## Rate Limiting The package includes built-in rate limiting: ```typescript import { getClient } from 'autotrader-connect-api'; const client = getClient(); // Check rate limit status const status = client.getRateLimitStatus(); console.log('Rate limit status:', status); // { // reservoir: 95, // requests remaining // running: 2, // requests in progress // queued: 0 // requests queued // } ``` ## Testing Run the test suite: ```bash # Run all tests npm test # Run tests in watch mode npm run test:watch # Run tests with coverage npm run test:coverage # Run linting npm run lint # Fix linting issues npm run lint:fix ``` ### Writing Tests ```typescript import { getVehicle } from 'autotrader-connect-api'; // Mock the client for testing jest.mock('autotrader-connect-api', () => ({ getVehicle: jest.fn(), })); test('should fetch vehicle data', async () => { const mockVehicle = { id: '123', make: 'BMW', model: '3 Series' }; (getVehicle as jest.Mock).mockResolvedValue(mockVehicle); const result = await getVehicle('ABC123', 12345); expect(result).toEqual(mockVehicle); }); ``` ## Next.js Integration ### App Router (Recommended) ```typescript // app/api/vehicles/route.ts import { searchVehicles } from 'autotrader-connect-api'; export async function GET(request: Request) { const { searchParams } = new URL(request.url); try { const vehicles = await searchVehicles({ make: searchParams.get('make') || undefined, model: searchParams.get('model') || undefined, }); return Response.json(vehicles); } catch (error) { return Response.json( { error: 'Failed to search vehicles' }, { status: 500 } ); } } ``` ### Server Component ```typescript // app/vehicles/page.tsx import { searchVehicles } from 'autotrader-connect-api'; export default async function VehiclesPage() { const vehicles = await searchVehicles({ make: 'BMW' }); return ( <div> <h1>BMW Vehicles</h1> {vehicles.data.map(vehicle => ( <div key={vehicle.id}> <h3>{vehicle.make} {vehicle.model}</h3> <p>ยฃ{vehicle.price.toLocaleString()}</p> </div> ))} </div> ); } ``` ## API Reference For complete API documentation, see the [TypeDoc generated documentation](./docs). ### Core Types ```typescript // Import types for use in your application import type { Vehicle, VehicleSearchParams, VehicleResponse, StockItem, SearchResponse, ValuationResponse, ApiResponse, PaginatedResponse, } from 'autotrader-connect-api'; ``` ## Building and Publishing ### Development ```bash # Install dependencies npm install # Run in development mode npm run dev # Build the package npm run build # Generate documentation npm run docs ``` ### Publishing ```bash # Version bump (patch, minor, or major) npm version patch # Build and test before publishing npm run prepublishOnly # Publish to NPM npm publish # Or publish with tag npm publish --tag beta ``` ### Automated Publishing The package includes GitHub Actions for automated publishing: 1. Create a release tag: `git tag v1.0.1` 2. Push the tag: `git push origin v1.0.1` 3. GitHub Actions will automatically build, test, and publish ## Contributing 1. Fork the repository 2. Create a feature branch: `git checkout -b feature/your-feature` 3. Make your changes and add tests 4. Ensure tests pass: `npm test` 5. Commit your changes: `git commit -am 'Add your feature'` 6. Push to the branch: `git push origin feature/your-feature` 7. Submit a pull request ### Development Guidelines - Follow the existing code style - Add tests for new features - Update documentation as needed - Ensure all tests pass - Follow semantic versioning ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## Support - ๐Ÿ“ง Email: support@your-org.com - ๐Ÿ’ฌ Issues: [GitHub Issues](https://github.com/your-org/autotrader-connect/issues) - ๐Ÿ“– Documentation: [API Docs](./docs) ## Changelog See [CHANGELOG.md](CHANGELOG.md) for release history. --- Made with โค๏ธ by [Your Organization](https://your-org.com)