@alphacharts/report 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alphabench
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,56 @@
1
- # Temporary Holding Version
1
+ # @alphacharts/report
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Opt-in, anonymous crash reports for alphacharts. **Off by default.** Importing this package does nothing: no
4
+ listener, no timer, no network, no global `window.onerror` or `unhandledrejection` handler. Reporting starts only
5
+ when you call `enableCrashReporting()` with the endpoint and key of **your own** PostHog project. There is no
6
+ default server: without both, it throws and sends nothing.
7
+
8
+ ```ts
9
+ import { enableCrashReporting } from "@alphacharts/report";
10
+
11
+ const disable = enableCrashReporting({
12
+ endpoint: "https://your-posthog.example/batch", // required; full URL, used exactly as given: no path is appended
13
+ key: "phc_...", // required; that project's public capture key
14
+ maxReports: 5, // optional; per page load (default 5)
15
+ });
16
+ // disable() stops it.
17
+ ```
18
+
19
+ It reports faults the core catches at its own entry points: the shared draw loop, the chart constructor, WebGL
20
+ context loss and restore, and shader compile or link failures. To also report errors your code already receives:
21
+
22
+ ```ts
23
+ import { errorForwarder, plotErrorForwarder } from "@alphacharts/report";
24
+
25
+ plot.on("error", plotErrorForwarder());
26
+ new DrawingsPlugin({ onError: errorForwarder("drawings", (e) => console.error(e)) });
27
+ new AlertsPlugin({ onError: errorForwarder("alerts") });
28
+ // datafeed: { onError: errorForwarder("feed") }
29
+ ```
30
+
31
+ A forwarder reads only its first argument. The drawing object that `DrawingsOptions.onError` passes second is never
32
+ read. The optional callback you pass receives the error only, so keep your own handler if you need the drawing.
33
+
34
+ ## What is sent
35
+
36
+ One PostHog `$exception` event, `POST` as `text/plain` JSON by `navigator.sendBeacon`, else `fetch` with `keepalive`.
37
+ Failures are ignored. Per page load: the same fault is sent once and at most `maxReports` are sent.
38
+
39
+ | Field | Value |
40
+ |---|---|
41
+ | `distinct_id` | random UUID, new on every page load, never stored |
42
+ | `project` | `alphacharts` |
43
+ | `version`, `report_version` | the `@alphacharts/core` version that faulted; this package's version |
44
+ | `error_type` | the error's class name (`TypeError`), or `NonError` / `None` |
45
+ | `source` | `draw-loop`, `ctor`, `context-lost`, `shader`, `plot`, `drawings`, `alerts`, `feed` |
46
+ | `renderer` | `webgl` or `canvas2d`, when known |
47
+ | `webgl2`, `context_lost` | booleans |
48
+ | `browser`, `os` | family and major version (`Chrome 126`), OS family |
49
+ | `$exception_list` | one entry: the error type and the fixed label `alphacharts fault: <source>`. No message, no stack frames, no file names |
50
+ | `$process_person_profile`, `$geoip_disable` | `false`, `true` |
51
+
52
+ Never sent: error messages, option, data, series, plugin or marker ids, symbols, prices, GPU vendor strings, page URL,
53
+ cookies or any stored id. Your server still sees the sender's IP address; turn on your project's "discard client IP
54
+ data" setting.
55
+
56
+ MIT licence.
package/dist/index.js ADDED
@@ -0,0 +1,116 @@
1
+ import { CORE_VERSION as e, onFault as t } from "@alphacharts/core/internal";
2
+ //#region src/index.ts
3
+ var n = "0.1.0", r = /* @__PURE__ */ new Set([
4
+ "draw-loop",
5
+ "ctor",
6
+ "context-lost",
7
+ "shader",
8
+ "plot",
9
+ "drawings",
10
+ "alerts",
11
+ "feed"
12
+ ]), i = null, a = null, o = "";
13
+ function s(e) {
14
+ let n = e?.endpoint, o = e?.key;
15
+ if (typeof n != "string" || n === "") throw TypeError("alphacharts report: endpoint is required (the full URL of your PostHog capture endpoint)");
16
+ if (typeof o != "string" || o === "") throw TypeError("alphacharts report: key is required (your PostHog project's public capture key)");
17
+ a?.();
18
+ let s = Math.max(0, Math.floor(e.maxReports ?? 5)), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new WeakSet(), u = 0, f = !1, p = { report(e, t, i) {
19
+ try {
20
+ if (t === "context-restored") {
21
+ f = !1;
22
+ return;
23
+ }
24
+ if (!r.has(t)) return;
25
+ if (typeof e == "object" && e) {
26
+ if (l.has(e)) return;
27
+ l.add(e);
28
+ }
29
+ t === "context-lost" && (f = !0);
30
+ let a = d(e, t, i, f), p = `${t}|${a.error_type}`;
31
+ if (c.has(p) || u >= s) return;
32
+ c.add(p), u++, h(n, o, a);
33
+ } catch {}
34
+ } };
35
+ i = p;
36
+ let m = t((e) => p.report(e.error, e.source, e.renderer)), g = () => {
37
+ m(), i === p && (i = null), a === g && (a = null);
38
+ };
39
+ return a = g, g;
40
+ }
41
+ function c(e, t) {
42
+ i?.report(e, t);
43
+ }
44
+ function l(e, t) {
45
+ return (n) => {
46
+ c(n, e), t?.(n);
47
+ };
48
+ }
49
+ function u(e) {
50
+ return (t) => {
51
+ c(t.error, "plot"), e?.(t);
52
+ };
53
+ }
54
+ function d(t, r, i, a) {
55
+ let o = f(t), { browser: s, os: c } = p(), l = {
56
+ project: "alphacharts",
57
+ version: e,
58
+ report_version: n,
59
+ error_type: o,
60
+ source: r,
61
+ webgl2: typeof WebGL2RenderingContext < "u",
62
+ context_lost: a,
63
+ browser: s,
64
+ os: c,
65
+ $exception_list: [{
66
+ type: o,
67
+ value: `alphacharts fault: ${r}`
68
+ }],
69
+ $process_person_profile: !1,
70
+ $geoip_disable: !0
71
+ };
72
+ return i && (l.renderer = i), l;
73
+ }
74
+ function f(e) {
75
+ let t = typeof e == "object" && e ? e.name : void 0;
76
+ return typeof t == "string" && /^[A-Za-z][A-Za-z0-9_]{0,39}$/.test(t) ? t : e === void 0 ? "None" : e instanceof Error ? "Error" : "NonError";
77
+ }
78
+ function p() {
79
+ let e = typeof navigator < "u" && typeof navigator.userAgent == "string" ? navigator.userAgent : "", t = (t, n) => {
80
+ let r = t.exec(e);
81
+ return r ? `${n} ${r[1]}` : null;
82
+ };
83
+ return {
84
+ browser: t(/Edg\/(\d+)/, "Edge") ?? t(/OPR\/(\d+)/, "Opera") ?? t(/(?:Firefox|FxiOS)\/(\d+)/, "Firefox") ?? t(/(?:Chrome|CriOS)\/(\d+)/, "Chrome") ?? t(/Version\/(\d+)[^]*Safari/, "Safari") ?? "other",
85
+ os: /Windows/.test(e) ? "Windows" : /Android/.test(e) ? "Android" : /iPhone|iPad|iPod/.test(e) ? "iOS" : /Mac OS X|Macintosh/.test(e) ? "macOS" : /CrOS/.test(e) ? "ChromeOS" : /Linux/.test(e) ? "Linux" : "other"
86
+ };
87
+ }
88
+ function m() {
89
+ if (o) return o;
90
+ let e = globalThis.crypto;
91
+ return o = e?.randomUUID ? e.randomUUID() : Array.from({ length: 4 }, () => Math.random().toString(16).slice(2, 10).padEnd(8, "0")).join("-"), o;
92
+ }
93
+ function h(e, t, n) {
94
+ try {
95
+ let r = JSON.stringify({
96
+ api_key: t,
97
+ batch: [{
98
+ event: "$exception",
99
+ distinct_id: m(),
100
+ properties: n
101
+ }]
102
+ }), i = typeof navigator < "u" ? navigator : void 0;
103
+ if (i && typeof i.sendBeacon == "function" && i.sendBeacon(e, new Blob([r], { type: "text/plain" }))) return;
104
+ typeof fetch == "function" && fetch(e, {
105
+ method: "POST",
106
+ body: r,
107
+ keepalive: !0,
108
+ credentials: "omit",
109
+ headers: { "content-type": "text/plain" }
110
+ }).catch(() => {});
111
+ } catch {}
112
+ }
113
+ //#endregion
114
+ export { n as VERSION, s as enableCrashReporting, l as errorForwarder, u as plotErrorForwarder, c as reportError };
115
+
116
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["VERSION","SOURCES","active","stop","pageId","enableCrashReporting","endpoint","options","key","cap","seenKeys","seenErrors","sent","contextLost","self","source","error","props","properties","renderer","dedupeKey","send","off","onFault","f","disable","reportError","errorForwarder","next","plotErrorForwarder","e","errorType","nameOf","agent","CORE_VERSION","n","ua","pick","m","re","name","uuid","c","body","nav"],"sources":["../src/index.ts"],"sourcesContent":["// Opt-in, anonymous crash reports. Nothing happens at import: no listener, no\n// timer, no network. enableCrashReporting() subscribes to the core's fault\n// emitter and sends a fixed set of fields to the endpoint the host names. There is no default endpoint.\n//\n// Never sent: error messages, option/data/series/plugin/marker ids, symbols,\n// prices, GPU strings, stack text, file names. No global\n// window.onerror / unhandledrejection handler is installed.\n\nimport { CORE_VERSION, onFault, type Fault } from \"@alphacharts/core/internal\";\n\nexport const VERSION = \"0.1.0\";\n\nexport type ReportSource = Fault[\"source\"] | \"plot\" | \"drawings\" | \"alerts\" | \"feed\";\n\nexport interface CrashReportingOptions {\n /** Full URL that accepts a PostHog capture batch (POST); no path is appended. Required: there is no default. */\n endpoint: string;\n /** The project's public capture key (it can only write events). Required. */\n key: string;\n /** Most reports sent per page load (default 5). */\n maxReports?: number | undefined;\n}\n\nconst SOURCES: ReadonlySet<string> = new Set([\"draw-loop\", \"ctor\", \"context-lost\", \"shader\", \"plot\", \"drawings\", \"alerts\", \"feed\"]);\n\ninterface Active {\n report(error: unknown, source: ReportSource, renderer?: \"webgl\" | \"canvas2d\"): void;\n}\nlet active: Active | null = null;\nlet stop: (() => void) | null = null;\nlet pageId = \"\";\n\n/** Start reporting. Returns the function that stops it. A missing, empty or non-string endpoint or key throws: nothing is sent unless the host names where. */\nexport function enableCrashReporting(options: CrashReportingOptions): () => void {\n const endpoint = options?.endpoint;\n const key = options?.key;\n if (typeof endpoint !== \"string\" || endpoint === \"\") throw new TypeError(\"alphacharts report: endpoint is required (the full URL of your PostHog capture endpoint)\");\n if (typeof key !== \"string\" || key === \"\") throw new TypeError(\"alphacharts report: key is required (your PostHog project's public capture key)\");\n stop?.(); // a second call replaces the first\n const cap = Math.max(0, Math.floor(options.maxReports ?? 5));\n const seenKeys = new Set<string>();\n const seenErrors = new WeakSet<object>();\n let sent = 0;\n let contextLost = false;\n\n const self: Active = {\n report(error, source, renderer) {\n try {\n if (source === \"context-restored\") {\n contextLost = false; // a recovery, not a fault: tracked, never sent\n return;\n }\n if (!SOURCES.has(source)) return;\n // One failure can reach two entry points (a shader error inside a frame).\n if (typeof error === \"object\" && error !== null) {\n if (seenErrors.has(error)) return;\n seenErrors.add(error);\n }\n if (source === \"context-lost\") contextLost = true;\n const props = properties(error, source, renderer, contextLost);\n const dedupeKey = `${source}|${props.error_type}`;\n if (seenKeys.has(dedupeKey) || sent >= cap) return;\n seenKeys.add(dedupeKey);\n sent++;\n send(endpoint, key, props);\n } catch {\n // reporting must never change what the page does\n }\n },\n };\n active = self;\n const off = onFault((f) => self.report(f.error, f.source, f.renderer));\n const disable = (): void => {\n off();\n if (active === self) active = null;\n if (stop === disable) stop = null;\n };\n stop = disable;\n return disable;\n}\n\n/** Forwards an error to the reporter if one is enabled. Only the error and a source name leave the caller. */\nexport function reportError(error: unknown, source: \"plot\" | \"drawings\" | \"alerts\" | \"feed\"): void {\n active?.report(error, source);\n}\n\n/** For `DrawingsOptions.onError`, `AlertsOptions.onError`, `FeedOptions.onError`. Uses only the first argument, never the drawing. */\nexport function errorForwarder(source: \"drawings\" | \"alerts\" | \"feed\", next?: (error: unknown) => void): (error: unknown) => void {\n return (error) => {\n reportError(error, source);\n next?.(error);\n };\n}\n\n/** For `plot.on(\"error\", ...)`. */\nexport function plotErrorForwarder(next?: (e: { error: unknown }) => void): (e: { error: unknown }) => void {\n return (e) => {\n reportError(e.error, \"plot\");\n next?.(e);\n };\n}\n\n// ---- payload -----------------------------------------------------------------\n\nfunction properties(error: unknown, source: string, renderer: \"webgl\" | \"canvas2d\" | undefined, contextLost: boolean): Record<string, unknown> {\n const errorType = nameOf(error);\n const { browser, os } = agent();\n const props: Record<string, unknown> = {\n project: \"alphacharts\",\n version: CORE_VERSION, // the core that faulted, not this package\n report_version: VERSION,\n error_type: errorType,\n source,\n webgl2: typeof WebGL2RenderingContext !== \"undefined\",\n context_lost: contextLost,\n browser,\n os,\n // No message and no stack: PostHog groups by class + source. The value is built from the source allow-list only.\n $exception_list: [{ type: errorType, value: `alphacharts fault: ${source}` }],\n $process_person_profile: false,\n $geoip_disable: true,\n };\n if (renderer) props.renderer = renderer;\n return props;\n}\n\nfunction nameOf(error: unknown): string {\n const n = typeof error === \"object\" && error !== null ? (error as { name?: unknown }).name : undefined;\n if (typeof n === \"string\" && /^[A-Za-z][A-Za-z0-9_]{0,39}$/.test(n)) return n;\n return error === undefined ? \"None\" : error instanceof Error ? \"Error\" : \"NonError\";\n}\n\nfunction agent(): { browser: string; os: string } {\n const ua = typeof navigator !== \"undefined\" && typeof navigator.userAgent === \"string\" ? navigator.userAgent : \"\";\n const pick = (re: RegExp, name: string): string | null => {\n const m = re.exec(ua);\n return m ? `${name} ${m[1]}` : null;\n };\n const browser =\n pick(/Edg\\/(\\d+)/, \"Edge\") ?? pick(/OPR\\/(\\d+)/, \"Opera\") ?? pick(/(?:Firefox|FxiOS)\\/(\\d+)/, \"Firefox\") ?? pick(/(?:Chrome|CriOS)\\/(\\d+)/, \"Chrome\") ?? pick(/Version\\/(\\d+)[^]*Safari/, \"Safari\") ?? \"other\";\n const os = /Windows/.test(ua) ? \"Windows\" : /Android/.test(ua) ? \"Android\" : /iPhone|iPad|iPod/.test(ua) ? \"iOS\" : /Mac OS X|Macintosh/.test(ua) ? \"macOS\" : /CrOS/.test(ua) ? \"ChromeOS\" : /Linux/.test(ua) ? \"Linux\" : \"other\";\n return { browser, os };\n}\n\n// ---- transport ---------------------------------------------------------------\n\nfunction uuid(): string {\n if (pageId) return pageId;\n const c = (globalThis as { crypto?: Crypto }).crypto;\n pageId = c?.randomUUID ? c.randomUUID() : Array.from({ length: 4 }, () => Math.random().toString(16).slice(2, 10).padEnd(8, \"0\")).join(\"-\");\n return pageId;\n}\n\nfunction send(endpoint: string, key: string, properties: Record<string, unknown>): void {\n try {\n const body = JSON.stringify({ api_key: key, batch: [{ event: \"$exception\", distinct_id: uuid(), properties }] });\n // text/plain keeps the request CORS-simple: no preflight.\n const nav = typeof navigator !== \"undefined\" ? navigator : undefined;\n if (nav && typeof nav.sendBeacon === \"function\" && nav.sendBeacon(endpoint, new Blob([body], { type: \"text/plain\" }))) return;\n if (typeof fetch === \"function\") {\n fetch(endpoint, { method: \"POST\", body, keepalive: true, credentials: \"omit\", headers: { \"content-type\": \"text/plain\" } }).catch(() => {});\n }\n } catch {\n // ignore every transport failure\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { type Fault } from "@alphacharts/core/internal";
2
+ export declare const VERSION = "0.1.0";
3
+ export type ReportSource = Fault["source"] | "plot" | "drawings" | "alerts" | "feed";
4
+ export interface CrashReportingOptions {
5
+ /** Full URL that accepts a PostHog capture batch (POST); no path is appended. Required: there is no default. */
6
+ endpoint: string;
7
+ /** The project's public capture key (it can only write events). Required. */
8
+ key: string;
9
+ /** Most reports sent per page load (default 5). */
10
+ maxReports?: number | undefined;
11
+ }
12
+ /** Start reporting. Returns the function that stops it. A missing, empty or non-string endpoint or key throws: nothing is sent unless the host names where. */
13
+ export declare function enableCrashReporting(options: CrashReportingOptions): () => void;
14
+ /** Forwards an error to the reporter if one is enabled. Only the error and a source name leave the caller. */
15
+ export declare function reportError(error: unknown, source: "plot" | "drawings" | "alerts" | "feed"): void;
16
+ /** For `DrawingsOptions.onError`, `AlertsOptions.onError`, `FeedOptions.onError`. Uses only the first argument, never the drawing. */
17
+ export declare function errorForwarder(source: "drawings" | "alerts" | "feed", next?: (error: unknown) => void): (error: unknown) => void;
18
+ /** For `plot.on("error", ...)`. */
19
+ export declare function plotErrorForwarder(next?: (e: {
20
+ error: unknown;
21
+ }) => void): (e: {
22
+ error: unknown;
23
+ }) => void;
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "@alphacharts/report",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Opt-in, anonymous crash reports for alphacharts. Off unless you call enableCrashReporting with your own PostHog endpoint and key; there is no default server.",
5
+ "keywords": [
6
+ "chart",
7
+ "crash-reporting",
8
+ "error-reporting",
9
+ "posthog"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "Alphabench",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/alphabench/alphacharts.git",
16
+ "directory": "packages/report"
17
+ },
18
+ "homepage": "https://github.com/alphabench/alphacharts#readme",
19
+ "bugs": {
20
+ "url": "https://github.com/alphabench/alphacharts/issues"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "type": "module",
26
+ "sideEffects": false,
27
+ "main": "./dist/index.js",
28
+ "module": "./dist/index.js",
29
+ "types": "./dist/types/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/types/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist"
38
+ ],
39
+ "peerDependencies": {
40
+ "@alphacharts/core": "^0.1.1"
41
+ },
42
+ "devDependencies": {
43
+ "typescript": "5.9.3",
44
+ "vite": "8.3.1",
45
+ "vitest": "5.0.2",
46
+ "@alphacharts/core": "0.1.1"
47
+ },
48
+ "scripts": {
49
+ "build": "vite build && tsc -p tsconfig.build.json",
50
+ "typecheck": "tsc -p tsconfig.json",
51
+ "typecheck:dist": "tsc -p tsconfig.dist.json",
52
+ "test": "vitest run"
53
+ }
6
54
  }