Better Helpdesk
Reference

Package exports

Each entry point of the better-helpdesk package and what it exports.

The better-helpdesk package has eight entry points. Related guide: Call the helpdesk from your own code.

Entry pointRuns onExports
better-helpdeskServerbuildHelpdesk, postgresAdapter, identity tokens, references, types
better-helpdesk/adaptersServerThe database adapters, the adapter contract and migrate
better-helpdesk/testingTestsrunAdapterTests, the checks an adapter of your own must pass
better-helpdesk/widgetBrowserThe widget and the support page, for React and as custom elements
better-helpdesk/adminBrowserThe agent UI
better-helpdesk/richServer or browserThe message format: parser and renderer
better-helpdesk/nextBuildwithHelpdesk for next.config
better-helpdesk/widget.jsBrowserThe standalone widget script

The package is ESM only and ships its type declarations. Its peer dependencies are react and react-dom (React 19) and the driver of the host's database, which only a host on that database installs: pg for Postgres, mysql2 3.24 or newer for MySQL, tedious 20 and tarn 3 for SQL Server, and none for SQLite; it requires Node.js 22.19 or newer.

better-helpdesk

ExportKindWhat it is
buildHelpdesk(config)functionBuilds the helpdesk from a HelpdeskConfig. Throws on invalid configuration.
postgresAdapter({ pool })functionThe DatabaseAdapter over a pg.Pool, for the db option.
mysqlAdapter({ pool })functionThe DatabaseAdapter over the host's mysql2 pool, MySQL 8.4 or newer. The pool must be created with timezone: 'Z'; the adapter refuses one that converts times in another zone.
mssqlAdapter(config)functionThe DatabaseAdapter over SQL Server 2022 or newer. config is what Kysely's MssqlDialect takes: the host's tedious and tarn modules and its connection.
sqliteAdapter({ database })functionThe DatabaseAdapter over a SQLite database the host opened, from node:sqlite or better-sqlite3. It turns foreign keys on and refuses to start if they stay off.
kyselyAdapter({ dialect, family })functionA built-in adapter over any Kysely dialect of a family Better Helpdesk knows. postgresAdapter is this with Kysely's PostgresDialect.
migrate(adapter)functionApplies the migrations through a built-in adapter, as better-helpdesk-migrate does; returns the names of the ones it applied.
createAdapter(input)functionTurns an AdapterInput, the contract a custom adapter implements, into a DatabaseAdapter: it sets ids and defaults and converts values to and from what the input supports.
memoryRealtime()functionA RealtimeAdapter for the realtime option that reaches the event streams of one process.
postgresRealtime({ pool, retryMs? })functionA RealtimeAdapter over Postgres LISTEN and NOTIFY on the host's pg.Pool, so a stream on one process hears a change made on another. It holds one pooled connection while anyone is subscribed.
createStore(adapter, options?)functionThe HelpdeskStore over an adapter, for code that runs without buildHelpdesk. Without options.slaClock, the targets buildHelpdesk derives from sla, the store starts no deadlines.
exportConversations(store, { prefix, since? })functionAn async iterator over every conversation in the export format, as better-helpdesk-export writes it.
importConversations(store, lines, options?)functionReads lines of that format, as better-helpdesk-import conversations does; returns the same report as the other imports.
helpdeskModelobjectEvery table and field, with its kind, whether it may be null, its default and its references.
signIdentityToken(payload, secret, options?)functionSigns an identity token.
verifyIdentityToken(token, secret)functionReturns the Identity a token vouches for, with isAgent: false, or null when it is forged, malformed or expired.
formatReference(prefix, number)functionformatReference('ACME', 1042) is ACME-1042.
parseReference(prefix, value)functionThe number in a reference such as ACME-1042, matched case-insensitively, or undefined.
ipBucket(ip)functionThe key the rate limits count a client address under: an IPv4 address as it is, an IPv6 address by its /64, since one host owns the whole block. For host code that limits or groups visitors the way the helpdesk does.
HelpdeskErrorclassAn error with an HTTP status and, for a bulk change, the failed ids. The handler answers it with that status.
BuiltHelpdesktypeWhat buildHelpdesk returns.
Conversation, MessagetypeRows of conversation and message.
HelpdeskStoretypeThe query layer, buildHelpdesk(...).store.
DatabaseAdapter, AdapterInput, Capabilities, Where, OrderBy, FindQuery, NotificationtypeThe adapter contract.
HelpdeskEventtypeSee Events.
SlaClock, SlaClockFor, SlaTargetNametypeThe targets a conversation runs under, as createStore takes them.
RealtimeAdapter, RealtimeChangetypeWhat the realtime option takes, and the change it carries.
IdentityClaimstypeThe claims of an identity token.

