Very minimal MVP

This commit is contained in:
Eric Gullickson
2025-08-23 09:54:22 -05:00
parent d60c3ec00e
commit 6683f1eeff
12 changed files with 661 additions and 13 deletions

View File

@@ -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();

View File

@@ -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[];
}