@sekolahcode/devpulse-browser 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/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # @sekolahcode/devpulse-browser
2
+
3
+ Zero-dependency browser SDK for DevPulse — frontend error tracking and Core Web Vitals monitoring.
4
+
5
+ ## Requirements
6
+
7
+ - A running DevPulse server
8
+ - Any modern browser (ES2017+)
9
+
10
+ ## Installation
11
+
12
+ ### Via script tag (UMD)
13
+
14
+ ```html
15
+ <script src="http://localhost:8000/devpulse.js"></script>
16
+ <script>
17
+ DevPulse.init({
18
+ dsn: 'http://localhost:8000/api/ingest/YOUR_API_KEY',
19
+ environment: 'production',
20
+ release: '1.0.0',
21
+ });
22
+ </script>
23
+ ```
24
+
25
+ ### Via npm
26
+
27
+ ```bash
28
+ npm install @sekolahcode/devpulse-browser
29
+ ```
30
+
31
+ ```js
32
+ import { DevPulse } from '@sekolahcode/devpulse-browser';
33
+
34
+ DevPulse.init({
35
+ dsn: 'http://localhost:8000/api/ingest/YOUR_API_KEY',
36
+ environment: 'production',
37
+ release: '1.0.0',
38
+ });
39
+ ```
40
+
41
+ ## API
42
+
43
+ ### `DevPulse.init(config)`
44
+
45
+ | Option | Default | Description |
46
+ |---------------------|----------------|----------------------------------------------------|
47
+ | `dsn` | *(required)* | Ingest endpoint URL including your API key |
48
+ | `environment` | `"production"` | Environment tag attached to every event |
49
+ | `release` | `null` | Release/version tag (e.g. `"1.2.3"`) |
50
+ | `enabled` | `true` | Enable / disable the SDK globally |
51
+ | `trackVitals` | `true` | Auto-track Core Web Vitals |
52
+ | `tracesSampleRate` | `1.0` | Fraction of events to send (0.0–1.0) |
53
+
54
+ After `init()`, uncaught JS errors and unhandled promise rejections are captured automatically.
55
+
56
+ ### `DevPulse.capture(error, extra?)`
57
+
58
+ Manually capture an `Error` object with optional extra context.
59
+
60
+ ```js
61
+ try {
62
+ riskyOperation();
63
+ } catch (err) {
64
+ DevPulse.capture(err, { userId: 42 });
65
+ }
66
+ ```
67
+
68
+ ### `DevPulse.captureMessage(message, level?)`
69
+
70
+ Capture a plain string message. `level` defaults to `"info"`.
71
+
72
+ ```js
73
+ DevPulse.captureMessage('Quota limit approaching', 'warning');
74
+ ```
75
+
76
+ ### `DevPulse.setUser(user)`
77
+
78
+ Attach user identity to all subsequent events.
79
+
80
+ ```js
81
+ DevPulse.setUser({ id: '123', email: 'user@example.com', name: 'Alice' });
82
+ ```
83
+
84
+ Call `DevPulse.clearUser()` on logout.
85
+
86
+ ### Core Web Vitals
87
+
88
+ When `trackVitals: true` (default), the SDK automatically tracks LCP, FID, CLS, FCP, and TTFB using the browser's `PerformanceObserver` API.
89
+
90
+ ## Build
91
+
92
+ ```bash
93
+ npm install
94
+ npm run build # outputs dist/devpulse.es.js and dist/devpulse.umd.js
95
+ npm test # run Vitest unit tests
96
+ ```
97
+
98
+ ## License
99
+
100
+ MIT — see [LICENSE](../../LICENSE)
@@ -0,0 +1,218 @@
1
+ var b = Object.defineProperty, v = Object.defineProperties;
2
+ var S = Object.getOwnPropertyDescriptors;
3
+ var f = Object.getOwnPropertySymbols;
4
+ var E = Object.prototype.hasOwnProperty, y = Object.prototype.propertyIsEnumerable;
5
+ var m = (r, e, t) => e in r ? b(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, o = (r, e) => {
6
+ for (var t in e || (e = {}))
7
+ E.call(e, t) && m(r, t, e[t]);
8
+ if (f)
9
+ for (var t of f(e))
10
+ y.call(e, t) && m(r, t, e[t]);
11
+ return r;
12
+ }, u = (r, e) => v(r, S(e));
13
+ function _(r, e = {}) {
14
+ var t, n, s;
15
+ return {
16
+ level: "error",
17
+ exception: {
18
+ type: (t = r.name) != null ? t : "Error",
19
+ message: (n = r.message) != null ? n : String(r),
20
+ stacktrace: T(r.stack)
21
+ },
22
+ context: c(),
23
+ request: d(),
24
+ user: (s = e.user) != null ? s : null,
25
+ platform: "browser",
26
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
27
+ };
28
+ }
29
+ function P(r, e = "info", t = {}) {
30
+ var n;
31
+ return {
32
+ level: e,
33
+ message: r,
34
+ context: c(),
35
+ request: d(),
36
+ user: (n = t.user) != null ? n : null,
37
+ platform: "browser",
38
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
39
+ };
40
+ }
41
+ function l(r, e, t = {}) {
42
+ var i;
43
+ const n = (i = t.unit) != null ? i : "ms", s = n === "ms" ? Math.round(e) : +Number(e).toFixed(4);
44
+ return {
45
+ level: "info",
46
+ message: `Performance: ${r} = ${s}${n}`,
47
+ context: u(o({}, c()), {
48
+ performance: { name: r, value: s, unit: n }
49
+ }),
50
+ request: d(),
51
+ platform: "browser",
52
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
53
+ };
54
+ }
55
+ function T(r) {
56
+ return r ? r.split(`
57
+ `).slice(1).map((e) => {
58
+ var i, a, h;
59
+ const t = e.trim(), n = t.match(/at\s+(.*?)\s+\((.*?):(\d+):(\d+)\)/);
60
+ if (n)
61
+ return {
62
+ function: (i = n[1]) != null ? i : null,
63
+ file: (a = n[2]) != null ? a : null,
64
+ line: parseInt(n[3]) || null,
65
+ column: parseInt(n[4]) || null
66
+ };
67
+ const s = t.match(/at\s+(.*?):(\d+):(\d+)/);
68
+ return s ? {
69
+ function: null,
70
+ file: (h = s[1]) != null ? h : null,
71
+ line: parseInt(s[2]) || null,
72
+ column: parseInt(s[3]) || null
73
+ } : { raw: t };
74
+ }).filter((e) => e.file || e.raw) : [];
75
+ }
76
+ function c() {
77
+ return {
78
+ url: window.location.href,
79
+ userAgent: navigator.userAgent,
80
+ language: navigator.language,
81
+ viewport: {
82
+ width: window.innerWidth,
83
+ height: window.innerHeight
84
+ },
85
+ screen: {
86
+ width: window.screen.width,
87
+ height: window.screen.height
88
+ }
89
+ };
90
+ }
91
+ function d() {
92
+ return {
93
+ url: window.location.href
94
+ };
95
+ }
96
+ class x {
97
+ constructor(e, t = {}) {
98
+ var n;
99
+ this.dsn = e, this.timeout = (n = t.timeout) != null ? n : 5e3;
100
+ }
101
+ send(e) {
102
+ const t = JSON.stringify(e), n = new AbortController(), s = setTimeout(() => n.abort(), this.timeout);
103
+ return fetch(this.dsn, {
104
+ method: "POST",
105
+ headers: { "Content-Type": "application/json" },
106
+ body: t,
107
+ keepalive: !0,
108
+ credentials: "omit",
109
+ signal: n.signal
110
+ }).catch(() => {
111
+ }).finally(() => clearTimeout(s)), !0;
112
+ }
113
+ }
114
+ class I {
115
+ constructor() {
116
+ this.transport = null, this.config = {}, this.user = null, this._installed = !1;
117
+ }
118
+ init(e = {}) {
119
+ var t, n, s, i, a;
120
+ if (!e.dsn) {
121
+ console.warn("[DevPulse] DSN is required");
122
+ return;
123
+ }
124
+ this.config = {
125
+ dsn: e.dsn,
126
+ environment: (t = e.environment) != null ? t : "production",
127
+ release: (n = e.release) != null ? n : null,
128
+ enabled: (s = e.enabled) != null ? s : !0,
129
+ trackVitals: (i = e.trackVitals) != null ? i : !0,
130
+ tracesSampleRate: (a = e.tracesSampleRate) != null ? a : 1
131
+ }, this.transport = new x(this.config.dsn), this.config.enabled && (this._installHandlers(), this.config.trackVitals && this._trackWebVitals());
132
+ }
133
+ // ── Public API ────────────────────────────────────────────────────────────
134
+ capture(e, t = {}) {
135
+ !this.transport || !this.config.enabled || Math.random() > this.config.tracesSampleRate || this.transport.send(u(o(o({}, _(e)), t), {
136
+ // Core identity fields always win over anything in extra
137
+ user: this.user,
138
+ environment: this.config.environment,
139
+ release: this.config.release
140
+ }));
141
+ }
142
+ captureMessage(e, t = "info") {
143
+ !this.transport || !this.config.enabled || Math.random() > this.config.tracesSampleRate || this.transport.send(u(o({}, P(e, t)), {
144
+ user: this.user,
145
+ environment: this.config.environment,
146
+ release: this.config.release
147
+ }));
148
+ }
149
+ setUser(e) {
150
+ this.user = e;
151
+ }
152
+ clearUser() {
153
+ this.user = null;
154
+ }
155
+ // ── Error Handlers ────────────────────────────────────────────────────────
156
+ _installHandlers() {
157
+ this._installed || (this._installed = !0, window.addEventListener("error", (e) => {
158
+ var t;
159
+ this.capture((t = e.error) != null ? t : new Error(e.message), {
160
+ context: {
161
+ filename: e.filename,
162
+ line: e.lineno,
163
+ column: e.colno
164
+ }
165
+ });
166
+ }), window.addEventListener("unhandledrejection", (e) => {
167
+ const t = e.reason instanceof Error ? e.reason : new Error(String(e.reason));
168
+ this.capture(t, { context: { type: "unhandledrejection" } });
169
+ }));
170
+ }
171
+ // ── Core Web Vitals ───────────────────────────────────────────────────────
172
+ _trackWebVitals() {
173
+ if (!("PerformanceObserver" in window)) return;
174
+ this._observe("largest-contentful-paint", (t) => {
175
+ const n = t[t.length - 1];
176
+ this.transport.send(l("LCP", n.startTime));
177
+ }), this._observe("first-input", (t) => {
178
+ const n = t[0];
179
+ this.transport.send(
180
+ l("FID", n.processingStart - n.startTime)
181
+ );
182
+ });
183
+ let e = 0;
184
+ this._observe("layout-shift", (t) => {
185
+ t.forEach((n) => {
186
+ n.hadRecentInput || (e += n.value);
187
+ });
188
+ }), window.addEventListener("pagehide", () => {
189
+ e > 0 && this.transport.send(l("CLS", e, { unit: "" }));
190
+ }), window.addEventListener("load", () => {
191
+ const t = performance.getEntriesByType("navigation")[0];
192
+ t && (this.transport.send(l("TTFB", t.responseStart)), this.transport.send(l("PageLoad", t.loadEventEnd)));
193
+ });
194
+ }
195
+ _observe(e, t) {
196
+ try {
197
+ new PerformanceObserver((s) => {
198
+ t(s.getEntries());
199
+ }).observe({ type: e, buffered: !0 });
200
+ } catch (n) {
201
+ }
202
+ }
203
+ }
204
+ const k = new I();
205
+ var p, g, w;
206
+ if (typeof document != "undefined") {
207
+ const r = document.currentScript;
208
+ (p = r == null ? void 0 : r.dataset) != null && p.dsn && k.init({
209
+ dsn: r.dataset.dsn,
210
+ environment: (g = r.dataset.env) != null ? g : "production",
211
+ release: (w = r.dataset.release) != null ? w : null
212
+ });
213
+ }
214
+ export {
215
+ k as DevPulse,
216
+ k as default
217
+ };
218
+ //# sourceMappingURL=devpulse.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devpulse.es.js","sources":["../src/payload.js","../src/transport.js","../src/index.js"],"sourcesContent":["export function buildFromError(error, options = {}) {\n return {\n level: \"error\",\n exception: {\n type: error.name ?? \"Error\",\n message: error.message ?? String(error),\n stacktrace: parseStack(error.stack),\n },\n context: buildContext(),\n request: buildRequest(),\n user: options.user ?? null,\n platform: \"browser\",\n timestamp: new Date().toISOString(),\n };\n}\n\nexport function buildFromMessage(message, level = \"info\", options = {}) {\n return {\n level,\n message,\n context: buildContext(),\n request: buildRequest(),\n user: options.user ?? null,\n platform: \"browser\",\n timestamp: new Date().toISOString(),\n };\n}\n\n// unit defaults to \"ms\" for timing metrics; pass { unit: \"\" } for unitless\n// scores like CLS which are in the 0–1 range, not milliseconds.\nexport function buildFromPerformance(name, value, options = {}) {\n const unit = options.unit ?? \"ms\";\n const displayValue =\n unit === \"ms\" ? Math.round(value) : +Number(value).toFixed(4);\n return {\n level: \"info\",\n message: `Performance: ${name} = ${displayValue}${unit}`,\n context: {\n ...buildContext(),\n performance: { name, value: displayValue, unit },\n },\n request: buildRequest(),\n platform: \"browser\",\n timestamp: new Date().toISOString(),\n };\n}\n\nfunction parseStack(stack) {\n if (!stack) return [];\n return stack\n .split(\"\\n\")\n .slice(1)\n .map((line) => {\n const trimmed = line.trim();\n\n // \" at functionName (file.js:10:5)\"\n const full = trimmed.match(/at\\s+(.*?)\\s+\\((.*?):(\\d+):(\\d+)\\)/);\n if (full) {\n return {\n function: full[1] ?? null,\n file: full[2] ?? null,\n line: parseInt(full[3]) || null,\n column: parseInt(full[4]) || null,\n };\n }\n\n // \" at file.js:10:5\" (anonymous or arrow functions)\n const short = trimmed.match(/at\\s+(.*?):(\\d+):(\\d+)/);\n if (short) {\n return {\n function: null,\n file: short[1] ?? null,\n line: parseInt(short[2]) || null,\n column: parseInt(short[3]) || null,\n };\n }\n\n return { raw: trimmed };\n })\n .filter((f) => f.file || f.raw);\n}\n\nfunction buildContext() {\n return {\n url: window.location.href,\n userAgent: navigator.userAgent,\n language: navigator.language,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n screen: {\n width: window.screen.width,\n height: window.screen.height,\n },\n };\n}\n\nfunction buildRequest() {\n return {\n url: window.location.href,\n };\n}\n","export class Transport {\n constructor(dsn, options = {}) {\n this.dsn = dsn;\n this.timeout = options.timeout ?? 5000;\n }\n\n send(payload) {\n const body = JSON.stringify(payload);\n\n // Use fetch with keepalive (survives page navigation) and credentials omitted\n // — the ingest endpoint authenticates via the API key in the URL, not cookies.\n // sendBeacon is avoided because it always sends credentials, which breaks\n // CORS preflight when the server responds with a specific origin.\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n fetch(this.dsn, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n keepalive: true,\n credentials: \"omit\",\n signal: controller.signal,\n })\n .catch(() => {})\n .finally(() => clearTimeout(timer));\n\n return true;\n }\n}\n","import {\n buildFromError,\n buildFromMessage,\n buildFromPerformance,\n} from \"./payload.js\";\nimport { Transport } from \"./transport.js\";\n\nclass DevPulseClient {\n constructor() {\n this.transport = null;\n this.config = {};\n this.user = null;\n this._installed = false;\n }\n\n init(config = {}) {\n if (!config.dsn) {\n console.warn(\"[DevPulse] DSN is required\");\n return;\n }\n\n this.config = {\n dsn: config.dsn,\n environment: config.environment ?? \"production\",\n release: config.release ?? null,\n enabled: config.enabled ?? true,\n trackVitals: config.trackVitals ?? true,\n tracesSampleRate: config.tracesSampleRate ?? 1.0,\n };\n\n this.transport = new Transport(this.config.dsn);\n\n if (!this.config.enabled) return;\n\n this._installHandlers();\n if (this.config.trackVitals) this._trackWebVitals();\n }\n\n // ── Public API ────────────────────────────────────────────────────────────\n capture(error, extra = {}) {\n if (!this.transport || !this.config.enabled) return;\n if (Math.random() > this.config.tracesSampleRate) return;\n this.transport.send({\n ...buildFromError(error),\n ...extra,\n // Core identity fields always win over anything in extra\n user: this.user,\n environment: this.config.environment,\n release: this.config.release,\n });\n }\n\n captureMessage(message, level = \"info\") {\n if (!this.transport || !this.config.enabled) return;\n if (Math.random() > this.config.tracesSampleRate) return;\n this.transport.send({\n ...buildFromMessage(message, level),\n user: this.user,\n environment: this.config.environment,\n release: this.config.release,\n });\n }\n\n setUser(user) {\n this.user = user; // { id, email, name }\n }\n\n clearUser() {\n this.user = null;\n }\n\n // ── Error Handlers ────────────────────────────────────────────────────────\n _installHandlers() {\n if (this._installed) return;\n this._installed = true;\n\n // Uncaught JS errors\n window.addEventListener(\"error\", (event) => {\n this.capture(event.error ?? new Error(event.message), {\n context: {\n filename: event.filename,\n line: event.lineno,\n column: event.colno,\n },\n });\n });\n\n // Unhandled Promise rejections\n window.addEventListener(\"unhandledrejection\", (event) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n this.capture(error, { context: { type: \"unhandledrejection\" } });\n });\n }\n\n // ── Core Web Vitals ───────────────────────────────────────────────────────\n _trackWebVitals() {\n if (!(\"PerformanceObserver\" in window)) return;\n\n // LCP — Largest Contentful Paint\n this._observe(\"largest-contentful-paint\", (entries) => {\n const lcp = entries[entries.length - 1];\n this.transport.send(buildFromPerformance(\"LCP\", lcp.startTime));\n });\n\n // FID — First Input Delay\n this._observe(\"first-input\", (entries) => {\n const fid = entries[0];\n this.transport.send(\n buildFromPerformance(\"FID\", fid.processingStart - fid.startTime),\n );\n });\n\n // CLS — Cumulative Layout Shift (unitless score 0–1, NOT milliseconds)\n let clsValue = 0;\n this._observe(\"layout-shift\", (entries) => {\n entries.forEach((entry) => {\n if (!entry.hadRecentInput) clsValue += entry.value;\n });\n });\n\n window.addEventListener(\"pagehide\", () => {\n if (clsValue > 0) {\n this.transport.send(buildFromPerformance(\"CLS\", clsValue, { unit: \"\" }));\n }\n });\n\n // TTFB — Time to First Byte\n window.addEventListener(\"load\", () => {\n const nav = performance.getEntriesByType(\"navigation\")[0];\n if (nav) {\n this.transport.send(buildFromPerformance(\"TTFB\", nav.responseStart));\n this.transport.send(buildFromPerformance(\"PageLoad\", nav.loadEventEnd));\n }\n });\n }\n\n _observe(type, callback) {\n try {\n const observer = new PerformanceObserver((list) => {\n callback(list.getEntries());\n });\n observer.observe({ type, buffered: true });\n } catch (e) {\n // Browser doesn't support this metric — silently skip\n }\n }\n}\n\n// Export singleton\nexport const DevPulse = new DevPulseClient();\nexport default DevPulse;\n\n// Auto-init from script tag data attributes\n// <script src=\"devpulse.umd.js\" data-dsn=\"...\" data-env=\"production\"></script>\nif (typeof document !== \"undefined\") {\n const script = document.currentScript;\n if (script?.dataset?.dsn) {\n DevPulse.init({\n dsn: script.dataset.dsn,\n environment: script.dataset.env ?? \"production\",\n release: script.dataset.release ?? null,\n });\n }\n}\n"],"names":["buildFromError","error","options","_a","_b","_c","parseStack","buildContext","buildRequest","buildFromMessage","message","level","buildFromPerformance","name","value","unit","displayValue","__spreadProps","__spreadValues","stack","line","trimmed","full","short","f","Transport","dsn","payload","body","controller","timer","DevPulseClient","config","_d","_e","extra","user","event","entries","lcp","fid","clsValue","entry","nav","type","callback","list","e","DevPulse","script"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ (function(i,s){typeof exports=="object"&&typeof module!="undefined"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(i=typeof globalThis!="undefined"?globalThis:i||self,s(i.DevPulse={}))})(this,(function(i){"use strict";var _=Object.defineProperty,D=Object.defineProperties;var x=Object.getOwnPropertyDescriptors;var S=Object.getOwnPropertySymbols;var I=Object.prototype.hasOwnProperty,k=Object.prototype.propertyIsEnumerable;var y=(i,s,a)=>s in i?_(i,s,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[s]=a,d=(i,s)=>{for(var a in s||(s={}))I.call(s,a)&&y(i,a,s[a]);if(S)for(var a of S(s))k.call(s,a)&&y(i,a,s[a]);return i},f=(i,s)=>D(i,x(s));var g,w,b;function s(r,e={}){var t,n,o;return{level:"error",exception:{type:(t=r.name)!=null?t:"Error",message:(n=r.message)!=null?n:String(r),stacktrace:E(r.stack)},context:h(),request:m(),user:(o=e.user)!=null?o:null,platform:"browser",timestamp:new Date().toISOString()}}function a(r,e="info",t={}){var n;return{level:e,message:r,context:h(),request:m(),user:(n=t.user)!=null?n:null,platform:"browser",timestamp:new Date().toISOString()}}function u(r,e,t={}){var l;const n=(l=t.unit)!=null?l:"ms",o=n==="ms"?Math.round(e):+Number(e).toFixed(4);return{level:"info",message:`Performance: ${r} = ${o}${n}`,context:f(d({},h()),{performance:{name:r,value:o,unit:n}}),request:m(),platform:"browser",timestamp:new Date().toISOString()}}function E(r){return r?r.split(`
2
+ `).slice(1).map(e=>{var l,c,v;const t=e.trim(),n=t.match(/at\s+(.*?)\s+\((.*?):(\d+):(\d+)\)/);if(n)return{function:(l=n[1])!=null?l:null,file:(c=n[2])!=null?c:null,line:parseInt(n[3])||null,column:parseInt(n[4])||null};const o=t.match(/at\s+(.*?):(\d+):(\d+)/);return o?{function:null,file:(v=o[1])!=null?v:null,line:parseInt(o[2])||null,column:parseInt(o[3])||null}:{raw:t}}).filter(e=>e.file||e.raw):[]}function h(){return{url:window.location.href,userAgent:navigator.userAgent,language:navigator.language,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height}}}function m(){return{url:window.location.href}}class P{constructor(e,t={}){var n;this.dsn=e,this.timeout=(n=t.timeout)!=null?n:5e3}send(e){const t=JSON.stringify(e),n=new AbortController,o=setTimeout(()=>n.abort(),this.timeout);return fetch(this.dsn,{method:"POST",headers:{"Content-Type":"application/json"},body:t,keepalive:!0,credentials:"omit",signal:n.signal}).catch(()=>{}).finally(()=>clearTimeout(o)),!0}}class T{constructor(){this.transport=null,this.config={},this.user=null,this._installed=!1}init(e={}){var t,n,o,l,c;if(!e.dsn){console.warn("[DevPulse] DSN is required");return}this.config={dsn:e.dsn,environment:(t=e.environment)!=null?t:"production",release:(n=e.release)!=null?n:null,enabled:(o=e.enabled)!=null?o:!0,trackVitals:(l=e.trackVitals)!=null?l:!0,tracesSampleRate:(c=e.tracesSampleRate)!=null?c:1},this.transport=new P(this.config.dsn),this.config.enabled&&(this._installHandlers(),this.config.trackVitals&&this._trackWebVitals())}capture(e,t={}){!this.transport||!this.config.enabled||Math.random()>this.config.tracesSampleRate||this.transport.send(f(d(d({},s(e)),t),{user:this.user,environment:this.config.environment,release:this.config.release}))}captureMessage(e,t="info"){!this.transport||!this.config.enabled||Math.random()>this.config.tracesSampleRate||this.transport.send(f(d({},a(e,t)),{user:this.user,environment:this.config.environment,release:this.config.release}))}setUser(e){this.user=e}clearUser(){this.user=null}_installHandlers(){this._installed||(this._installed=!0,window.addEventListener("error",e=>{var t;this.capture((t=e.error)!=null?t:new Error(e.message),{context:{filename:e.filename,line:e.lineno,column:e.colno}})}),window.addEventListener("unhandledrejection",e=>{const t=e.reason instanceof Error?e.reason:new Error(String(e.reason));this.capture(t,{context:{type:"unhandledrejection"}})}))}_trackWebVitals(){if(!("PerformanceObserver"in window))return;this._observe("largest-contentful-paint",t=>{const n=t[t.length-1];this.transport.send(u("LCP",n.startTime))}),this._observe("first-input",t=>{const n=t[0];this.transport.send(u("FID",n.processingStart-n.startTime))});let e=0;this._observe("layout-shift",t=>{t.forEach(n=>{n.hadRecentInput||(e+=n.value)})}),window.addEventListener("pagehide",()=>{e>0&&this.transport.send(u("CLS",e,{unit:""}))}),window.addEventListener("load",()=>{const t=performance.getEntriesByType("navigation")[0];t&&(this.transport.send(u("TTFB",t.responseStart)),this.transport.send(u("PageLoad",t.loadEventEnd)))})}_observe(e,t){try{new PerformanceObserver(o=>{t(o.getEntries())}).observe({type:e,buffered:!0})}catch(n){}}}const p=new T;if(typeof document!="undefined"){const r=document.currentScript;(g=r==null?void 0:r.dataset)!=null&&g.dsn&&p.init({dsn:r.dataset.dsn,environment:(w=r.dataset.env)!=null?w:"production",release:(b=r.dataset.release)!=null?b:null})}i.DevPulse=p,i.default=p,Object.defineProperties(i,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
3
+ //# sourceMappingURL=devpulse.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devpulse.umd.js","sources":["../src/payload.js","../src/transport.js","../src/index.js"],"sourcesContent":["export function buildFromError(error, options = {}) {\n return {\n level: \"error\",\n exception: {\n type: error.name ?? \"Error\",\n message: error.message ?? String(error),\n stacktrace: parseStack(error.stack),\n },\n context: buildContext(),\n request: buildRequest(),\n user: options.user ?? null,\n platform: \"browser\",\n timestamp: new Date().toISOString(),\n };\n}\n\nexport function buildFromMessage(message, level = \"info\", options = {}) {\n return {\n level,\n message,\n context: buildContext(),\n request: buildRequest(),\n user: options.user ?? null,\n platform: \"browser\",\n timestamp: new Date().toISOString(),\n };\n}\n\n// unit defaults to \"ms\" for timing metrics; pass { unit: \"\" } for unitless\n// scores like CLS which are in the 0–1 range, not milliseconds.\nexport function buildFromPerformance(name, value, options = {}) {\n const unit = options.unit ?? \"ms\";\n const displayValue =\n unit === \"ms\" ? Math.round(value) : +Number(value).toFixed(4);\n return {\n level: \"info\",\n message: `Performance: ${name} = ${displayValue}${unit}`,\n context: {\n ...buildContext(),\n performance: { name, value: displayValue, unit },\n },\n request: buildRequest(),\n platform: \"browser\",\n timestamp: new Date().toISOString(),\n };\n}\n\nfunction parseStack(stack) {\n if (!stack) return [];\n return stack\n .split(\"\\n\")\n .slice(1)\n .map((line) => {\n const trimmed = line.trim();\n\n // \" at functionName (file.js:10:5)\"\n const full = trimmed.match(/at\\s+(.*?)\\s+\\((.*?):(\\d+):(\\d+)\\)/);\n if (full) {\n return {\n function: full[1] ?? null,\n file: full[2] ?? null,\n line: parseInt(full[3]) || null,\n column: parseInt(full[4]) || null,\n };\n }\n\n // \" at file.js:10:5\" (anonymous or arrow functions)\n const short = trimmed.match(/at\\s+(.*?):(\\d+):(\\d+)/);\n if (short) {\n return {\n function: null,\n file: short[1] ?? null,\n line: parseInt(short[2]) || null,\n column: parseInt(short[3]) || null,\n };\n }\n\n return { raw: trimmed };\n })\n .filter((f) => f.file || f.raw);\n}\n\nfunction buildContext() {\n return {\n url: window.location.href,\n userAgent: navigator.userAgent,\n language: navigator.language,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n screen: {\n width: window.screen.width,\n height: window.screen.height,\n },\n };\n}\n\nfunction buildRequest() {\n return {\n url: window.location.href,\n };\n}\n","export class Transport {\n constructor(dsn, options = {}) {\n this.dsn = dsn;\n this.timeout = options.timeout ?? 5000;\n }\n\n send(payload) {\n const body = JSON.stringify(payload);\n\n // Use fetch with keepalive (survives page navigation) and credentials omitted\n // — the ingest endpoint authenticates via the API key in the URL, not cookies.\n // sendBeacon is avoided because it always sends credentials, which breaks\n // CORS preflight when the server responds with a specific origin.\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n fetch(this.dsn, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n keepalive: true,\n credentials: \"omit\",\n signal: controller.signal,\n })\n .catch(() => {})\n .finally(() => clearTimeout(timer));\n\n return true;\n }\n}\n","import {\n buildFromError,\n buildFromMessage,\n buildFromPerformance,\n} from \"./payload.js\";\nimport { Transport } from \"./transport.js\";\n\nclass DevPulseClient {\n constructor() {\n this.transport = null;\n this.config = {};\n this.user = null;\n this._installed = false;\n }\n\n init(config = {}) {\n if (!config.dsn) {\n console.warn(\"[DevPulse] DSN is required\");\n return;\n }\n\n this.config = {\n dsn: config.dsn,\n environment: config.environment ?? \"production\",\n release: config.release ?? null,\n enabled: config.enabled ?? true,\n trackVitals: config.trackVitals ?? true,\n tracesSampleRate: config.tracesSampleRate ?? 1.0,\n };\n\n this.transport = new Transport(this.config.dsn);\n\n if (!this.config.enabled) return;\n\n this._installHandlers();\n if (this.config.trackVitals) this._trackWebVitals();\n }\n\n // ── Public API ────────────────────────────────────────────────────────────\n capture(error, extra = {}) {\n if (!this.transport || !this.config.enabled) return;\n if (Math.random() > this.config.tracesSampleRate) return;\n this.transport.send({\n ...buildFromError(error),\n ...extra,\n // Core identity fields always win over anything in extra\n user: this.user,\n environment: this.config.environment,\n release: this.config.release,\n });\n }\n\n captureMessage(message, level = \"info\") {\n if (!this.transport || !this.config.enabled) return;\n if (Math.random() > this.config.tracesSampleRate) return;\n this.transport.send({\n ...buildFromMessage(message, level),\n user: this.user,\n environment: this.config.environment,\n release: this.config.release,\n });\n }\n\n setUser(user) {\n this.user = user; // { id, email, name }\n }\n\n clearUser() {\n this.user = null;\n }\n\n // ── Error Handlers ────────────────────────────────────────────────────────\n _installHandlers() {\n if (this._installed) return;\n this._installed = true;\n\n // Uncaught JS errors\n window.addEventListener(\"error\", (event) => {\n this.capture(event.error ?? new Error(event.message), {\n context: {\n filename: event.filename,\n line: event.lineno,\n column: event.colno,\n },\n });\n });\n\n // Unhandled Promise rejections\n window.addEventListener(\"unhandledrejection\", (event) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n this.capture(error, { context: { type: \"unhandledrejection\" } });\n });\n }\n\n // ── Core Web Vitals ───────────────────────────────────────────────────────\n _trackWebVitals() {\n if (!(\"PerformanceObserver\" in window)) return;\n\n // LCP — Largest Contentful Paint\n this._observe(\"largest-contentful-paint\", (entries) => {\n const lcp = entries[entries.length - 1];\n this.transport.send(buildFromPerformance(\"LCP\", lcp.startTime));\n });\n\n // FID — First Input Delay\n this._observe(\"first-input\", (entries) => {\n const fid = entries[0];\n this.transport.send(\n buildFromPerformance(\"FID\", fid.processingStart - fid.startTime),\n );\n });\n\n // CLS — Cumulative Layout Shift (unitless score 0–1, NOT milliseconds)\n let clsValue = 0;\n this._observe(\"layout-shift\", (entries) => {\n entries.forEach((entry) => {\n if (!entry.hadRecentInput) clsValue += entry.value;\n });\n });\n\n window.addEventListener(\"pagehide\", () => {\n if (clsValue > 0) {\n this.transport.send(buildFromPerformance(\"CLS\", clsValue, { unit: \"\" }));\n }\n });\n\n // TTFB — Time to First Byte\n window.addEventListener(\"load\", () => {\n const nav = performance.getEntriesByType(\"navigation\")[0];\n if (nav) {\n this.transport.send(buildFromPerformance(\"TTFB\", nav.responseStart));\n this.transport.send(buildFromPerformance(\"PageLoad\", nav.loadEventEnd));\n }\n });\n }\n\n _observe(type, callback) {\n try {\n const observer = new PerformanceObserver((list) => {\n callback(list.getEntries());\n });\n observer.observe({ type, buffered: true });\n } catch (e) {\n // Browser doesn't support this metric — silently skip\n }\n }\n}\n\n// Export singleton\nexport const DevPulse = new DevPulseClient();\nexport default DevPulse;\n\n// Auto-init from script tag data attributes\n// <script src=\"devpulse.umd.js\" data-dsn=\"...\" data-env=\"production\"></script>\nif (typeof document !== \"undefined\") {\n const script = document.currentScript;\n if (script?.dataset?.dsn) {\n DevPulse.init({\n dsn: script.dataset.dsn,\n environment: script.dataset.env ?? \"production\",\n release: script.dataset.release ?? null,\n });\n }\n}\n"],"names":["buildFromError","error","options","_a","_b","parseStack","buildContext","buildRequest","_c","buildFromMessage","message","level","buildFromPerformance","name","value","unit","displayValue","__spreadProps","__spreadValues","stack","line","trimmed","full","short","f","Transport","dsn","payload","body","controller","timer","DevPulseClient","config","_d","_e","extra","user","event","entries","lcp","fid","clsValue","entry","nav","type","callback","list","e","DevPulse","script"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@sekolahcode/devpulse-browser",
3
+ "version": "0.1.0",
4
+ "description": "DevPulse browser SDK — frontend error and performance tracking",
5
+ "license": "MIT",
6
+ "keywords": ["error-tracking", "monitoring", "browser", "sdk", "web-vitals"],
7
+ "main": "dist/devpulse.umd.js",
8
+ "module": "dist/devpulse.es.js",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/devpulse.es.js",
12
+ "require": "./dist/devpulse.umd.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "sideEffects": true,
19
+ "scripts": {
20
+ "build": "vite build",
21
+ "dev": "vite build --watch",
22
+ "test": "vitest",
23
+ "lint": "eslint src",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "devDependencies": {
27
+ "eslint": "^10.0.0",
28
+ "jsdom": "^25.0.0",
29
+ "prettier": "^3.0.0",
30
+ "vite": "^6.0.0",
31
+ "vitest": "^3.0.0"
32
+ }
33
+ }