@frank/crm (0.1.0)
Installation
@frank:registry=npm install @frank/crm@0.1.0"@frank/crm": "0.1.0"About this package
@frank/crm
One Frappe CRM site per customer, driven from a Node server. Ported from Blockwise src/lib/crm unchanged in behaviour: per-site vault credentials, command_id idempotency, the provision state machine with the real ready-probe, and the delivery worker with wait-not-fail semantics. Server-only; nothing here may be imported by a client component.
Public API (src/index.ts)
createWorkspaceCrm- mapping + credential + client + commands for a workspacecreateCrmClient,createCrmCommands- transport and typed command surfaceconfigFromEnv,CrmConfig,CrmNames,defaultCrmNames- configurationloadCrmSiteCredential,upsertCrmSiteCredential,clearCrmSiteCredentialresolveCrmSite,requireCrmSite,isValidCrmSite,crmSiteForSlugprovisionCrmSiteForWorkspace,createVaultCrmSiteProbe,createCrmProvisionTenantProvisioner- the state machineensureLeadCrmDeliveryJob,queueLeadCrmDelivery,executeLeadCrmDeliveryJobById,crmCaptureCommandId,formatLeadCrmDeliveryCrmErrorand helpers, domain types (CrmLead, stages, tasks)
Config
configFromEnv(env, names) is the only env reader: base URL (the CRM backend,
never an nginx frontend), timeout, vault key, delivery kill switch. Table,
queue-kind, RPC and Frappe-namespace names are a CrmNames parameter;
defaultCrmNames holds the Blockwise values. Queue helpers take the product's
job-queue enqueue as a parameter; this package owns no queue. Tests run with
npm run test: node --test, no network or database.
Usage
const crm = await createWorkspaceCrm({ supabase, serviceSupabase, workspaceId, config });
await crm.commands.captureEnquiry({
commandId: `crm-capture:${lead.source}:${lead.submissionId}`, // replay-safe
sourceProvider: lead.source,
sourceSubmissionId: lead.submissionId,
});
Dependencies
Dependencies
| ID | Version |
|---|---|
| @supabase/supabase-js | ^2.49.8 |
Development dependencies
| ID | Version |
|---|---|
| @types/node | ^22.0.0 |