Rocky_Mountain_Vending/lib/convex.ts

99 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)
}