90 lines
2.1 KiB
TypeScript
90 lines
2.1 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;
|
|
firstName?: string;
|
|
lastName?: string;
|
|
email: string;
|
|
phone: string;
|
|
company?: string;
|
|
service?: string;
|
|
intent?: string;
|
|
page?: string;
|
|
url?: string;
|
|
message: string;
|
|
employeeCount?: string;
|
|
machineType?: string;
|
|
machineCount?: string;
|
|
serviceTextConsent?: boolean;
|
|
marketingTextConsent?: boolean;
|
|
consentVersion?: string;
|
|
consentCapturedAt?: string;
|
|
consentSourcePage?: 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);
|
|
}
|