UNPKG

gophr-bridge-sdk

Version:

A simple SDK for interacting with the Gophr Bridge API

386 lines (347 loc) • 14.2 kB
const axios = require('axios'); /** * Gophr Bridge SDK * A simple SDK for interacting with the Gophr Bridge API */ class GophrBridge { /** * Initialize the Gophr Bridge SDK * @param {Object} config - Configuration object * @param {string} config.clientId - Gophr client ID * @param {string} config.clientSecret - Gophr client secret * @param {string} config.host - Gophr Bridge API host URL */ constructor(config) { if (!config.clientId || !config.clientSecret || !config.host) { throw new Error('Missing required configuration: clientId, clientSecret, and host are required'); } this.clientId = config.clientId; this.clientSecret = config.clientSecret; this.host = config.host; // Create axios instance with default headers this.client = axios.create({ baseURL: this.host, headers: { 'client-id': this.clientId, 'client-secret': this.clientSecret, 'Content-Type': 'application/json' } }); // Add response interceptor for consistent error handling this.client.interceptors.response.use( response => response, error => this._handleError(error) ); } /** * Get a quote for delivery * @param {Object} quoteData - Quote request data * @param {string} quoteData.first_name - Customer first name * @param {string} quoteData.last_name - Customer last name * @param {string} quoteData.phone - Customer phone number * @param {string} quoteData.email - Customer email (optional) * @param {string} quoteData.address_1 - Delivery address line 1 * @param {string} quoteData.address_2 - Delivery address line 2 (optional) * @param {string} quoteData.city - Delivery city * @param {string} quoteData.state - Delivery state * @param {string} quoteData.zip - Delivery ZIP code * @param {string} quoteData.country - Delivery country (default: 'US') * @param {string} quoteData.pick_up_instructions - Pickup instructions (optional) * @param {string} quoteData.drop_off_instructions - Drop-off instructions (optional) * @param {string|null} quoteData.scheduled_for - Scheduled delivery date (YYYY-MM-DD format, null for ASAP) * @param {Array} quoteData.items - Array of items to be delivered * @returns {Promise<Object>} Quote response with standard and expedited options */ async getQuote(quoteData) { try { const response = await this.client.post('/quote', quoteData); return response.data; } catch (error) { throw error; } } /** * Create a shipment using a quote ID * @param {Object} shipmentData - Shipment creation data * @param {string} shipmentData.quote_id - Quote ID from previous quote request * @param {string} shipmentData.drop_off_instructions - Drop-off instructions (optional) * @returns {Promise<Object>} Shipment creation response */ async createShipment(shipmentData) { try { const response = await this.client.post('/create', shipmentData); return response.data; } catch (error) { throw error; } } /** * Helper method to build quote data with defaults * @param {Object} customerInfo - Customer information * @param {Object} addressInfo - Address information * @param {Array} items - Items array * @param {Object} options - Additional options * @returns {Object} Formatted quote data */ buildQuoteData(customerInfo, addressInfo, items, options = {}) { return { first_name: customerInfo.firstName, last_name: customerInfo.lastName, phone: customerInfo.phone, email: customerInfo.email || '', address_1: addressInfo.address1, address_2: addressInfo.address2 || '', city: addressInfo.city, state: addressInfo.state, zip: addressInfo.zip, country: addressInfo.country || 'US', pick_up_instructions: options.pickupInstructions || '', drop_off_instructions: options.dropoffInstructions || '', scheduled_for: options.scheduledFor || null, items: items }; } /** * Extract standard quote ID from quote response * @param {Object} quoteResponse - Response from getQuote() * @returns {string|null} Standard quote ID or null if not found */ getStandardQuoteId(quoteResponse) { return quoteResponse?.payload?.standard_quote?.quote_id || null; } /** * Extract expedited quote ID from quote response * @param {Object} quoteResponse - Response from getQuote() * @returns {string|null} Expedited quote ID or null if not found */ getExpeditedQuoteId(quoteResponse) { return quoteResponse?.payload?.expedited_quote?.quote_id || null; } /** * Extract standard quote fee from quote response * @param {Object} quoteResponse - Response from getQuote() * @returns {number|null} Standard quote fee or null if not found */ getStandardQuoteFee(quoteResponse) { return quoteResponse?.payload?.standard_quote?.fee || null; } /** * Extract expedited quote fee from quote response * @param {Object} quoteResponse - Response from getQuote() * @returns {number|null} Expedited quote fee or null if not found */ getExpeditedQuoteFee(quoteResponse) { return quoteResponse?.payload?.expedited_quote?.fee || null; } /** * Extract delivery ID from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {string|number|null} Delivery ID or null if not found */ getDeliveryId(shipmentResponse) { return shipmentResponse?.payload?.delivery_id || null; } /** * Extract delivery status from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {string|null} Delivery status or null if not found */ getDeliveryStatus(shipmentResponse) { return shipmentResponse?.payload?.delivery_status || null; } /** * Extract shipping fee from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {number|null} Shipping fee or null if not found */ getShippingFee(shipmentResponse) { return shipmentResponse?.payload?.shipping_fee || null; } /** * Extract vehicle type from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {string|null} Vehicle type or null if not found */ getVehicleType(shipmentResponse) { return shipmentResponse?.payload?.vehicle_type || null; } /** * Extract distance from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {number|null} Distance in miles or null if not found */ getDistance(shipmentResponse) { return shipmentResponse?.payload?.distance || null; } /** * Extract full payload from quote response * @param {Object} quoteResponse - Response from getQuote() * @returns {Object|null} Quote payload or null if not found */ getQuotePayload(quoteResponse) { return quoteResponse?.payload || null; } /** * Extract full payload from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {Object|null} Shipment payload or null if not found */ getShipmentPayload(shipmentResponse) { return shipmentResponse?.payload || null; } /** * Extract pickup address from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {Object|null} Pickup address object or null if not found */ getPickupAddress(shipmentResponse) { return shipmentResponse?.payload?.pick_up || null; } /** * Extract drop-off address from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {Object|null} Drop-off address object or null if not found */ getDropoffAddress(shipmentResponse) { return shipmentResponse?.payload?.drop_off || null; } /** * Extract items array from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {Array|null} Items array or null if not found */ getShipmentItems(shipmentResponse) { return shipmentResponse?.payload?.items || null; } /** * Extract weight from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {number|null} Weight or null if not found */ getShipmentWeight(shipmentResponse) { return shipmentResponse?.payload?.weight || null; } /** * Check if shipment is expedited * @param {Object} shipmentResponse - Response from createShipment() * @returns {boolean|null} True if expedited, false if standard, null if not found */ isExpedited(shipmentResponse) { return shipmentResponse?.payload?.is_expedited ?? null; } /** * Extract scheduled_for date from shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {string|null} Scheduled date or null if ASAP/not found */ getScheduledFor(shipmentResponse) { return shipmentResponse?.payload?.scheduled_for || null; } /** * Check if response is successful * @param {Object} response - API response object * @returns {boolean} True if response status is 'successful' */ isSuccessful(response) { return response?.status === 'successful' && response?.status_code === 200; } /** * Get a formatted summary of quote response * @param {Object} quoteResponse - Response from getQuote() * @returns {Object} Formatted quote summary */ getQuoteSummary(quoteResponse) { if (!this.isSuccessful(quoteResponse)) { return { error: 'Quote request was not successful' }; } return { success: true, standard: { quoteId: this.getStandardQuoteId(quoteResponse), fee: this.getStandardQuoteFee(quoteResponse) }, expedited: { quoteId: this.getExpeditedQuoteId(quoteResponse), fee: this.getExpeditedQuoteFee(quoteResponse) } }; } /** * Get a formatted summary of shipment response * @param {Object} shipmentResponse - Response from createShipment() * @returns {Object} Formatted shipment summary */ getShipmentSummary(shipmentResponse) { if (!this.isSuccessful(shipmentResponse)) { return { error: 'Shipment creation was not successful' }; } return { success: true, deliveryId: this.getDeliveryId(shipmentResponse), status: this.getDeliveryStatus(shipmentResponse), fee: this.getShippingFee(shipmentResponse), vehicleType: this.getVehicleType(shipmentResponse), distance: this.getDistance(shipmentResponse) }; } /** * Enhanced error handling for API responses * @private */ _handleError(error) { const enhancedError = new Error(); if (error.response) { // Server responded with error status enhancedError.message = `API Error (${error.response.status}): ${error.response.statusText}`; enhancedError.status = error.response.status; enhancedError.statusText = error.response.statusText; enhancedError.data = error.response.data; enhancedError.url = error.config?.url; // Add more specific error details if (error.response.data) { if (typeof error.response.data === 'object') { enhancedError.details = error.response.data; if (error.response.data.message) { enhancedError.message += ` - ${error.response.data.message}`; } } } } else if (error.request) { // Network error enhancedError.message = `Network Error: Unable to connect to ${this.host}`; enhancedError.code = error.code; enhancedError.isNetworkError = true; } else { // Request setup error enhancedError.message = `Request Error: ${error.message}`; enhancedError.isRequestError = true; } enhancedError.originalError = error; throw enhancedError; } /** * Utility method to log errors in a formatted way * @param {Error} error - Error object to log */ static logError(error) { console.error('\nšŸ”“ Gophr Bridge API Error:'); console.error('================================'); if (error.status) { console.error(`šŸ“” Status: ${error.status} (${error.statusText})`); console.error(`🌐 URL: ${error.url || 'Unknown'}`); if (error.details) { console.error(`šŸ“‹ Details:`); console.error(JSON.stringify(error.details, null, 2)); } } else if (error.isNetworkError) { console.error(`🌐 Network Error: ${error.message}`); if (error.code) { console.error(`šŸ“‹ Code: ${error.code}`); } } else { console.error(`āš™ļø Error: ${error.message}`); } console.error('================================\n'); } } module.exports = GophrBridge;