@cresenity/cresjs-error-collector
v0.1.0
Published
Browser/React error collector for CF (Cresenity Framework) apps - reports to devcloud's Exception Collector via POST /cresenity/jsError. Used by cres.js itself and by every app's React SPA.
Readme
cresjs-error-collector
Browser/React error collector for CF (Cresenity Framework) apps. Reports uncaught JS errors, unhandled promise rejections, and caught React render errors directly to devcloud — cross- origin, no backend relay — landing in the same Exception Collector PHP exceptions already use.
How it talks to devcloud
The browser POSTs straight to devcloud's v1/jsExceptions endpoint (CORS-open), authenticated
with a query-string key — not a header, since navigator.sendBeacon() (the primary transport
here, so a report still goes out even if the page is closing) can't set custom headers at all.
That key is app.js_ingest_key from devcloud (Manager → Project → App → "JS Ingest Key") — a
low-privilege, per-app token deliberately safe to expose in page source, the same way a Sentry
DSN's public key is. It can only submit JS error reports through this one endpoint; it is not
app.api_key/secret_key (those stay server-side, used by devcloud's APM trace ingestion and
other server-to-server calls).
Never hardcode the devcloud endpoint URL or the key in your app's source. Both come from server-side config injected into the page at render time — see "Wiring it into a page" below.
Install
Not published to a private registry — public on npm under the @cresenity scope:
npm install @cresenity/cresjs-error-collectorUsage
Vanilla (any page, framework-agnostic)
import { initJsErrorCollector } from '@cresenity/cresjs-error-collector';
initJsErrorCollector();Attaches window.onerror/unhandledrejection listeners. Reads window.__CF_JS_COLLECTOR_CONFIG__
({ endpoint, key } | null) by default — no-ops entirely (not even attaching the listeners) when
that's missing. Pass { endpoint, key } directly to createCollector() instead if your host page
doesn't go through that injection point.
React
import { CresjsErrorBoundary } from '@cresenity/cresjs-error-collector/react';
<CresjsErrorBoundary>
<App />
</CresjsErrorBoundary>React never lets a render/lifecycle/hook error bubble to window.onerror once a boundary exists
above it — CresjsErrorBoundary is that boundary, reporting via the same mechanism. Errors outside
React's render cycle (event handlers, timers, unhandled promise rejections) still need the vanilla
initJsErrorCollector() call too — the two cover different failure modes, use both.
Pass fallback (node, or (error, reset) => node) for a custom crash UI instead of the built-in
one, and onError for an extra side effect (toast, local logging) alongside the report.
Wiring it into a page (CF-specific)
Something server-side has to set window.__CF_JS_COLLECTOR_CONFIG__ before this package's code
runs, reading devcloud.jsCollector.url / devcloud.jsCollector.key (system/config/devcloud.php
in the CF monorepo — both env-driven, no hardcoded defaults):
<script>
window.__CF_JS_COLLECTOR_CONFIG__ = { endpoint: "...", key: "..." };
</script>CApp's RendererTrait already does this for every classic CF page automatically. A standalone
SPA shell (one that bypasses CApp::renderScripts() entirely, e.g. a bare <!DOCTYPE html> blade)
needs the same snippet added by hand — see application/devcloud/default/views/page/
home-console.blade.php for the reference.
Build
npm install
npm run build # tsup -> dist/ (esm+cjs+d.ts, two entries: index, react)
npm run typechecknpm install from a git URL runs the prepare script automatically, so consumers get a built
dist/ without needing to run npm run build themselves.
