import { query, internalQuery } from "./_generated/server"; import { v } from "convex/values"; import * as Users from "./model/users"; import * as CartsModel from "./model/carts"; import { validateAndEnrichCart } from "./model/checkout"; import type { CartValidationResult } from "./model/checkout"; const EMPTY_RESULT_INVALID: CartValidationResult = { valid: false, items: [], issues: [], subtotal: 0, }; const EMPTY_RESULT_VALID: CartValidationResult = { valid: true, items: [], issues: [], subtotal: 0, }; export const validateCart = query({ args: { sessionId: v.optional(v.string()) }, handler: async (ctx, args) => { const user = await Users.getCurrentUser(ctx); const userId = user?._id ?? null; if (!userId && !args.sessionId) { return EMPTY_RESULT_INVALID; } const cart = await CartsModel.getCart(ctx, userId ?? undefined, args.sessionId); if (!cart || cart.items.length === 0) { return EMPTY_RESULT_VALID; } return await validateAndEnrichCart(ctx, cart.items); }, }); export const getShippingAddresses = query({ args: {}, handler: async (ctx) => { const user = await Users.getCurrentUserOrThrow(ctx); const addresses = await ctx.db .query("addresses") .withIndex("by_user_and_type", (q) => q.eq("userId", user._id).eq("type", "shipping"), ) .collect(); addresses.sort((a, b) => { if (a.isDefault !== b.isDefault) return a.isDefault ? -1 : 1; return b._creationTime - a._creationTime; }); return addresses; }, }); // ─── Internal Queries (consumed by actions in checkoutActions.ts) ──────────── export const getAddressById = internalQuery({ args: { addressId: v.id("addresses") }, handler: async (ctx, args) => { const address = await ctx.db.get(args.addressId); if (!address) throw new Error("Address not found"); return address; }, }); export const validateCartInternal = internalQuery({ args: { userId: v.optional(v.id("users")), sessionId: v.optional(v.string()), }, handler: async (ctx, args) => { const cart = await CartsModel.getCart( ctx, args.userId ?? undefined, args.sessionId, ); if (!cart || cart.items.length === 0) return null; return await validateAndEnrichCart(ctx, cart.items); }, }); export const getCurrentUserId = internalQuery({ args: {}, handler: async (ctx) => { const user = await Users.getCurrentUserOrThrow(ctx); return user._id; }, });