@jsjackson/better
v0.1.0
Published
Better SDK for JavaScript and TypeScript
Readme
@jsjackson/better
@jsjackson/better sends native Better events from JavaScript and TypeScript applications.
The package has a shared client and explicit entry points for browsers and Node.js.
Browser
import { createBetterWebClient } from '@jsjackson/better/web';
const better = createBetterWebClient({
endpoint: 'https://better.example',
projectId: 'project-id',
apiKey: 'better-project-key',
});
await better.capture('checkout_completed');The browser client uses localStorage when it is available. It sets the default
platform to web and retains failed events across page loads.
Node.js
import { createBetterNodeClient } from '@jsjackson/better/node';
const better = createBetterNodeClient({
endpoint: 'https://better.example',
projectId: 'project-id',
apiKey: 'better-project-key',
storagePath: '.better/events.json',
});
await better.capture('job_completed');
await better.shutdown();The Node.js client sets the default platform to node. storagePath adds an
optional disk-backed retry queue. The file has mode 0600 on systems that
support POSIX file modes. Call shutdown() before a process or serverless
invocation stops.
Process error capture is explicit:
import { createBetterNodeClient, installNodeErrorHandlers } from '@jsjackson/better/node';
const better = createBetterNodeClient({ endpoint, projectId, apiKey });
const removeHandlers = installNodeErrorHandlers(better);The default handler uses Node's uncaughtExceptionMonitor event. It observes
an uncaught exception without changing the default exit behavior. Unhandled
rejection capture is disabled by default because its listener changes Node's
default rejection behavior.
Shared behavior
All entry points use the better.event/1 envelope. The client supports events,
errors, logs, replay references, feedback, and flag exposures. It also provides
bounded queues, retries with jitter, privacy filtering, identity, sessions, and
correlation context.
Privacy defaults
Better collects nothing automatically: applications explicitly choose every event and payload. Before buffering or transport, fields named like email, phone, IP address, password, token, cookie, authorization, or API key are redacted. Embedded email addresses, bearer tokens, and private keys are also redacted.
Use identify() only with an opaque internal ID—not an email, phone number, name, or
other direct identifier. PII-like identifiers are rejected before persistence. Error
messages and stacks are omitted by default because they commonly contain user input,
URLs, and local paths. Set captureErrorDetails: true only after reviewing your error
content and privacy requirements.
Free-form log messages, feedback, replay payloads, and custom event values can still
contain personal data the SDK cannot reliably recognize. Do not send raw customer
content. Use privacy.denyFields and privacy.maskFields for application-specific
fields, obtain any required consent, and keep data retention scoped to your purpose.
