@clueline/core
v0.2.0
Published
Framework-agnostic core for the Clueline SDK: payload shaping, transport, retry, and redaction.
Readme
@clueline/core
Framework-agnostic core for the Clueline SDK: payload shaping, transport with bounded retries, and best-effort PII redaction.
Not for direct install. End users install a framework package such as
@clueline/react, which depends on this. This package is documented here for SDK authors.
Design guarantees
- Never crashes the host app.
capture()andreportError()shape and send an event and always resolve to aSendResult— they never throw or reject (PRD §7). - Redaction on by default. Common PII (emails, card-like numbers) is masked client-side before transport, on every string in the payload. Set
redact: falseto opt out, or add extra rules on top withsanitize. - Bounded retries. Transient failures (429/5xx/network) retry with exponential backoff up to
maxRetries(default 3).
Usage (SDK authors)
import { createClient } from "@clueline/core";
const client = createClient({ apiKey: "clue_live_..." });
await client.capture({
name: "TypeError",
message: "Cannot read properties of undefined",
stack: err.stack,
source: "manual",
timestamp: new Date().toISOString(),
userNote: "I clicked Save on the invoice",
});Framework packages (@clueline/react, @clueline/next) build on CluelineClient rather than reimplementing shaping/redaction/classification: they call client.capture() / client.reportError() / client.identify() directly, and share the errorFromValue() / baseEventFromError() normalizers this package exports for turning a caught value into an event.
Config
| Option | Default | Description |
|---|---|---|
| apiKey | — (required) | Project API key. |
| apiEndpoint | hosted ingest URL | Ingestion API base URL. Override for self-hosted/proxied setups. |
| release | — | App version, attached to every event. |
| environment | "production" | Current environment, attached to every event. |
| maxRetries | 3 | Transport retry attempts on transient failure. |
| redact | true | Mask common PII before transport. |
| sanitize | — | (text: string) => string. Extra redaction rules applied on top of the built-in PII scrubber (additive, not a replacement). |
| userId | — | Optional user identifier attached to reports. |
| sessionId | generated | Optional session identifier attached to reports. |
| onError | — | (report) => void, called with the full report whenever an error is captured. A throwing callback is caught and ignored. |
| enabled | true | Set false to drop events (dev/test). |
Manual reporting, identity, and classification
// Report a caught error that didn't crash the app, tagged with what happened:
await client.reportError(error, { action: "checkout" }, "payment_integration");
// Attach a known user's identity once you have it (e.g. right after login):
client.identify({ email: user.email, name: user.name });errorType ('api_error' | 'network_timeout' | 'payment_integration' | 'render_crash' | 'component_crash' | 'unhandled_rejection' | 'global_error' | 'generic') is inferred from the capture source when not given (defaultErrorType()), so this is only needed when reporting manually with more specific knowledge than the source alone provides.
Scripts
npm run build -w @clueline/core # tsup → dist (ESM + CJS + d.ts)
npm test -w @clueline/core # vitest
npm run typecheck -w @clueline/core # tsc --noEmit