// What the crm module does, as pure TypeScript over the port in ports.ts. // // Parties belong to the credential-bound app tenant and environment. Projects within // that partition share its address book. Linked people use the actual resolved // app member reference; another app tenant or environment has a different binding. import type { ProjectScope } from "@conusai-kit/core" import { type ContactView, PAGE_LIMIT, type PartyView } from "../contract/index.js" import { type ContactActionInput, contactActionData, type PartyActionInput, partyActionData } from "./action-plan.js" import type { CrmReads, CrmService, Page } from "./ports.js" export function listParties( reads: CrmReads, query: { q?: string; after?: string; limit?: number }, ): Promise> { const q = query.q?.trim() return reads.listParties({ ...(q ? { q } : {}), ...(query.after === undefined ? {} : { after: query.after }), limit: query.limit ?? PAGE_LIMIT, }) } export async function getParty( reads: CrmReads, partyId: string, ): Promise<{ party: PartyView; contacts: ContactView[] }> { const party = await reads.getParty(partyId) const contacts = await reads.listContacts(partyId, { limit: PAGE_LIMIT }) return { party, contacts: contacts.rows } } export async function createParty( service: CrmService, scope: ProjectScope, input: PartyActionInput, ): Promise { return service.createParty(partyActionData(scope, service.bindingId, input)) } export function addContact( service: CrmService, scope: ProjectScope, input: ContactActionInput, now: Date = new Date(), ): Promise { return service.addContact(contactActionData(scope, input, now)) }