Skip to main content
Glama

Boilerplate MCP Server

by devkindhq
swell.orders.service.ts•11.9 kB
import { z } from 'zod'; import { Logger } from '../utils/logger.util.js'; import { config } from '../utils/config.util.js'; import { swellClient } from '../utils/swell-client.util.js'; import { createApiError, createUnexpectedError, McpError, } from '../utils/error.util.js'; import { SwellOrder, SwellOrderSchema, SwellOrdersList, SwellOrdersListSchema, OrderListOptions, OrderGetOptions, OrderStatusUpdateOptions, OrderAnalyticsOptions, OrderStatus, } from './swell.orders.types.js'; // Create a contextualized logger for this file const serviceLogger = Logger.forContext('services/swell.orders.service.ts'); // Log service initialization serviceLogger.debug('Swell Orders service initialized'); /** * @namespace SwellOrdersService * @description Service layer for interacting with Swell Orders API. * Handles order listing, retrieval, status updates, and analytics. */ /** * @function list * @description Fetches a paginated list of orders from Swell with optional filtering. * @memberof SwellOrdersService * @param {OrderListOptions} [options={}] - Optional filtering and pagination options * @returns {Promise<SwellOrdersList>} A promise that resolves to the orders list with pagination info * @throws {McpError} Throws an `McpError` if the API call fails or response validation fails * @example * // Get first 10 orders * const orders = await list({ limit: 10 }); * // Get orders with specific status * const pendingOrders = await list({ status: 'pending', page: 1 }); * // Get orders for a specific customer * const customerOrders = await list({ account_email: 'customer@example.com' }); */ async function list(options: OrderListOptions = {}): Promise<SwellOrdersList> { const methodLogger = serviceLogger.forMethod('list'); methodLogger.debug('Fetching orders list', options); try { // Ensure client is initialized if (!swellClient.isClientInitialized()) { swellClient.initWithAutoConfig(); } const client = swellClient.getClient(); // Build query parameters const queryParams: Record<string, unknown> = {}; if (options.page !== undefined) { queryParams.page = options.page; } if (options.limit !== undefined) { queryParams.limit = options.limit; } if (options.status !== undefined) { if (Array.isArray(options.status)) { queryParams.status = { $in: options.status }; } else { queryParams.status = options.status; } } if (options.account_id) { queryParams.account_id = options.account_id; } if (options.account_email) { queryParams.account_email = options.account_email; } if (options.date_created) { queryParams.date_created = options.date_created; } if (options.date_updated) { queryParams.date_updated = options.date_updated; } if (options.search) { queryParams.search = options.search; } if (options.sort) { queryParams.sort = options.sort; } if (options.where) { queryParams.where = options.where; } if (options.expand && options.expand.length > 0) { queryParams.expand = options.expand.join(','); } // Make the API call const rawData = await client.get<unknown>('/orders', queryParams); // Check if debug mode is enabled const isDebugMode = config.getBoolean('DEBUG', false); if (isDebugMode) { methodLogger.debug( 'Debug mode enabled - returning raw data without validation', ); return rawData as SwellOrdersList; } // Validate response with Zod schema const validatedData = SwellOrdersListSchema.parse(rawData); methodLogger.debug( `Successfully fetched ${validatedData.results.length} orders`, { count: validatedData.count, page: validatedData.page, pages: validatedData.pages, }, ); return validatedData; } catch (error) { methodLogger.error('Service error fetching orders list', error); // Handle Zod validation errors if (error instanceof z.ZodError) { throw createApiError( `Orders list response validation failed: ${error.issues .map((e: z.ZodIssue) => `${e.path.join('.')}: ${e.message}`) .join(', ')}`, 500, error, ); } // Rethrow other McpErrors if (error instanceof McpError) { throw error; } // Wrap any other unexpected errors throw createUnexpectedError( 'Unexpected service error while fetching orders list', error, ); } } /** * @function get * @description Fetches detailed information for a specific order by ID. * @memberof SwellOrdersService * @param {string} orderId - The ID of the order to retrieve * @param {OrderGetOptions} [options={}] - Optional retrieval options * @returns {Promise<SwellOrder>} A promise that resolves to the order details * @throws {McpError} Throws an `McpError` if the order is not found or API call fails * @example * // Get basic order details * const order = await get('order-id-123'); * // Get order with expanded relationships * const orderWithItems = await get('order-id-123', { expand: ['items', 'payments', 'shipments'] }); */ async function get( orderId: string, options: OrderGetOptions = {}, ): Promise<SwellOrder> { const methodLogger = serviceLogger.forMethod('get'); methodLogger.debug(`Fetching order details for ID: ${orderId}`, options); if (!orderId || orderId.trim().length === 0) { throw createApiError('Order ID is required', 400); } try { // Ensure client is initialized if (!swellClient.isClientInitialized()) { swellClient.initWithAutoConfig(); } const client = swellClient.getClient(); // Build query parameters const queryParams: Record<string, unknown> = {}; if (options.expand && options.expand.length > 0) { queryParams.expand = options.expand.join(','); } // Make the API call const rawData = await client.get<unknown>( `/orders/${orderId}`, queryParams, ); // Handle null response (order not found) if (!rawData) { throw createApiError(`Order not found: ${orderId}`, 404); } // Validate response with Zod schema const validatedData = SwellOrderSchema.parse(rawData); methodLogger.debug( `Successfully fetched order: ${validatedData.number || orderId}`, ); return validatedData; } catch (error) { methodLogger.error(`Service error fetching order ${orderId}`, error); // Handle Zod validation errors if (error instanceof z.ZodError) { throw createApiError( `Order response validation failed: ${error.issues .map((e: z.ZodIssue) => `${e.path.join('.')}: ${e.message}`) .join(', ')}`, 500, error, ); } // Rethrow other McpErrors if (error instanceof McpError) { throw error; } // Wrap any other unexpected errors throw createUnexpectedError( `Unexpected service error while fetching order ${orderId}`, error, ); } } /** * @function updateStatus * @description Updates the status of a specific order. * @memberof SwellOrdersService * @param {string} orderId - The ID of the order to update * @param {OrderStatusUpdateOptions} options - Status update options * @returns {Promise<SwellOrder>} A promise that resolves to the updated order * @throws {McpError} Throws an `McpError` if the order is not found or update fails * @example * // Update order status to complete * const updatedOrder = await updateStatus('order-id-123', { * status: 'complete', * notes: 'Order fulfilled successfully', * send_email: true * }); */ async function updateStatus( orderId: string, options: OrderStatusUpdateOptions, ): Promise<SwellOrder> { const methodLogger = serviceLogger.forMethod('updateStatus'); methodLogger.debug(`Updating status for order ID: ${orderId}`, options); if (!orderId || orderId.trim().length === 0) { throw createApiError('Order ID is required', 400); } if (!options.status) { throw createApiError('Order status is required', 400); } // Validate status value const validStatuses: OrderStatus[] = [ 'pending', 'payment_pending', 'delivery_pending', 'hold', 'complete', 'canceled', ]; if (!validStatuses.includes(options.status)) { throw createApiError( `Invalid order status: ${options.status}. Valid statuses are: ${validStatuses.join(', ')}`, 400, ); } try { // Ensure client is initialized if (!swellClient.isClientInitialized()) { swellClient.initWithAutoConfig(); } const client = swellClient.getClient(); // Build update data const updateData: Record<string, unknown> = { status: options.status, }; if (options.notes) { updateData.notes = options.notes; } if (options.send_email !== undefined) { updateData.send_email = options.send_email; } // Make the API call const rawData = await client.put<unknown>( `/orders/${orderId}`, updateData, ); // Handle null response (order not found) if (!rawData) { throw createApiError(`Order not found: ${orderId}`, 404); } // Validate response with Zod schema const validatedData = SwellOrderSchema.parse(rawData); methodLogger.debug( `Successfully updated order status: ${validatedData.number || orderId} -> ${options.status}`, ); return validatedData; } catch (error) { methodLogger.error( `Service error updating order status ${orderId}`, error, ); // Handle Zod validation errors if (error instanceof z.ZodError) { throw createApiError( `Order update response validation failed: ${error.issues .map((e: z.ZodIssue) => `${e.path.join('.')}: ${e.message}`) .join(', ')}`, 500, error, ); } // Rethrow other McpErrors if (error instanceof McpError) { throw error; } // Wrap any other unexpected errors throw createUnexpectedError( `Unexpected service error while updating order status ${orderId}`, error, ); } } /** * @function getAnalytics * @description Retrieves order analytics and reporting data. * @memberof SwellOrdersService * @param {OrderAnalyticsOptions} [options={}] - Analytics options * @returns {Promise<SwellOrdersList>} A promise that resolves to orders data for analytics * @throws {McpError} Throws an `McpError` if the API call fails * @example * // Get orders for the last 30 days * const analytics = await getAnalytics({ * date_from: '2023-01-01', * date_to: '2023-01-31', * group_by: 'day' * }); * // Get completed orders analytics * const completedAnalytics = await getAnalytics({ * status: 'complete', * metrics: ['count', 'total', 'average'] * }); */ async function getAnalytics( options: OrderAnalyticsOptions = {}, ): Promise<SwellOrdersList> { const methodLogger = serviceLogger.forMethod('getAnalytics'); methodLogger.debug('Fetching order analytics', options); try { // Build list options for analytics const listOptions: OrderListOptions = { limit: 1000, // Get more data for analytics }; if (options.status) { listOptions.status = options.status; } if (options.date_from || options.date_to) { listOptions.date_created = {}; if (options.date_from) { listOptions.date_created.$gte = options.date_from; } if (options.date_to) { listOptions.date_created.$lte = options.date_to; } } // Sort by date for analytics listOptions.sort = 'date_created'; // Expand items for detailed analytics listOptions.expand = ['items']; // Get orders data const ordersData = await list(listOptions); methodLogger.debug( `Successfully fetched analytics data: ${ordersData.count} orders`, { date_from: options.date_from, date_to: options.date_to, status: options.status, }, ); return ordersData; } catch (error) { methodLogger.error('Service error fetching order analytics', error); // Rethrow McpErrors if (error instanceof McpError) { throw error; } // Wrap any other unexpected errors throw createUnexpectedError( 'Unexpected service error while fetching order analytics', error, ); } } export default { list, get, updateStatus, getAnalytics, };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/devkindhq/swell-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server