LogicTrail
How does checkout work? 52 nodes · 56 edges · static analysis
CheckoutPage calls useCart()CheckoutPage calls handleCheckout()onClickuseCart() requests GET /api/cartuseEffecthandleCheckout() calls createOrder()handleCheckout() calls Stripe.js: confirmCardPaymenthandleCheckout() condition result.errorcreateOrder() requests POST /api/ordersresult.error navigates navigate /checkout/failedyesresult.error navigates navigate /orders/:paramnoPOST /api/orders calls requireAuth()middlewarePOST /api/orders calls validateBody()middlewarePOST /api/orders calls OrdersController.create()requireAuth() reads session.findUniquerequireAuth() condition !session || session.expiresAt < new Date()validateBody() condition !result.successOrdersController.create() calls getCart()OrdersController.create() calls validateCart()OrdersController.create() condition !validation.ok!session || session.expiresAt < new Date() returns 401 Unauthorizedyes!result.success returns 400 Bad RequestyesgetCart() reads cartItem.findMany!validation.ok returns 400 Bad Requestyes!validation.ok calls OrderService.createOrder()no!validation.ok calls createPaymentIntent()noOrderService.createOrder() calls cartTotal()OrderService.createOrder() writes order.createOrderService.createOrder() calls reserveInventory()OrderService.createOrder() emits order.createdcreatePaymentIntent() calls Stripe: paymentIntents.createreserveInventory() writes product.updatefor eachreserveInventory() condition product.stock < 0Stripe: paymentIntents.create triggers POST /api/webhooks/stripe (inferred, 60%)webhookproduct.stock < 0 returns throw OutOfStockErroryesPOST /api/webhooks/stripe calls handleStripeWebhook()handleStripeWebhook() calls Stripe: webhooks.constructEventhandleStripeWebhook() condition catchon errorhandleStripeWebhook() condition switch (event.type)catch returns 400 Bad Requestswitch (event.type) calls markOrderPaid()payment_intent.succeededswitch (event.type) calls markOrderFailed()payment_intent.payment_fail…markOrderPaid() writes order.updatemarkOrderPaid() emits emails queueorder-confirmationmarkOrderFailed() writes order.updatemarkOrderFailed() calls releaseInventory()markOrderFailed() emits order.paymentFailedemails queue triggers worker emails handlerworkerreleaseInventory() reads cartItem.findManyreleaseInventory() writes product.updatefor eachorder.paymentFailed triggers notifyPaymentFailed()listenerworker emails handler condition job.name === "order-confirmation"notifyPaymentFailed() calls sendPaymentFailedEmail()job.name === "order-confirmation" calls sendOrderConfirmation()yessendPaymentFailedEmail() reads order.findUniquesendPaymentFailedEmail() calls Resend: emails.sendsendOrderConfirmation() reads order.findUniquesendOrderConfirmation() calls Resend: emails.sendCheckoutPage React component rendered for /checkout.CheckoutPagepages/CheckoutPage.tsx:9useCart() export function useCart()useCart()hooks/useCart.ts:4handleCheckout() async function handleCheckout()handleCheckout()pages/CheckoutPage.tsx:14GET /api/cart HTTP GET request to /cart.GET /api/carthooks/useCart.ts:9createOrder() export async function createOrder(shippingAddressId: string): Promise<CreatedOrder>createOrder()api/orders.ts:8Stripe.js: confirmCardPayment Calls Stripe.js: confirmCardPayment.Stripe.js: confirmCardPaymentpages/CheckoutPage.tsx:18result.error handleCheckout() branches on `result.error`.result.errorPOST /api/orders express route POST /api/orders.POST /api/ordersroutes/orders.ts:8navigate /checkout/failed Client-side navigation to /checkout/failed.navigate /checkout/failedpages/CheckoutPage.tsx:21navigate /orders/:param Client-side navigation to /orders/:param.navigate /orders/:parampages/CheckoutPage.tsx:24requireAuth() Rejects requests without a valid session cookie.requireAuth()middleware/requireAuth.ts:5validateBody() Validates the request body against a zod schema.validateBody()middleware/validate.ts:5OrdersController.create() Turns the user's cart into an order and starts a Stripe payment.OrdersController.create()controllers/ordersController.ts:10session.findUnique Reads from session via prisma (findUnique).session.findUniquemiddleware/requireAuth.ts:8!session || session.expiresAt < new Date() requireAuth() branches on `!session || session.expiresAt < new Date()`.!session || session.expiresAt < new Dat…!result.success validateBody() branches on `!result.success`.!result.successgetCart() export async function getCart(userId: string): Promise<Cart>getCart()services/cart.ts:14validateCart() Checks that the cart is not empty and every quantity is positive.validateCart()services/cart.ts:27!validation.ok OrdersController.create() branches on `!validation.ok`.!validation.ok401 Unauthorized requireAuth() responds with HTTP 401.401 Unauthorizedmiddleware/requireAuth.ts:11400 Bad Request validateBody() responds with HTTP 400.400 Bad Requestmiddleware/validate.ts:9cartItem.findMany Reads from cartItem via prisma (findMany).cartItem.findManyservices/cart.ts:15400 Bad Request OrdersController.create() responds with HTTP 400.400 Bad Requestcontrollers/ordersController.ts:14OrderService.createOrder() Persists a pending order and reserves stock for its items.OrderService.createOrder()services/orderService.ts:9createPaymentIntent() Creates a Stripe PaymentIntent for the order total.createPaymentIntent()payments/stripe.ts:8cartTotal() export function cartTotal(cart: Cart): numbercartTotal()services/cart.ts:36order.create Writes to order via prisma (create).order.createservices/orderService.ts:10reserveInventory() Decrements stock for every cart line; fails if a product runs out.reserveInventory()services/inventory.ts:11order.created Event "order.created".order.createdservices/orderService.ts:14Stripe: paymentIntents.create Calls Stripe: paymentIntents.create.Stripe: paymentIntents.createpayments/stripe.ts:9product.update Writes to product via prisma (update).product.updateservices/inventory.ts:13product.stock < 0 reserveInventory() branches on `product.stock < 0`.product.stock < 0POST /api/webhooks/stripe express route POST /api/webhooks/stripe.POST /api/webhooks/striperoutes/webhooks.ts:6throw OutOfStockError reserveInventory() throws OutOfStockError.throw OutOfStockErrorservices/inventory.ts:18handleStripeWebhook() Verifies the Stripe signature and applies payment results to orders.handleStripeWebhook()payments/stripe.ts:17Stripe: webhooks.constructEvent Calls Stripe: webhooks.constructEvent.Stripe: webhooks.constructEventpayments/stripe.ts:20catch Error handling in handleStripeWebhook(): runs when the code above throws.catchswitch (event.type) handleStripeWebhook() branches on `switch (event.type)`.switch (event.type)400 Bad Request handleStripeWebhook() responds with HTTP 400.400 Bad Requestpayments/stripe.ts:26markOrderPaid() Marks an order as paid and queues the confirmation email.markOrderPaid()services/orderService.ts:24markOrderFailed() Marks an order as failed, releases its stock and notifies listeners.markOrderFailed()services/orderService.ts:30order.update Writes to order via prisma (update).order.updateservices/orderService.ts:25emails queue Background job queue "emails".emails queueservices/orderService.ts:26releaseInventory() export async function releaseInventory(orderId: string)releaseInventory()services/inventory.ts:23order.paymentFailed Event "order.paymentFailed".order.paymentFailedservices/orderService.ts:33worker emails handler async (job) =>worker emails handlerjobs/emailWorker.ts:7notifyPaymentFailed() async function notifyPaymentFailed({ orderId }: { orderId: string })notifyPaymentFailed()events/handlers.ts:11job.name === "order-confirmation" worker emails handler branches on `job.name === "order-confirmation"`.job.name === "order-confirmation"sendPaymentFailedEmail() export async function sendPaymentFailedEmail(orderId: string)sendPaymentFailedEmail()email/send.ts:18sendOrderConfirmation() Emails the customer a receipt for a paid order.sendOrderConfirmation()email/send.ts:7order.findUnique Reads from order via prisma (findUnique).order.findUniqueemail/send.ts:8Resend: emails.send Calls Resend: emails.send.Resend: emails.sendemail/send.ts:10
ComponentFunctionExternal serviceConditionRouteDatabaseServiceErrorEvent / queueInferred
100%