Very minimal MVP
This commit is contained in:
@@ -7,11 +7,21 @@ import axios from 'axios';
|
||||
import { env } from '../../../../core/config/environment';
|
||||
import { logger } from '../../../../core/logging/logger';
|
||||
import { cacheService } from '../../../../core/config/redis';
|
||||
import { VPICResponse, VPICDecodeResult } from './vpic.types';
|
||||
import {
|
||||
VPICResponse,
|
||||
VPICDecodeResult,
|
||||
VPICMake,
|
||||
VPICModel,
|
||||
VPICTransmission,
|
||||
VPICEngine,
|
||||
VPICTrim,
|
||||
DropdownDataResponse
|
||||
} from './vpic.types';
|
||||
|
||||
export class VPICClient {
|
||||
private readonly baseURL = env.VPIC_API_URL;
|
||||
private readonly cacheTTL = 30 * 24 * 60 * 60; // 30 days in seconds
|
||||
private readonly dropdownCacheTTL = 7 * 24 * 60 * 60; // 7 days for dropdown data
|
||||
|
||||
async decodeVIN(vin: string): Promise<VPICDecodeResult | null> {
|
||||
const cacheKey = `vpic:vin:${vin}`;
|
||||
@@ -73,6 +83,96 @@ export class VPICClient {
|
||||
rawData: response.Results,
|
||||
};
|
||||
}
|
||||
|
||||
async getAllMakes(): Promise<VPICMake[]> {
|
||||
const cacheKey = 'vpic:makes';
|
||||
|
||||
try {
|
||||
const cached = await cacheService.get<VPICMake[]>(cacheKey);
|
||||
if (cached) {
|
||||
logger.debug('Makes cache hit');
|
||||
return cached;
|
||||
}
|
||||
|
||||
logger.info('Calling vPIC API for makes');
|
||||
const response = await axios.get<{ Count: number; Message: string; Results: VPICMake[] }>(
|
||||
`${this.baseURL}/GetAllMakes?format=json`
|
||||
);
|
||||
|
||||
const makes = response.data.Results || [];
|
||||
await cacheService.set(cacheKey, makes, this.dropdownCacheTTL);
|
||||
|
||||
return makes;
|
||||
} catch (error) {
|
||||
logger.error('Get makes failed', { error });
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async getModelsForMake(make: string): Promise<VPICModel[]> {
|
||||
const cacheKey = `vpic:models:${make}`;
|
||||
|
||||
try {
|
||||
const cached = await cacheService.get<VPICModel[]>(cacheKey);
|
||||
if (cached) {
|
||||
logger.debug('Models cache hit', { make });
|
||||
return cached;
|
||||
}
|
||||
|
||||
logger.info('Calling vPIC API for models', { make });
|
||||
const response = await axios.get<{ Count: number; Message: string; Results: VPICModel[] }>(
|
||||
`${this.baseURL}/GetModelsForMake/${encodeURIComponent(make)}?format=json`
|
||||
);
|
||||
|
||||
const models = response.data.Results || [];
|
||||
await cacheService.set(cacheKey, models, this.dropdownCacheTTL);
|
||||
|
||||
return models;
|
||||
} catch (error) {
|
||||
logger.error('Get models failed', { make, error });
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async getTransmissionTypes(): Promise<VPICTransmission[]> {
|
||||
return this.getVariableValues('Transmission Style', 'transmissions');
|
||||
}
|
||||
|
||||
async getEngineConfigurations(): Promise<VPICEngine[]> {
|
||||
return this.getVariableValues('Engine Configuration', 'engines');
|
||||
}
|
||||
|
||||
async getTrimLevels(): Promise<VPICTrim[]> {
|
||||
return this.getVariableValues('Trim', 'trims');
|
||||
}
|
||||
|
||||
private async getVariableValues(
|
||||
variable: string,
|
||||
cachePrefix: string
|
||||
): Promise<VPICTransmission[] | VPICEngine[] | VPICTrim[]> {
|
||||
const cacheKey = `vpic:${cachePrefix}`;
|
||||
|
||||
try {
|
||||
const cached = await cacheService.get<VPICTransmission[]>(cacheKey);
|
||||
if (cached) {
|
||||
logger.debug('Variable values cache hit', { variable });
|
||||
return cached;
|
||||
}
|
||||
|
||||
logger.info('Calling vPIC API for variable values', { variable });
|
||||
const response = await axios.get<DropdownDataResponse>(
|
||||
`${this.baseURL}/GetVehicleVariableValuesList/${encodeURIComponent(variable)}?format=json`
|
||||
);
|
||||
|
||||
const values = response.data.Results || [];
|
||||
await cacheService.set(cacheKey, values, this.dropdownCacheTTL);
|
||||
|
||||
return values;
|
||||
} catch (error) {
|
||||
logger.error('Get variable values failed', { variable, error });
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const vpicClient = new VPICClient();
|
||||
@@ -23,4 +23,32 @@ export interface VPICDecodeResult {
|
||||
engineType?: string;
|
||||
bodyType?: string;
|
||||
rawData: VPICResult[];
|
||||
}
|
||||
|
||||
export interface VPICMake {
|
||||
Make_ID: number;
|
||||
Make_Name: string;
|
||||
}
|
||||
|
||||
export interface VPICModel {
|
||||
Make_ID: number;
|
||||
Make_Name: string;
|
||||
Model_ID: number;
|
||||
Model_Name: string;
|
||||
}
|
||||
|
||||
export interface VPICDropdownItem {
|
||||
Id: number;
|
||||
Name: string;
|
||||
}
|
||||
|
||||
export interface VPICTransmission extends VPICDropdownItem {}
|
||||
export interface VPICEngine extends VPICDropdownItem {}
|
||||
export interface VPICTrim extends VPICDropdownItem {}
|
||||
|
||||
export interface DropdownDataResponse {
|
||||
Count: number;
|
||||
Message: string;
|
||||
SearchCriteria: string;
|
||||
Results: VPICDropdownItem[];
|
||||
}
|
||||
Reference in New Issue
Block a user