Skip to content
← Public packages

@kody/doordash

Order food on DoorDash as a customer through the consumer MCP used by dd-cli.

src/order.ts

96 lines · 2.8 KB · TypeScript
/**
 * Order helpers (history / preview / submit / reorder / receipt / status / checkout-url).
 *
 * Mutations (submit, reorder) dry-run unless `confirm: true`.
 */

import { callMcpTool, TOOLS, type DoorDashMcpAuthInput } from './mcp.ts'

const ACTIONS = [
	'history',
	'preview',
	'submit',
	'reorder',
	'receipt',
	'status',
	'checkout-url',
] as const
export type OrderAction = (typeof ACTIONS)[number]

export type OrderInput = DoorDashMcpAuthInput & {
	action?: OrderAction
	cartUuid?: string
	orderUuid?: string
	tipCents?: number
	maxOrders?: number
	confirm?: boolean
	dryRun?: boolean
	[key: string]: unknown
}

function shouldDryRun(input: OrderInput, mutating: boolean) {
	if (input.dryRun === true) return true
	if (mutating && input.confirm !== true && input.dryRun !== false) return true
	return false
}

export default async function order(input: OrderInput = {}) {
	const action = (input.action ?? 'history') as OrderAction
	if (!ACTIONS.includes(action)) {
		throw new Error('Unknown order action: ' + action + '. Valid: ' + ACTIONS.join(', '))
	}

	if (action === 'history') {
		const args: Record<string, unknown> = {}
		if (input.maxOrders != null) args.max_orders = input.maxOrders
		return callMcpTool({ ...input, name: TOOLS.orderHistory, arguments: args })
	}
	if (action === 'preview') {
		const cartUuid = String(input.cartUuid ?? '').trim()
		if (!cartUuid) throw new Error('cartUuid is required for preview.')
		return callMcpTool({
			...input,
			name: TOOLS.previewOrder,
			arguments: { cart_uuid: cartUuid },
		})
	}
	if (action === 'checkout-url') {
		const cartUuid = String(input.cartUuid ?? '').trim()
		if (!cartUuid) throw new Error('cartUuid is required for checkout-url.')
		return callMcpTool({
			...input,
			name: TOOLS.checkoutUrl,
			arguments: { cart_uuid: cartUuid },
		})
	}
	if (action === 'receipt' || action === 'status') {
		const orderUuid = String(input.orderUuid ?? '').trim()
		if (!orderUuid) throw new Error('orderUuid is required for ' + action + '.')
		return callMcpTool({
			...input,
			name: action === 'receipt' ? TOOLS.orderReceipt : TOOLS.orderStatus,
			arguments: { order_uuid: orderUuid },
		})
	}
	if (action === 'reorder') {
		const orderUuid = String(input.orderUuid ?? '').trim()
		if (!orderUuid) throw new Error('orderUuid is required for reorder.')
		return callMcpTool({
			...input,
			name: TOOLS.reorder,
			arguments: { order_uuid: orderUuid },
			dryRun: shouldDryRun(input, true),
		})
	}
	// submit
	const cartUuid = String(input.cartUuid ?? '').trim()
	if (!cartUuid) throw new Error('cartUuid is required for submit.')
	const args: Record<string, unknown> = { cart_uuid: cartUuid }
	if (input.tipCents != null) args.tip_amount_cents = input.tipCents
	return callMcpTool({
		...input,
		name: TOOLS.submitOrder,
		arguments: args,
		dryRun: shouldDryRun(input, true),
	})
}