57 lines
2.2 KiB
TypeScript
57 lines
2.2 KiB
TypeScript
// The port the crm module's use cases are written against: the platform's CRM service, in this
|
|
// module's own words. adapters/service.ts is the one place that knows `@conusai-sdk/crm` exists, and
|
|
// it turns every refusal into the kit's app errors (`businessAppError` of
|
|
// `@conusai-kit/business`) before core sees it.
|
|
|
|
import { token } from "@conusai-kit/core"
|
|
import type { ContactView, PartyView } from "../contract/index.js"
|
|
|
|
export interface Page<T> {
|
|
readonly rows: T[]
|
|
readonly after?: string
|
|
}
|
|
|
|
/** What a `read` procedure may ask the service: nothing that changes a row. */
|
|
export interface CrmReads {
|
|
/** The immutable app/environment binding UUID for attributed member references. */
|
|
readonly bindingId: string
|
|
listParties(query: { q?: string; after?: string; limit: number }): Promise<Page<PartyView>>
|
|
getParty(partyId: string): Promise<PartyView>
|
|
listContacts(partyId: string, query: { after?: string; limit: number }): Promise<Page<ContactView>>
|
|
}
|
|
|
|
export interface CrmService extends CrmReads {
|
|
createParty(input: {
|
|
kind: "person" | "organization"
|
|
displayName: string
|
|
legalName?: string
|
|
country: string
|
|
identifiers: { scheme: string; value: string }[]
|
|
key: string
|
|
}): Promise<PartyView>
|
|
addContact(input: {
|
|
partyId: string
|
|
kind: "email" | "phone" | "web"
|
|
value: string
|
|
purposes: ContactView["purposes"]
|
|
isPrimary: boolean
|
|
/** `YYYY-MM-DD`: the day the contact point starts to hold. */
|
|
effectiveFrom: string
|
|
key: string
|
|
}): Promise<ContactView>
|
|
}
|
|
|
|
/** The read view a `read` or `write` handler receives: the kind is a capability, not a label. */
|
|
export const crmReadsOf = (service: CrmReads): CrmReads => ({
|
|
bindingId: service.bindingId,
|
|
listParties: (query) => service.listParties(query),
|
|
getParty: (partyId) => service.getParty(partyId),
|
|
listContacts: (partyId, query) => service.listContacts(partyId, query),
|
|
})
|
|
|
|
/**
|
|
* Bound by a composition root or a test that brings its own client (another organization, the
|
|
* business-services fake). With nothing bound, the module calls this deployment's service.
|
|
*/
|
|
export const CRM_SERVICE = token<CrmService>("crm.service", { views: { read: crmReadsOf, write: crmReadsOf } })
|