/** * Landvex JavaScript SDK * Official JavaScript client for Landvex API */ class LandvexClient { /** * Create Landvex client * @param {string} apiKey - API authentication key * @param {string} baseUrl - API base URL */ constructor(apiKey, baseUrl = 'https://api.landvex.com/v1') { this.apiKey = apiKey; this.baseUrl = baseUrl.replace(/\/$/, ''); } /** * Make API request * @private */ async _request(method, endpoint, options = {}) { const url = `${this.baseUrl}/${endpoint.replace(/^\//, '')}`; const config = { method, headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', ...options.headers, }, ...options, }; if (options.body && typeof options.body === 'object') { config.body = JSON.stringify(options.body); } const response = await fetch(url, config); if (!response.ok) { const error = await response.json().catch(() => ({})); throw new Error(error.message || `HTTP ${response.status}: ${response.statusText}`); } return response.json(); } // === Observations === /** * List observations * @param {Object} params - Query parameters * @returns {Promise} Observations */ async listObservations(params = {}) { const queryParams = new URLSearchParams(); Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null) { queryParams.append(key, value); } }); const data = await this._request('GET', `/observations?${queryParams}`); return data.observations || []; } /** * Get single observation * @param {string} id - Observation ID * @returns {Promise} Observation */ async getObservation(id) { const data = await this._request('GET', `/observations/${id}`); return data.observation; } /** * Create observation * @param {Object} observation - Observation data * @returns {Promise} Created observation */ async createObservation(observation) { return this._request('POST', '/observations', { body: observation }); } // === Missions === /** * List missions * @param {Object} params - Query parameters * @returns {Promise} Missions */ async listMissions(params = {}) { const queryParams = new URLSearchParams(params); const data = await this._request('GET', `/missions?${queryParams}`); return data.missions || []; } /** * Accept mission * @param {string} id - Mission ID * @returns {Promise} Result */ async acceptMission(id) { return this._request('POST', `/missions/${id}/accept`); } // === Indexes === /** * Get RGI score * @param {number} lat - Latitude * @param {number} lng - Longitude * @returns {Promise} RGI data */ async getRGI(lat, lng) { return this._request('GET', `/indexes/rgi?lat=${lat}&lng=${lng}`); } /** * Get UMI score * @param {number} lat - Latitude * @param {number} lng - Longitude * @returns {Promise} UMI data */ async getUMI(lat, lng) { return this._request('GET', `/indexes/umi?lat=${lat}&lng=${lng}`); } // === Visual Geolocation === /** * Analyze image * @param {string} imagePath - Path to image * @param {string} imageId - Optional image ID * @returns {Promise} Analysis result */ async analyzeImage(imagePath, imageId) { return this._request('POST', '/visual-geolocation/analyze', { body: { image_path: imagePath, image_id: imageId }, }); } /** * Batch analyze images * @param {Array} images - Array of image objects * @returns {Promise} Batch results */ async batchAnalyze(images) { return this._request('POST', '/visual-geolocation/batch', { body: { images }, }); } // === Decisions === /** * Get recommendations * @param {string} stakeholder - Stakeholder type * @param {number} lat - Latitude * @param {number} lng - Longitude * @returns {Promise} Recommendations */ async getRecommendations(stakeholder, lat, lng) { return this._request('POST', '/decisions/recommend', { body: { stakeholder, lat, lng }, }); } // === Stats === /** * Get dashboard stats * @returns {Promise} Statistics */ async getStats() { return this._request('GET', '/stats'); } /** * Get earnings data * @returns {Promise} Earnings */ async getEarnings() { return this._request('GET', '/stats/earnings'); } // === Health === /** * Check API health * @returns {Promise} Health status */ async healthCheck() { return this._request('GET', '/health'); } } // Export for different module systems if (typeof module !== 'undefined' && module.exports) { module.exports = { LandvexClient }; } if (typeof window !== 'undefined') { window.LandvexClient = LandvexClient; }