/** * Lightspeed API Client * Supports both Retail (X-Series) and Restaurant (R-Series) APIs */ import axios, { AxiosInstance } from 'axios'; import type { LightspeedConfig, Product, ProductInventory, Customer, Sale, Order, Employee, Category, Supplier, Discount, LoyaltyProgram, CustomerLoyalty, Shop, Register, PaymentType, TaxCategory, Manufacturer, ApiResponse } from '../types/index.js'; export class LightspeedClient { private client: AxiosInstance; private config: LightspeedConfig; constructor(config: LightspeedConfig) { this.config = config; const baseUrl = config.baseUrl || 'https://api.lightspeedapp.com/API/V3'; this.client = axios.create({ baseURL: baseUrl, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${config.apiKey}` }, timeout: 30000 }); // Add response interceptor for error handling this.client.interceptors.response.use( response => response, error => { console.error('Lightspeed API Error:', error.response?.data || error.message); throw error; } ); } private getAccountPath(): string { return `/Account/${this.config.accountId}`; } // ========== PRODUCTS ========== async getProducts(params?: { limit?: number; offset?: number; categoryID?: string }): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Item.json`, { params }); return { success: true, data: response.data.Item || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getProduct(productID: string): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Item/${productID}.json`); return { success: true, data: response.data.Item }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async createProduct(product: Partial): Promise> { try { const response = await this.client.post(`${this.getAccountPath()}/Item.json`, { Item: product }); return { success: true, data: response.data.Item }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async updateProduct(productID: string, updates: Partial): Promise> { try { const response = await this.client.put(`${this.getAccountPath()}/Item/${productID}.json`, { Item: updates }); return { success: true, data: response.data.Item }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async deleteProduct(productID: string): Promise> { try { await this.client.delete(`${this.getAccountPath()}/Item/${productID}.json`); return { success: true, data: true }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getProductInventory(productID: string, shopID?: string): Promise> { try { const params = shopID ? { shopID } : {}; const response = await this.client.get(`${this.getAccountPath()}/Item/${productID}/ItemShops.json`, { params }); return { success: true, data: response.data.ItemShop || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async updateInventory(productID: string, shopID: string, qty: number): Promise> { try { const response = await this.client.put( `${this.getAccountPath()}/Item/${productID}/ItemShops/${shopID}.json`, { ItemShop: { qty } } ); return { success: true, data: response.data.ItemShop }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== CUSTOMERS ========== async getCustomers(params?: { limit?: number; offset?: number; email?: string }): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Customer.json`, { params }); return { success: true, data: response.data.Customer || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getCustomer(customerID: string): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Customer/${customerID}.json`); return { success: true, data: response.data.Customer }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async createCustomer(customer: Partial): Promise> { try { const response = await this.client.post(`${this.getAccountPath()}/Customer.json`, { Customer: customer }); return { success: true, data: response.data.Customer }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async updateCustomer(customerID: string, updates: Partial): Promise> { try { const response = await this.client.put(`${this.getAccountPath()}/Customer/${customerID}.json`, { Customer: updates }); return { success: true, data: response.data.Customer }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async deleteCustomer(customerID: string): Promise> { try { await this.client.delete(`${this.getAccountPath()}/Customer/${customerID}.json`); return { success: true, data: true }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== SALES ========== async getSales(params?: { limit?: number; offset?: number; startDate?: string; endDate?: string }): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Sale.json`, { params }); return { success: true, data: response.data.Sale || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getSale(saleID: string): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Sale/${saleID}.json`); return { success: true, data: response.data.Sale }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async createSale(sale: Partial): Promise> { try { const response = await this.client.post(`${this.getAccountPath()}/Sale.json`, { Sale: sale }); return { success: true, data: response.data.Sale }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async updateSale(saleID: string, updates: Partial): Promise> { try { const response = await this.client.put(`${this.getAccountPath()}/Sale/${saleID}.json`, { Sale: updates }); return { success: true, data: response.data.Sale }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async voidSale(saleID: string): Promise> { try { const response = await this.client.put(`${this.getAccountPath()}/Sale/${saleID}.json`, { Sale: { voided: true } }); return { success: true, data: response.data.Sale }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== ORDERS ========== async getOrders(params?: { limit?: number; offset?: number; status?: string }): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Order.json`, { params }); return { success: true, data: response.data.Order || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getOrder(orderID: string): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Order/${orderID}.json`); return { success: true, data: response.data.Order }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async createOrder(order: Partial): Promise> { try { const response = await this.client.post(`${this.getAccountPath()}/Order.json`, { Order: order }); return { success: true, data: response.data.Order }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async updateOrder(orderID: string, updates: Partial): Promise> { try { const response = await this.client.put(`${this.getAccountPath()}/Order/${orderID}.json`, { Order: updates }); return { success: true, data: response.data.Order }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async deleteOrder(orderID: string): Promise> { try { await this.client.delete(`${this.getAccountPath()}/Order/${orderID}.json`); return { success: true, data: true }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== EMPLOYEES ========== async getEmployees(params?: { limit?: number; offset?: number }): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Employee.json`, { params }); return { success: true, data: response.data.Employee || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getEmployee(employeeID: string): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Employee/${employeeID}.json`); return { success: true, data: response.data.Employee }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async createEmployee(employee: Partial): Promise> { try { const response = await this.client.post(`${this.getAccountPath()}/Employee.json`, { Employee: employee }); return { success: true, data: response.data.Employee }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async updateEmployee(employeeID: string, updates: Partial): Promise> { try { const response = await this.client.put(`${this.getAccountPath()}/Employee/${employeeID}.json`, { Employee: updates }); return { success: true, data: response.data.Employee }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async deleteEmployee(employeeID: string): Promise> { try { await this.client.delete(`${this.getAccountPath()}/Employee/${employeeID}.json`); return { success: true, data: true }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== CATEGORIES ========== async getCategories(params?: { limit?: number; offset?: number }): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Category.json`, { params }); return { success: true, data: response.data.Category || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getCategory(categoryID: string): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Category/${categoryID}.json`); return { success: true, data: response.data.Category }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async createCategory(category: Partial): Promise> { try { const response = await this.client.post(`${this.getAccountPath()}/Category.json`, { Category: category }); return { success: true, data: response.data.Category }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async updateCategory(categoryID: string, updates: Partial): Promise> { try { const response = await this.client.put(`${this.getAccountPath()}/Category/${categoryID}.json`, { Category: updates }); return { success: true, data: response.data.Category }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async deleteCategory(categoryID: string): Promise> { try { await this.client.delete(`${this.getAccountPath()}/Category/${categoryID}.json`); return { success: true, data: true }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== SUPPLIERS ========== async getSuppliers(params?: { limit?: number; offset?: number }): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Vendor.json`, { params }); return { success: true, data: response.data.Vendor || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getSupplier(supplierID: string): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Vendor/${supplierID}.json`); return { success: true, data: response.data.Vendor }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async createSupplier(supplier: Partial): Promise> { try { const response = await this.client.post(`${this.getAccountPath()}/Vendor.json`, { Vendor: supplier }); return { success: true, data: response.data.Vendor }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async updateSupplier(supplierID: string, updates: Partial): Promise> { try { const response = await this.client.put(`${this.getAccountPath()}/Vendor/${supplierID}.json`, { Vendor: updates }); return { success: true, data: response.data.Vendor }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async deleteSupplier(supplierID: string): Promise> { try { await this.client.delete(`${this.getAccountPath()}/Vendor/${supplierID}.json`); return { success: true, data: true }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== DISCOUNTS ========== async getDiscounts(params?: { limit?: number; offset?: number }): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Discount.json`, { params }); return { success: true, data: response.data.Discount || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getDiscount(discountID: string): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Discount/${discountID}.json`); return { success: true, data: response.data.Discount }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async createDiscount(discount: Partial): Promise> { try { const response = await this.client.post(`${this.getAccountPath()}/Discount.json`, { Discount: discount }); return { success: true, data: response.data.Discount }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async updateDiscount(discountID: string, updates: Partial): Promise> { try { const response = await this.client.put(`${this.getAccountPath()}/Discount/${discountID}.json`, { Discount: updates }); return { success: true, data: response.data.Discount }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async deleteDiscount(discountID: string): Promise> { try { await this.client.delete(`${this.getAccountPath()}/Discount/${discountID}.json`); return { success: true, data: true }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== SHOPS & REGISTERS ========== async getShops(): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Shop.json`); return { success: true, data: response.data.Shop || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getShop(shopID: string): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Shop/${shopID}.json`); return { success: true, data: response.data.Shop }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async getRegisters(shopID?: string): Promise> { try { const params = shopID ? { shopID } : {}; const response = await this.client.get(`${this.getAccountPath()}/Register.json`, { params }); return { success: true, data: response.data.Register || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== MANUFACTURERS ========== async getManufacturers(): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/Manufacturer.json`); return { success: true, data: response.data.Manufacturer || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } async createManufacturer(name: string): Promise> { try { const response = await this.client.post(`${this.getAccountPath()}/Manufacturer.json`, { Manufacturer: { name } }); return { success: true, data: response.data.Manufacturer }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== TAX CATEGORIES ========== async getTaxCategories(): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/TaxCategory.json`); return { success: true, data: response.data.TaxCategory || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } // ========== PAYMENT TYPES ========== async getPaymentTypes(): Promise> { try { const response = await this.client.get(`${this.getAccountPath()}/PaymentType.json`); return { success: true, data: response.data.PaymentType || [] }; } catch (error: any) { return { success: false, error: error.message, details: error.response?.data }; } } }