import axios from 'axios'; export class ToastAPIError extends Error { statusCode; response; constructor(message, statusCode, response) { super(message); this.statusCode = statusCode; this.response = response; this.name = 'ToastAPIError'; } } export class ToastAPIClient { client; config; constructor(config) { this.config = { baseUrl: config.baseUrl || 'https://ws-api.toasttab.com', ...config, }; this.client = axios.create({ baseURL: this.config.baseUrl, headers: { 'Authorization': `Bearer ${this.config.apiToken}`, 'Content-Type': 'application/json', 'Toast-Restaurant-External-ID': this.config.restaurantGuid, }, timeout: 30000, }); // Response interceptor for error handling this.client.interceptors.response.use((response) => response, (error) => { if (error.response) { const errorData = error.response.data; throw new ToastAPIError(errorData?.message || error.message, error.response.status, error.response.data); } else if (error.request) { throw new ToastAPIError('No response received from Toast API'); } else { throw new ToastAPIError(error.message); } }); } // Generic GET request with pagination support async get(endpoint, params, config) { const response = await this.client.get(endpoint, { params, ...config, }); return response.data; } // Generic POST request async post(endpoint, data, config) { const response = await this.client.post(endpoint, data, config); return response.data; } // Generic PUT request async put(endpoint, data, config) { const response = await this.client.put(endpoint, data, config); return response.data; } // Generic PATCH request async patch(endpoint, data, config) { const response = await this.client.patch(endpoint, data, config); return response.data; } // Generic DELETE request async delete(endpoint, config) { const response = await this.client.delete(endpoint, config); return response.data; } // Paginated GET request async getPaginated(endpoint, pagination, additionalParams) { const params = { page: pagination?.page || 1, pageSize: pagination?.pageSize || 100, ...additionalParams, }; const response = await this.get(endpoint, params); // If the API returns pagination metadata, use it // Otherwise, create a simple paginated response return { data: Array.isArray(response) ? response : [], page: params.page, pageSize: params.pageSize, totalPages: 1, totalCount: Array.isArray(response) ? response.length : 0, }; } // Get all pages automatically async getAllPages(endpoint, pageSize = 100, additionalParams) { const allData = []; let page = 1; let hasMore = true; while (hasMore) { const response = await this.getPaginated(endpoint, { page, pageSize }, additionalParams); allData.push(...response.data); // Check if there are more pages hasMore = response.data.length === pageSize && page < response.totalPages; page++; } return allData; } // Orders API orders = { list: (params) => this.getPaginated('/orders/v2/orders', params?.pagination, { startDate: params?.startDate, endDate: params?.endDate, }), get: (orderId) => this.get(`/orders/v2/orders/${orderId}`), create: (orderData) => this.post('/orders/v2/orders', orderData), update: (orderId, orderData) => this.put(`/orders/v2/orders/${orderId}`, orderData), void: (orderId, voidReason) => this.post(`/orders/v2/orders/${orderId}/void`, { voidReason }), listChecks: (orderId) => this.get(`/orders/v2/orders/${orderId}/checks`), addItem: (orderId, checkId, itemData) => this.post(`/orders/v2/orders/${orderId}/checks/${checkId}/selections`, itemData), removeItem: (orderId, checkId, selectionId) => this.delete(`/orders/v2/orders/${orderId}/checks/${checkId}/selections/${selectionId}`), applyDiscount: (orderId, checkId, discountData) => this.post(`/orders/v2/orders/${orderId}/checks/${checkId}/appliedDiscounts`, discountData), }; // Menus API menus = { list: () => this.get('/menus/v2/menus'), get: (menuId) => this.get(`/menus/v2/menus/${menuId}`), listGroups: (menuId) => this.get(`/menus/v2/menus/${menuId}/groups`), getGroup: (menuId, groupId) => this.get(`/menus/v2/menus/${menuId}/groups/${groupId}`), listItems: (menuId, groupId) => groupId ? this.get(`/menus/v2/menus/${menuId}/groups/${groupId}/items`) : this.get(`/menus/v2/menus/${menuId}/items`), getItem: (menuId, itemId) => this.get(`/menus/v2/menus/${menuId}/items/${itemId}`), listModifiers: (menuId, itemId) => this.get(`/menus/v2/menus/${menuId}/items/${itemId}/modifierGroups`), updatePrice: (menuId, itemId, price) => this.patch(`/menus/v2/menus/${menuId}/items/${itemId}`, { price }), }; // Employees API employees = { list: (pagination) => this.getPaginated('/labor/v1/employees', pagination), get: (employeeId) => this.get(`/labor/v1/employees/${employeeId}`), create: (employeeData) => this.post('/labor/v1/employees', employeeData), update: (employeeId, employeeData) => this.put(`/labor/v1/employees/${employeeId}`, employeeData), delete: (employeeId) => this.delete(`/labor/v1/employees/${employeeId}`), listJobs: (employeeId) => this.get(`/labor/v1/employees/${employeeId}/jobs`), listShifts: (employeeId, startDate, endDate) => this.get(`/labor/v1/employees/${employeeId}/shifts`, { startDate, endDate }), clockIn: (employeeId, jobId) => this.post(`/labor/v1/employees/${employeeId}/timeEntries`, { jobGuid: jobId, inDate: new Date().toISOString(), }), clockOut: (employeeId, timeEntryId) => this.patch(`/labor/v1/employees/${employeeId}/timeEntries/${timeEntryId}`, { outDate: new Date().toISOString(), }), listTimeEntries: (employeeId, startDate, endDate) => this.get(`/labor/v1/employees/${employeeId}/timeEntries`, { startDate, endDate }), }; // Labor API labor = { listShifts: (startDate, endDate, pagination) => this.getPaginated('/labor/v1/shifts', pagination, { startDate, endDate }), getShift: (shiftId) => this.get(`/labor/v1/shifts/${shiftId}`), listBreaks: (shiftId) => this.get(`/labor/v1/shifts/${shiftId}/breaks`), getLaborCost: (businessDate) => this.get('/labor/v1/laborCost', { businessDate }), listJobs: () => this.get('/labor/v1/jobs'), }; // Restaurant API restaurant = { getInfo: () => this.get('/restaurants/v1/restaurants/' + this.config.restaurantGuid), listRevenueCenters: () => this.get('/restaurants/v1/restaurants/' + this.config.restaurantGuid + '/revenueCenters'), listDiningOptions: () => this.get('/restaurants/v1/restaurants/' + this.config.restaurantGuid + '/diningOptions'), listServiceAreas: () => this.get('/restaurants/v1/restaurants/' + this.config.restaurantGuid + '/serviceAreas'), listTables: (serviceAreaId) => serviceAreaId ? this.get(`/restaurants/v1/restaurants/${this.config.restaurantGuid}/serviceAreas/${serviceAreaId}/tables`) : this.get(`/restaurants/v1/restaurants/${this.config.restaurantGuid}/tables`), }; // Payments API payments = { list: (startDate, endDate, pagination) => this.getPaginated('/payments/v1/payments', pagination, { startDate, endDate }), get: (paymentId) => this.get(`/payments/v1/payments/${paymentId}`), void: (paymentId, voidReason) => this.post(`/payments/v1/payments/${paymentId}/void`, { voidReason }), refund: (paymentId, refundAmount, refundReason) => this.post(`/payments/v1/payments/${paymentId}/refund`, { refundAmount, refundReason, }), listTips: (startDate, endDate) => this.get('/payments/v1/tips', { startDate, endDate }), }; // Inventory API (Note: Toast may not have full inventory API, these are examples) inventory = { listItems: (pagination) => this.getPaginated('/inventory/v1/items', pagination), getItem: (itemId) => this.get(`/inventory/v1/items/${itemId}`), updateCount: (itemId, quantity) => this.patch(`/inventory/v1/items/${itemId}`, { currentQuantity: quantity }), listVendors: () => this.get('/inventory/v1/vendors'), createPurchaseOrder: (poData) => this.post('/inventory/v1/purchaseOrders', poData), }; // Customers API (Note: Toast may not have full customer API, these are examples) customers = { list: (pagination) => this.getPaginated('/customers/v1/customers', pagination), get: (customerId) => this.get(`/customers/v1/customers/${customerId}`), create: (customerData) => this.post('/customers/v1/customers', customerData), update: (customerId, customerData) => this.put(`/customers/v1/customers/${customerId}`, customerData), listLoyalty: (customerId) => this.get(`/customers/v1/customers/${customerId}/loyalty`), addLoyaltyPoints: (customerId, points) => this.post(`/customers/v1/customers/${customerId}/loyalty/points`, { points }), }; // Cash Management API cash = { listEntries: (startDate, endDate, pagination) => this.getPaginated('/cash/v1/entries', pagination, { startDate, endDate }), getDrawerStatus: (drawerId) => this.get(`/cash/v1/drawers/${drawerId}`), }; } //# sourceMappingURL=api-client.js.map