201 lines
9.9 KiB
JavaScript
201 lines
9.9 KiB
JavaScript
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
|