import "server-only"; import { adminRoleSchema } from "@salixcommerce/core"; import { PostgrestClient } from "@supabase/postgrest-js"; import { adminFailure, type AdminDashboard, type AdminRepository, type AdminResult, } from "./repository"; interface Credentials { readonly serviceRoleKey: string; readonly url: string; } type Row = Record; export function createSupabaseAdminRepository(credentials: Credentials): AdminRepository { const client = new PostgrestClient(`${credentials.url.replace(/\/$/u, "")}/rest/v1`, { headers: { apikey: credentials.serviceRoleKey, authorization: `Bearer ${credentials.serviceRoleKey}`, }, timeout: 10_000, }); const repository = { async adjustInventory(context, inventoryItemId, command, requestHash) { const result = await client.rpc("salix_admin_adjust_inventory", { p_admin_user_id: context.userId, p_delta: command.delta, p_idempotency_key: command.idempotencyKey, p_inventory_item_id: inventoryItemId, p_reason: command.reason, p_request_hash: requestHash, }); const rpc = readRpc(result.data, result.error); return rpc.ok ? { data: { onHand: readSafeNumber(rpc.data, "on_hand"), replayed: boolean(rpc.data, "replayed"), }, ok: true, } : rpc; }, async loadDashboard(context) { const [ productsResult, variantsResult, inventoryResult, ordersResult, paymentsResult, refundsResult, ] = await Promise.all([ client.from("products").select("id,name,description,status").order("id"), client .from("product_variants") .select("id,product_id,name,price_minor,currency,active,allow_backorder") .order("position") .order("id"), client.from("inventory_items").select("id,variant_id,mode,on_hand,reserved").order("id"), client .from("orders") .select( "id,reference,contact_email,status,currency,merchandise_subtotal_minor,tracking_carrier,tracking_number,created_at", ) .order("created_at", { ascending: false }) .limit(100), client .from("payments") .select( "id,order_id,provider,provider_payment_reference,status,currency,amount_minor,refunded_amount_minor", ) .order("created_at", { ascending: false }) .limit(100), client .from("refund_requests") .select( "order_id,provider_refund_reference,amount_minor,currency,reason,status,created_at", ) .order("created_at", { ascending: false }) .limit(100), ]); const activityResult = context.capabilities.includes("admin.audit.read") ? await client .from("admin_activity_log") .select("action,entity_type,entity_id,created_at") .order("created_at", { ascending: false }) .limit(100) : { data: [], error: null }; const products = rows(productsResult, "products"); const variants = rows(variantsResult, "variants"); const inventory = rows(inventoryResult, "inventory"); const orders = rows(ordersResult, "orders"); const payments = rows(paymentsResult, "payments"); const refunds = rows(refundsResult, "refunds"); const activity = rows(activityResult, "activity"); const orderById = new Map( orders.map((row) => [identifier(row, "id"), string(row, "reference")]), ); const variantById = new Map(variants.map((row) => [identifier(row, "id"), row])); const productById = new Map(products.map((row) => [identifier(row, "id"), row])); return { activity: activity.map((row) => ({ action: string(row, "action"), createdAt: string(row, "created_at"), entityId: string(row, "entity_id"), entityType: string(row, "entity_type"), })), inventory: inventory.map((row) => { const variant = required( variantById.get(identifier(row, "variant_id")), "inventory variant", ); const product = required( productById.get(identifier(variant, "product_id")), "inventory product", ); const mode = string(row, "mode"); if (mode !== "tracked" && mode !== "untracked") throw invalid("inventory mode"); return { id: identifier(row, "id"), mode, onHand: readSafeNumber(row, "on_hand"), productName: string(product, "name"), reserved: readSafeNumber(row, "reserved"), variantName: string(variant, "name"), }; }), orders: orders.map((row) => { const status = string(row, "status"); if (!["pending_payment", "paid", "processing", "fulfilled", "cancelled"].includes(status)) throw invalid("order status"); return { contactEmail: string(row, "contact_email"), createdAt: string(row, "created_at"), currency: string(row, "currency"), merchandiseSubtotalMinor: readSafeNumber(row, "merchandise_subtotal_minor"), reference: string(row, "reference"), status: status as AdminDashboard["orders"][number]["status"], trackingCarrier: nullableString(row, "tracking_carrier"), trackingNumber: nullableString(row, "tracking_number"), }; }), payments: payments.map((row) => ({ amountMinor: readSafeNumber(row, "amount_minor"), currency: string(row, "currency"), orderReference: required(orderById.get(identifier(row, "order_id")), "payment order"), provider: string(row, "provider"), providerPaymentReference: string(row, "provider_payment_reference"), refundedAmountMinor: readSafeNumber(row, "refunded_amount_minor"), status: string(row, "status"), })), products: products.map((row) => { const status = string(row, "status"); if (status !== "draft" && status !== "published" && status !== "archived") throw invalid("product status"); return { description: nullableString(row, "description"), id: identifier(row, "id"), name: string(row, "name"), status, variants: variants .filter((variant) => identifier(variant, "product_id") === identifier(row, "id")) .map((variant) => ({ active: boolean(variant, "active"), allowBackorder: boolean(variant, "allow_backorder"), currency: string(variant, "currency"), id: identifier(variant, "id"), name: string(variant, "name"), priceMinor: readSafeNumber(variant, "price_minor"), })), }; }), refunds: refunds.map((row) => { const status = string(row, "status"); if (status !== "pending" && status !== "succeeded" && status !== "failed") throw invalid("refund status"); return { amountMinor: readSafeNumber(row, "amount_minor"), createdAt: string(row, "created_at"), currency: string(row, "currency"), orderReference: required(orderById.get(identifier(row, "order_id")), "refund order"), providerRefundReference: string(row, "provider_refund_reference"), reason: string(row, "reason"), status, }; }), } satisfies AdminDashboard; }, async loadMembership(userId) { const result = await client .from("admin_users") .select("user_id,role,display_name,active") .eq("user_id", userId) .limit(1); const row = rows(result, "membership")[0]; return row === undefined ? null : { active: boolean(row, "active"), displayName: string(row, "display_name"), role: adminRoleSchema.parse(string(row, "role")), userId: string(row, "user_id"), }; }, async loadPayment(providerPaymentReference) { const result = await client .from("payments") .select( "order_id,provider,provider_payment_reference,status,currency,amount_minor,refunded_amount_minor", ) .eq("provider_payment_reference", providerPaymentReference) .limit(1); const payment = rows(result, "payment")[0]; if (payment === undefined) return null; const orderResult = await client .from("orders") .select("reference") .eq("id", identifier(payment, "order_id")) .limit(1); const order = rows(orderResult, "payment order")[0]; if (order === undefined) throw invalid("payment order"); return { amountMinor: readSafeNumber(payment, "amount_minor"), currency: string(payment, "currency"), orderReference: string(order, "reference"), provider: string(payment, "provider"), providerPaymentReference: string(payment, "provider_payment_reference"), refundedAmountMinor: readSafeNumber(payment, "refunded_amount_minor"), status: string(payment, "status"), }; }, async recordRefund(context, command, payment, refund, requestHash) { const result = await client.rpc("salix_admin_record_refund", { p_admin_user_id: context.userId, p_amount_minor: refund.amount.amountMinor, p_currency: refund.amount.currency, p_idempotency_key: command.idempotencyKey, p_provider: refund.provider, p_provider_payment_reference: payment.providerPaymentReference, p_provider_refund_reference: refund.providerRefundReference, p_reason: command.reason, p_request_hash: requestHash, p_status: refund.status, }); const rpc = readRpc(result.data, result.error); return rpc.ok ? { data: { refundRequestId: identifier(rpc.data, "refund_request_id"), replayed: boolean(rpc.data, "replayed"), }, ok: true, } : rpc; }, async transitionOrder(context, orderReference, command, requestHash) { const result = await client.rpc("salix_admin_transition_order", { p_admin_user_id: context.userId, p_idempotency_key: command.idempotencyKey, p_order_reference: orderReference, p_reason: command.reason, p_request_hash: requestHash, p_to_status: command.outcome, p_tracking_carrier: command.trackingCarrier ?? null, p_tracking_number: command.trackingNumber ?? null, }); const rpc = readRpc(result.data, result.error); return rpc.ok ? { data: { replayed: boolean(rpc.data, "replayed"), status: string(rpc.data, "order_status"), }, ok: true, } : rpc; }, async updateProduct(context, productId, command, requestHash) { const result = await client.rpc("salix_admin_update_product", { p_admin_user_id: context.userId, p_description: command.description, p_idempotency_key: command.idempotencyKey, p_name: command.name, p_product_id: productId, p_request_hash: requestHash, p_status: command.status, }); const rpc = readRpc(result.data, result.error); return rpc.ok ? { data: { replayed: boolean(rpc.data, "replayed") }, ok: true } : rpc; }, async updateVariant(context, variantId, command, requestHash) { const result = await client.rpc("salix_admin_update_variant", { p_active: command.active, p_admin_user_id: context.userId, p_allow_backorder: command.allowBackorder, p_idempotency_key: command.idempotencyKey, p_name: command.name, p_price_minor: command.priceMinor, p_request_hash: requestHash, p_variant_id: variantId, }); const rpc = readRpc(result.data, result.error); return rpc.ok ? { data: { replayed: boolean(rpc.data, "replayed") }, ok: true } : rpc; }, } satisfies AdminRepository; return Object.freeze(repository); } function readRpc(data: unknown, error: unknown): AdminResult { if (error !== null) return { error: mapError(error), ok: false }; if (!Array.isArray(data) || data.length !== 1 || !isRow(data[0])) return providerFailure(); return { data: data[0], ok: true }; } function mapError(error: unknown) { const message = isRow(error) && typeof error.message === "string" ? error.message : ""; const known = { SALIX_ADMIN_FORBIDDEN: adminFailure( "FORBIDDEN", "Your role cannot perform this operation.", 403, ), SALIX_ADMIN_UNAUTHORIZED: adminFailure( "UNAUTHENTICATED", "Administrator access is required.", 401, ), SALIX_IDEMPOTENCY_CONFLICT: adminFailure( "IDEMPOTENCY_CONFLICT", "That request key was already used for different input.", 409, ), SALIX_ILLEGAL_ORDER_TRANSITION: adminFailure( "ILLEGAL_ORDER_TRANSITION", "The order cannot move to that state.", 409, ), SALIX_ORDER_NOT_FOUND: adminFailure("NOT_FOUND", "Order not found.", 404), SALIX_PAYMENT_NOT_FOUND: adminFailure("NOT_FOUND", "Payment not found.", 404), SALIX_PRODUCT_NOT_FOUND: adminFailure("NOT_FOUND", "Product not found.", 404), SALIX_VARIANT_NOT_FOUND: adminFailure("NOT_FOUND", "Variant not found.", 404), SALIX_INVENTORY_ITEM_NOT_FOUND: adminFailure("NOT_FOUND", "Inventory item not found.", 404), SALIX_REFUND_EXCEEDS_PAYMENT: adminFailure( "REFUND_EXCEEDS_PAYMENT", "The refund exceeds the captured payment.", 409, ), } as const; if (message in known) return known[message as keyof typeof known]; if ( message.startsWith("SALIX_INVALID_") || message === "SALIX_INVENTORY_UNTRACKED" || message === "SALIX_INVENTORY_BELOW_RESERVED" ) return adminFailure("INVALID_REQUEST", "The administrative request is invalid.", 400); return adminFailure( "PROVIDER_FAILURE", "The administration store could not complete the request.", 500, ); } function rows(result: Readonly<{ data: unknown; error: unknown }>, label: string): Row[] { if (result.error !== null) throw new Error(`Unable to load admin ${label}.`); if (!Array.isArray(result.data) || !result.data.every(isRow)) throw invalid(label); return result.data; } function isRow(value: unknown): value is Row { return typeof value === "object" && value !== null && !Array.isArray(value); } function string(row: Row, key: string): string { const value = row[key]; if (typeof value !== "string") throw invalid(key); return value; } function nullableString(row: Row, key: string): string | null { const value = row[key]; if (value === null) return null; if (typeof value !== "string") throw invalid(key); return value; } function boolean(row: Row, key: string): boolean { const value = row[key]; if (typeof value !== "boolean") throw invalid(key); return value; } function identifier(row: Row, key: string): string { const value = row[key]; if (typeof value === "number" && Number.isSafeInteger(value) && value > 0) return String(value); if (typeof value === "string" && /^[1-9][0-9]*$/u.test(value)) return value; throw invalid(key); } function readSafeNumber(row: Row, key: string): number { const value = row[key]; const parsed = typeof value === "string" && /^-?[0-9]+$/u.test(value) ? Number(value) : value; if (typeof parsed !== "number" || !Number.isSafeInteger(parsed)) throw invalid(key); return parsed; } function required(value: T | undefined, label: string): T { if (value === undefined) throw invalid(label); return value; } function invalid(label: string): TypeError { return new TypeError(`Admin store returned invalid ${label}.`); } function providerFailure(): AdminResult { return { error: adminFailure( "PROVIDER_FAILURE", "The administration store returned an invalid response.", 500, ), ok: false, }; }