Skip to main content
Glama
reference.js13 kB
const { logger } = require('../utils/logger'); class ReferenceAPI { constructor(apiClient) { this.client = apiClient; } async getMakes(searchTerm = null) { try { const result = await this.client.get('/refdata/CAR/makes'); let makes = result.values || []; if (searchTerm) { const search = searchTerm.toLowerCase(); makes = makes.filter(make => make.name.toLowerCase().includes(search) ); } return { count: makes.length, makes: makes.map(make => ({ id: make.id, code: make.name, // Use name as code since API doesn't provide code name: make.name })) }; } catch (error) { logger.error('Failed to get makes', { error: error.message, searchTerm }); throw error; } } async getModels(makeCode, searchTerm = null) { try { const result = await this.client.get(`/refdata/CAR/makes/${makeCode}/models`); let models = result.values || []; if (searchTerm) { const search = searchTerm.toLowerCase(); models = models.filter(model => model.name.toLowerCase().includes(search) ); } return { make: makeCode, count: models.length, models: models.map(model => ({ id: model.id, code: model.name, // Use name as code since API doesn't provide code name: model.name })) }; } catch (error) { logger.error('Failed to get models', { error: error.message, makeCode, searchTerm }); throw error; } } async getTrims(makeCode, modelCode, searchTerm = null) { try { const result = await this.client.get(`/refdata/CAR/makes/${makeCode}/models/${modelCode}/variants`); let trims = result.values || []; if (searchTerm) { const search = searchTerm.toLowerCase(); trims = trims.filter(trim => trim.name.toLowerCase().includes(search) ); } return { make: makeCode, model: modelCode, count: trims.length, trims: trims.map(trim => ({ id: trim.id, source: trim.source, code: trim.code, name: trim.name, engineSize: trim.engineSize, power: trim.power, fuelType: trim.fuelType, make: trim.make })) }; } catch (error) { logger.error('Failed to get trims', { error: error.message, makeCode, modelCode, searchTerm }); throw error; } } async compileVehicleByVersion(companyId, providerCode, vehicleClass, provider = null) { try { const params = { companyId, providerCode, vehicleClass }; if (provider) { params.provider = provider; } const result = await this.client.get('/vehicle/compileByTrim', params); return result; } catch (error) { logger.error('Failed to compile vehicle by version', { error: error.message, companyId, providerCode, vehicleClass, provider }); throw error; } } async getFuelTypes() { try { const result = await this.client.get('/refdata/CAR/fuels'); return { count: result.values.length, fuelTypes: result.values.map(fuel => ({ code: fuel.code, name: fuel.name })) }; } catch (error) { logger.error('Failed to get fuel types', { error: error.message }); throw error; } } async getTransmissionTypes() { try { // For now, return static data since endpoint doesn't exist const transmissions = [ { code: 'MANUAL', name: 'Manual' }, { code: 'AUTOMATIC', name: 'Automatic' }, { code: 'SEMI_AUTOMATIC', name: 'Semi-automatic' }, { code: 'CVT', name: 'Continuously Variable Transmission' } ]; return { count: transmissions.length, transmissionTypes: transmissions }; } catch (error) { logger.error('Failed to get transmission types', { error: error.message }); throw error; } } // Vehicle navigation functions async getVehicleMakes(country, vehicleClass = 'car') { try { const params = { vehicleClass }; const result = await this.client.get('/vehicle/makes', params); // The API returns an array directly, not an object with 'makes' property const makes = Array.isArray(result) ? result : []; return { country, vehicleClass, count: makes.length, makes: makes.map(make => ({ id: make.id, name: make.name, code: make.code || make.name })) }; } catch (error) { logger.error('Failed to get vehicle makes', { error: error.message, country, vehicleClass }); throw error; } } async getVehicleModels(country, vehicleClass, make) { try { const params = { vehicleClass: vehicleClass, make: make }; const result = await this.client.get('/vehicle/models', params); // The API likely returns an array directly const models = Array.isArray(result) ? result : (result.models || []); return { country, vehicleClass, make, count: models.length, models: models.map(model => ({ id: model.id, name: model.name, make: model.make, bodyType: model.bodyType, fuelType: model.fuelType, manufactureDate: model.manufactureDate })) }; } catch (error) { logger.error('Failed to get vehicle models', { error: error.message, country, vehicleClass, make }); throw error; } } async getVehicleBodies(country, vehicleClass = 'car') { try { const params = { vehicleClass }; const result = await this.client.get('/vehicle/bodies', params); // The API likely returns an array directly const bodies = Array.isArray(result) ? result : (result.content || []); return { country, vehicleClass, count: bodies.length, bodies: bodies.map(body => ({ id: body.id, name: body.name, key: body.key, code: body.code })) }; } catch (error) { logger.error('Failed to get vehicle bodies', { error: error.message, country, vehicleClass }); throw error; } } async getVehicleFuels(country, vehicleClass = 'car') { try { const params = { vehicleClass }; const result = await this.client.get('/vehicle/fuels', params); // The API likely returns an array directly const fuels = Array.isArray(result) ? result : (result.content || []); return { country, vehicleClass, count: fuels.length, fuels: fuels.map(fuel => ({ id: fuel.id, name: fuel.name, key: fuel.key, code: fuel.code })) }; } catch (error) { logger.error('Failed to get vehicle fuels', { error: error.message, country, vehicleClass }); throw error; } } async getVehicleTrims(country, modelId, bodyType = null, fuelType = null, manufactureDate = null) { try { const pageSize = 50; let page = 0; let allTrims = []; let hasMore = true; // Implement pagination to fetch all trims while (hasMore) { const params = { modelId, page, size: pageSize }; if (bodyType) params.bodyType = bodyType; if (fuelType) params.fuelType = fuelType; if (manufactureDate) params.manufactureDate = manufactureDate; const result = await this.client.get('/vehicle/trims', params); // The API returns a paginated response with content array const trims = result.content || []; allTrims.push(...trims); // Check if there are more pages // Assuming the API returns totalPages or we check if current page has full content hasMore = trims.length === pageSize && page < 10; // Safety limit of 10 pages (500 trims) page++; } return { country, modelId, filters: { bodyType, fuelType, manufactureDate }, count: allTrims.length, trims: allTrims.map(trim => ({ id: trim.id, name: trim.name, source: trim.source, make: trim.make, model: trim.model, bodyType: trim.bodyType, fuelType: trim.fuelType, engineSize: trim.displacement, powerKw: trim.powerKw, powerHp: trim.powerHp, transmission: trim.gearType, listPrice: trim.listPrice, beginSelling: trim.beginSelling, endSelling: trim.endSelling })) }; } catch (error) { logger.error('Failed to get vehicle trims', { error: error.message, country, modelId, bodyType, fuelType, manufactureDate }); throw error; } } async findModelsByMake(country, makeName, vehicleClass = 'car') { try { // First get all models for the vehicle class and make const modelsResult = await this.getVehicleModels(country, vehicleClass, makeName); if (modelsResult.count === 0) { // Try fuzzy matching - get all makes first const makesResult = await this.getVehicleMakes(country); const fuzzyMake = makesResult.makes.find(make => make.name.toLowerCase().includes(makeName.toLowerCase()) || makeName.toLowerCase().includes(make.name.toLowerCase()) ); if (fuzzyMake) { logger.info(`Fuzzy matched "${makeName}" to "${fuzzyMake.name}"`); return await this.getVehicleModels(country, vehicleClass, fuzzyMake.name); } } return modelsResult; } catch (error) { logger.error('Failed to find models by make', { error: error.message, country, makeName, vehicleClass }); throw error; } } async searchAll(query, type = 'all', limit = 20) { try { const results = { query, type, results: { makes: [], models: [], trims: [] } }; const search = query.toLowerCase(); // Search makes if (type === 'all' || type === 'makes') { const makesResult = await this.getMakes(query); results.results.makes = makesResult.makes.slice(0, limit); } // Search models for matching makes if (type === 'all' || type === 'models' || type === 'trims') { const allMakes = await this.getMakes(); const relevantMakes = allMakes.makes.filter(make => make.name.toLowerCase().includes(search) ).slice(0, 5); // Limit to avoid too many API calls for (const make of relevantMakes) { try { if (type === 'all' || type === 'models') { const modelsResult = await this.getModels(make.code, query); results.results.models.push(...modelsResult.models.map(model => ({ ...model, make: make.name }))); } if (type === 'all' || type === 'trims') { const modelsResult = await this.getModels(make.code); const relevantModels = modelsResult.models.filter(model => model.name.toLowerCase().includes(search) ).slice(0, 3); for (const model of relevantModels) { try { const trimsResult = await this.getTrims(make.code, model.code, query); results.results.trims.push(...trimsResult.trims.map(trim => ({ ...trim, make: make.name, model: model.name }))); } catch (trimError) { // Continue if specific trim lookup fails logger.debug('Trim lookup failed', { make: make.code, model: model.code }); } } } } catch (modelError) { // Continue if specific model lookup fails logger.debug('Model lookup failed', { make: make.code }); } } } // Apply limit to final results results.results.makes = results.results.makes.slice(0, limit); results.results.models = results.results.models.slice(0, limit); results.results.trims = results.results.trims.slice(0, limit); results.totalFound = results.results.makes.length + results.results.models.length + results.results.trims.length; return results; } catch (error) { logger.error('Failed to search reference data', { error: error.message, query, type }); throw error; } } } module.exports = { ReferenceAPI };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/loukach/stockspark-mcp-poc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server