const express = require('express'); const router = express.Router(); const shippingService = require('../services/shippingService.js'); const config = require('../config'); module.exports = (pool, query, authMiddleware) => { // Apply authentication middleware to all routes router.use(authMiddleware); /** * Get shipping rates * POST /api/shipping/rates * * Request Body: * { * address: { * name: string, * street: string, * city: string, * state: string, * zip: string, * country: string, * email: string * }, * parcel: { * length: number, * width: number, * height: number, * weight: number, * order_total: number * }, * items: [{ id, quantity, weight_grams }] // Optional cart items for weight calculation * } */ router.post('/rates', async (req, res, next) => { try { const { address, parcel, items } = req.body; // Shipping must be enabled if (!config.shipping.enabled) { return res.status(400).json({ error: true, message: 'Shipping is currently disabled' }); } // Validate required fields if (!address || !parcel) { return res.status(400).json({ error: true, message: 'Address and parcel information are required' }); } // If address is a string, parse it const parsedAddress = typeof address === 'string' ? shippingService.parseAddressString(address) : address; // Calculate total weight if items are provided if (items && items.length > 0) { parcel.weight = shippingService.calculateTotalWeight(items); } // Get shipping rates const rates = await shippingService.getShippingRates( null, // Use default from config parsedAddress, { ...parcel, order_total: parcel.order_total || 0 } ); res.json({ success: true, rates }); } catch (error) { console.error('Error getting shipping rates:', error); next(error); } }); /** * Validate shipping address * POST /api/shipping/validate-address * * Request Body: * { * address: { * name: string, * street: string, * city: string, * state: string, * zip: string, * country: string, * email: string * } * } */ router.post('/validate-address', async (req, res, next) => { try { const { address } = req.body; // Shipping must be enabled if (!config.shipping.enabled) { return res.status(400).json({ error: true, message: 'Shipping is currently disabled' }); } // Validate required fields if (!address) { return res.status(400).json({ error: true, message: 'Address information is required' }); } // If EasyPost is not enabled, just perform basic validation if (!config.shipping.easypostEnabled || !config.shipping.easypostApiKey) { const isValid = validateAddressFormat(address); return res.json({ success: true, valid: isValid, original_address: address, verified_address: address }); } // If address is a string, parse it const parsedAddress = typeof address === 'string' ? shippingService.parseAddressString(address) : address; // TODO: Implement EasyPost address verification // This would require making a call to EasyPost's API // For now, we'll return the original address res.json({ success: true, valid: true, original_address: parsedAddress, verified_address: parsedAddress }); } catch (error) { console.error('Error validating address:', error); next(error); } }); return router; }; /** * Basic address format validation * @param {Object} address - Address to validate * @returns {boolean} Whether the address has valid format */ function validateAddressFormat(address) { // Check required fields if (!address.street || !address.city || !address.zip || !address.country) { return false; } // Check zip code format - just basic validation if (address.country === 'US' && !/^\d{5}(-\d{4})?$/.test(address.zip)) { return false; } if (address.country === 'CA' && !/^[A-Za-z]\d[A-Za-z] \d[A-Za-z]\d$/.test(address.zip)) { return false; } return true; }