Connector examples
Everything on this page comes from the pasted product sources. Nothing here is illustrative. It is the adapter boundary, quoted.
Copy-paste factory (adapter boundary, from source)
Section titled “Copy-paste factory (adapter boundary, from source)”import type { ConnectorProviderFactory } from '@/lib/integrations/crm-sync';
export const createProvider: ConnectorProviderFactory = async (context) => { const client = await createTenantClient(context); return { label: 'Provider name', objects: () => client.listSupportedObjects(), properties: (objectKey) => client.listProperties(objectKey), records: (objectKey, properties, after) => client.listRecordPage({ objectKey, properties, after }), };};Notes from source:
- The factory receives a context and builds a refreshed tenant/connection-scoped client (
createTenantClienthere stands for whatever client constructor your adapter uses, same shape, your tenant scoping). - Three operations, no more at the boundary:
objects(),properties(objectKey),records(objectKey, properties, after). - The runtime, store, writer, and UI are shared. The adapter never reimplements them.
Run it (from source)
Section titled “Run it (from source)”await syncConnectorObjectMappings({ orgId, connectionId, packageKey });- Call from an authorized runner (new Inngest function via function-catalog, never
connector-sync-runner). - Watermark advances only when
failed === 0. - Persist via
upsertConnectorCrmRecord(inbound writer path), and never exposeapplyConnectorMappedRecordunauthenticated.
Destination example (from source)
Section titled “Destination example (from source)”Valid destination shape per target-catalog.ts:
targetObject: 'work-items' + workItemTypeIdRetired and forbidden: tasks / deliverables.
Adapter contract tests (from source)
Section titled “Adapter contract tests (from source)”Every adapter proves, in order:
- Create: new source records arrive as mapped records.
- Update: changed source records update via the upsert path.
- Retry: a failed run re-runs from the held watermark (no loss, no duplication, no skip).
- Pause: pausing stops scheduling cleanly; resume continues correctly.
What these examples assume you already did
Section titled “What these examples assume you already did”- Package registered with
mappingTemplate: 'crm'(Build step 1). - Factory registered in
crm-sync/provider.ts(Build step 3). - Bindings in install
settings.object_mappingsfor the target org, package, and connection; identitybinding:<uuid>inai.connector_object_map. - Auth wired per the tenant contract (canonical host callbacks, HMAC state, allowlisted path, vaulted secrets).
Test-story mechanics beyond the four contract tests (runners, fixtures, CI placement): not in pasted sources.
Next: Worked example: HubSpot e2e import runs this skeleton end to end (registry, package, factory, bindings, authorized sync, contract tests) against the HubSpot registered adapter.

