Rocky_Mountain_Vending/lib/convex.ts

76 lines
1.8 KiB
TypeScript

export type LeadSyncStatus = "pending" | "sent" | "synced" | "failed" | "skipped";
export type IngestLeadInput = {
host: string;
tenantSlug?: string;
tenantName?: string;
tenantDomains?: string[];
source?: string;
idempotencyKey: string;
name: string;
email: string;
company?: string;
service?: string;
message: string;
};
export type IngestLeadResult = {
inserted: boolean;
leadId: string;
idempotencyKey: string;
tenantId: string;
};
function getConvexUrl() {
return (process.env.CONVEX_URL || process.env.NEXT_PUBLIC_CONVEX_URL || "").replace(
/\/+$/,
""
);
}
async function callConvex(path: string, args: Record<string, unknown>) {
const convexUrl = getConvexUrl();
if (!convexUrl) {
throw new Error("CONVEX_URL is not configured");
}
const endpoint = `${convexUrl}/api/mutation`;
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
cache: "no-store",
body: JSON.stringify({
path,
args,
format: "json",
}),
});
const body = await response.json().catch(() => null);
if (!response.ok || body?.status === "error") {
const message = body?.errorMessage || `Convex call failed (${response.status})`;
throw new Error(message);
}
return body?.value;
}
export function isConvexConfigured() {
return getConvexUrl().length > 0;
}
export async function ingestLead(input: IngestLeadInput): Promise<IngestLeadResult> {
const value = await callConvex("leads:ingestLead", input);
return value as IngestLeadResult;
}
export async function updateLeadSyncStatus(input: {
leadId: string;
usesendStatus?: LeadSyncStatus;
ghlStatus?: LeadSyncStatus;
error?: string;
}) {
return await callConvex("leads:updateLeadSyncStatus", input);
}