Every type in the configuration module is exported as well: HelpdeskConfig, InboxConfig, BusinessHours, Identity, HelpdeskUser, HelpdeskOrg, HostLink, LinkContact, LinkCompany, HelpdeskEmail, StorageAdapter, AiAdapter, CaptchaAdapter, AiFeature, AiSettings, HelpResult, InboundMessage, CustomFieldDef, Locale, Translated, Priority, SlaConfig, SlaPolicy, SlaTarget, SlaDuration, TierInput and ResolvedConfig. The default lists, such as the statuses and the default types, are not exported.

What buildHelpdesk returns

Prop

Type

JobsReport stands for { woken, reminders, retention, jobs, failed, errors }, described under Jobs; it is not an exported name. The object also carries the internal functions the handler is built from, which are not listed here.

HelpdeskStore

helpdesk.store holds the queries the routes run, over the helpdesk schema. These are the ones the guides use. Rows use the column names of Database in camel case.

Prop

Type

Contact, Agent and Activity are the stored rows; only Conversation and Message are exported as type names.

signIdentityToken

signIdentityToken(
  payload: Omit<IdentityClaims, 'exp'>,
  secret: string,
  options?: { expiresInSeconds?: number } // default 3600
): string

The claims of the token:

Prop

Type

The token is an HS256 JWT, so any JWT library that signs the same claims produces a valid one.

better-helpdesk/adapters

What a host needs to pick or write a database adapter, without the rest of the server: postgresAdapter, mysqlAdapter, mssqlAdapter, sqliteAdapter, kyselyAdapter, createAdapter, migrate and helpdeskModel, with the contract's types, and the realtime adapters memoryRealtime and postgresRealtime. The same names are exported from better-helpdesk. None of them imports a database driver: the host passes its own connection.

better-helpdesk/testing

runAdapterTests({ name?, adapter, reset }) registers vitest tests that hold an adapter to the contract the store relies on: every kind of value read back as written, NULL compared as SQL does, exact text unless insensitive, search characters taken literally, NULLs ordered where asked, times and numbers compared and ordered by value, paging and selected fields, conditions through another table, counted updates and in-place increments, one winner of simultaneous compare-and-swap updates, a row read for update held until its transaction ends, whole transactions, a repeated primary key refused, and the partial verified-identity key held. adapter returns the adapter (an AdapterInput or a DatabaseAdapter) over a database that has the tables of helpdeskModel; reset empties them before each test. vitest 4 or 5 is an optional peer dependency, needed only here. examples/adapters/database-memory.ts, an adapter that keeps everything in memory, passes it, and the built-in adapters run it in the integration suite.

better-helpdesk/widget

HelpdeskWidget, HelpdeskConversations, defineHelpdeskWidget and defineHelpdeskConversations. See Widget.

better-helpdesk/admin

HelpdeskAdmin, HELPDESK_SECTIONS and HELPDESK_CHANGED. See Agent UI.

better-helpdesk/rich

The message format that messages and canned replies are written in, and a renderer for it. The module has no hooks and no 'use client', so it renders on the server as well, for example in an email template.

The format is plain text with a small set of Markdown: **bold**, _italic_, ++underline++, [label](url), bare http and https links, lists whose lines start with -, * or •, or with a number and . or ), blank lines between paragraphs, and code blocks between lines of three or more backticks.

ExportSignatureWhat it does
RichText(props: { text: string; compact?: boolean; hosts?: boolean; code?: (text: string) => ReactNode; reference?: (reference: string) => ReactNode }) => ReactNodeRenders a message. compact renders inline only, with lists as • lines. hosts shows where each labeled link goes. code renders code blocks. reference renders each conversation reference outside links and code.
parseRich(text: string) => Block[]Parses a message into paragraphs, lists and code blocks.
parseInline(text: string) => Inline[]Parses one line into text, bold, italic, underline and link runs.
plainText(text: string) => stringThe words without the markers.
safeHref(href: string) => string | nullThe target when it starts with http://, https:// or mailto:, otherwise null.
unlabelLinks(text: string) => stringRewrites [label](url) as label (url).
fence(text: string) => stringWraps text in a code block whose backtick lines are longer than any run inside it.
Block, InlinetypeThe parsed shapes.

better-helpdesk/next

next.config.mjs
import { withHelpdesk } from 'better-helpdesk/next';

export default withHelpdesk({ trailingSlash: true });

withHelpdesk(nextConfig = {}) returns the config with better-helpdesk added to transpilePackages, keeping any packages already listed.

better-helpdesk/widget.js

The minified standalone widget, the file dist/widget.js, for a page without React. See Script tag.

better-helpdesk/package.json is exported too.

On this page