@glassanalytics/browser 0.1.1 → 0.1.2
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/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -135,10 +135,14 @@ var ReplayRecorder = class {
|
|
|
135
135
|
interval = null;
|
|
136
136
|
boundFinal = null;
|
|
137
137
|
encoder = new ReplayEncoder();
|
|
138
|
+
/** rrweb's addCustomEvent, captured on start — lets us weave Glass events into the stream. */
|
|
139
|
+
addCustom = null;
|
|
138
140
|
async start() {
|
|
139
141
|
if (this.stop) return;
|
|
140
142
|
if (typeof window === "undefined") return;
|
|
141
143
|
const { record } = await import('rrweb');
|
|
144
|
+
const rec = record;
|
|
145
|
+
this.addCustom = typeof rec.addCustomEvent === "function" ? rec.addCustomEvent.bind(record) : null;
|
|
142
146
|
this.stop = record({
|
|
143
147
|
emit: (event) => {
|
|
144
148
|
this.events.push(event);
|
|
@@ -163,6 +167,19 @@ var ReplayRecorder = class {
|
|
|
163
167
|
this.boundFinal = () => this.flushFinalBeacon();
|
|
164
168
|
window.addEventListener("pagehide", this.boundFinal);
|
|
165
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Weave a Glass event into the rrweb stream as a Custom (type 5) event, so the
|
|
172
|
+
* player can render it as a timeline marker (`UI.md` §4.1). No-op unless we're
|
|
173
|
+
* actively recording. Payload is kept tiny (name + optional level) to avoid
|
|
174
|
+
* bloating replay segments.
|
|
175
|
+
*/
|
|
176
|
+
addEvent(name, payload) {
|
|
177
|
+
if (!this.stop || !this.addCustom) return;
|
|
178
|
+
try {
|
|
179
|
+
this.addCustom(name, payload);
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
}
|
|
166
183
|
async flushSegment() {
|
|
167
184
|
if (this.events.length === 0) return;
|
|
168
185
|
const segment = this.events.splice(0, this.events.length);
|
|
@@ -199,6 +216,7 @@ var ReplayRecorder = class {
|
|
|
199
216
|
await this.flushSegment();
|
|
200
217
|
this.stop?.();
|
|
201
218
|
this.stop = null;
|
|
219
|
+
this.addCustom = null;
|
|
202
220
|
if (this.interval) {
|
|
203
221
|
clearInterval(this.interval);
|
|
204
222
|
this.interval = null;
|
|
@@ -744,6 +762,10 @@ var Glass = class {
|
|
|
744
762
|
t_client: (/* @__PURE__ */ new Date()).toISOString(),
|
|
745
763
|
props: { ...this.contextProps(), ...this.superProps, ...props }
|
|
746
764
|
});
|
|
765
|
+
if (this.cfg.replay) {
|
|
766
|
+
const name = event ?? type;
|
|
767
|
+
this.replay.addEvent(name, { event: name, ...type === "error" ? { level: "error" } : {} });
|
|
768
|
+
}
|
|
747
769
|
}
|
|
748
770
|
/** Device/screen context attached to EVERY event (`SDK.md` §4). */
|
|
749
771
|
contextProps() {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/replay-encoder.ts","../src/replay.ts","../src/offline-store.ts","../src/transport.ts","../src/index.ts"],"names":["ls"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Off-main-thread replay-segment encoder (`SDK.md` §6). rrweb segments are large\n * and highly repetitive, so we (a) JSON-serialize and (b) gzip them in a Web\n * Worker — keeping both the (potentially multi-MB) stringify and the compression\n * off the page's main thread. Everything degrades gracefully: no Worker → encode\n * on the main thread; no `CompressionStream` → send uncompressed JSON. The result\n * is the same bytes the ingest endpoint already accepts, just optionally gzipped\n * (signalled to callers via `gzip`, which they translate to `Content-Encoding`).\n */\n\nexport interface EncodedSegment {\n body: Uint8Array | string;\n gzip: boolean;\n}\n\n/**\n * Worker body, kept dependency-free so it can be inlined via a Blob URL (no\n * separate build step / bundler entry). It receives `{ id, json }`, gzips when\n * possible, and posts back `{ id, buf, gzip }` transferring the buffer.\n */\nconst WORKER_SRC = `\nself.onmessage = async function (e) {\n var id = e.data.id, json = e.data.json;\n try {\n var bytes = new TextEncoder().encode(json);\n if (typeof CompressionStream !== 'undefined') {\n var cs = new CompressionStream('gzip');\n var w = cs.writable.getWriter();\n w.write(bytes); w.close();\n var buf = await new Response(cs.readable).arrayBuffer();\n self.postMessage({ id: id, buf: buf, gzip: true }, [buf]);\n } else {\n self.postMessage({ id: id, buf: bytes.buffer, gzip: false }, [bytes.buffer]);\n }\n } catch (err) {\n self.postMessage({ id: id, error: String(err) });\n }\n};\n`;\n\ninterface WorkerReply {\n id: number;\n buf?: ArrayBuffer;\n gzip?: boolean;\n error?: string;\n}\n\nexport class ReplayEncoder {\n private worker: Worker | null = null;\n private workerUrl: string | null = null;\n private workerBroken = false;\n private nextId = 1;\n private pending = new Map<number, (r: WorkerReply) => void>();\n\n /** Lazily spin up the encode worker; null if Workers/Blob URLs aren't available. */\n private ensureWorker(): Worker | null {\n if (this.worker || this.workerBroken) return this.worker;\n try {\n if (typeof Worker === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined') {\n this.workerBroken = true;\n return null;\n }\n this.workerUrl = URL.createObjectURL(new Blob([WORKER_SRC], { type: 'text/javascript' }));\n this.worker = new Worker(this.workerUrl);\n this.worker.onmessage = (ev: MessageEvent<WorkerReply>) => {\n const resolve = this.pending.get(ev.data.id);\n if (resolve) {\n this.pending.delete(ev.data.id);\n resolve(ev.data);\n }\n };\n this.worker.onerror = () => {\n // A broken worker disables itself; future encodes run on the main thread.\n this.workerBroken = true;\n for (const [, resolve] of this.pending) resolve({ id: -1, error: 'worker_error' });\n this.pending.clear();\n };\n return this.worker;\n } catch {\n this.workerBroken = true;\n return null;\n }\n }\n\n async encode(segment: unknown): Promise<EncodedSegment> {\n let json: string;\n try {\n json = JSON.stringify(segment);\n } catch {\n json = '[]';\n }\n\n const worker = this.ensureWorker();\n if (worker) {\n try {\n const reply = await this.postToWorker(worker, json);\n if (!reply.error && reply.buf) {\n return { body: new Uint8Array(reply.buf), gzip: reply.gzip === true };\n }\n } catch {\n /* fall through to main-thread encoding */\n }\n }\n return this.encodeMainThread(json);\n }\n\n private postToWorker(worker: Worker, json: string): Promise<WorkerReply> {\n const id = this.nextId++;\n return new Promise<WorkerReply>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error('encode_timeout'));\n }, 2000);\n this.pending.set(id, (r) => {\n clearTimeout(timeout);\n resolve(r);\n });\n worker.postMessage({ id, json });\n });\n }\n\n /** Main-thread fallback: gzip via CompressionStream when present, else raw JSON. */\n private async encodeMainThread(json: string): Promise<EncodedSegment> {\n const CS = (globalThis as { CompressionStream?: typeof CompressionStream }).CompressionStream;\n if (typeof CS !== 'undefined') {\n try {\n const cs = new CS('gzip');\n const writer = cs.writable.getWriter();\n void writer.write(new TextEncoder().encode(json));\n void writer.close();\n const buf = await new Response(cs.readable).arrayBuffer();\n return { body: new Uint8Array(buf), gzip: true };\n } catch {\n /* fall through to uncompressed */\n }\n }\n return { body: json, gzip: false };\n }\n\n dispose(): void {\n this.worker?.terminate();\n this.worker = null;\n if (this.workerUrl) {\n try {\n URL.revokeObjectURL(this.workerUrl);\n } catch {\n /* ignore */\n }\n this.workerUrl = null;\n }\n this.pending.clear();\n }\n}\n","import { replaySegmentPath } from '@glassanalytics/core';\nimport type { ResolvedConfig } from './types.js';\nimport { ReplayEncoder } from './replay-encoder.js';\n\n/**\n * Session replay (`SDK.md` §6). rrweb is loaded LAZILY (dynamic import) so apps\n * that don't record pay nothing. Recording is MASKED BY DEFAULT — all inputs\n * masked, configurable text/blocked selectors — and segments are streamed to the\n * ingest `/v1/replay/:session/:seq` endpoint, not buffered in memory.\n */\n/** Input types/name patterns ALWAYS masked, even when maskAllInputs is false. */\nconst SENSITIVE_INPUT_TYPES = new Set(['password', 'email', 'tel', 'hidden']);\nconst SENSITIVE_NAME_RE = /pass|secret|token|ssn|card|cvv|cvc|account|email|phone|tax/i;\n\nexport class ReplayRecorder {\n private stop: (() => void) | null = null;\n private seq = 0;\n private events: unknown[] = [];\n private interval: ReturnType<typeof setInterval> | null = null;\n private boundFinal: (() => void) | null = null;\n private encoder = new ReplayEncoder();\n\n constructor(\n private cfg: ResolvedConfig,\n private getSessionId: () => string,\n ) {}\n\n async start(): Promise<void> {\n if (this.stop) return;\n if (typeof window === 'undefined') return;\n const { record } = await import('rrweb');\n this.stop =\n record({\n emit: (event: unknown) => {\n this.events.push(event);\n if (this.events.length >= 50) void this.flushSegment();\n },\n // Privacy defaults: never leak user input.\n maskAllInputs: this.cfg.maskAllInputs,\n maskTextSelector: this.cfg.maskTextSelector,\n blockSelector: this.cfg.blockSelector,\n // ALWAYS mask sensitive fields regardless of maskAllInputs (defense in depth).\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.cfg.maskAllInputs) return '*'.repeat(text.length);\n const type = (element.getAttribute('type') ?? '').toLowerCase();\n const name = `${element.getAttribute('name') ?? ''} ${element.getAttribute('autocomplete') ?? ''} ${element.id}`;\n if (SENSITIVE_INPUT_TYPES.has(type) || SENSITIVE_NAME_RE.test(name)) return '*'.repeat(text.length);\n return text;\n },\n recordCanvas: false,\n collectFonts: false,\n }) ?? null;\n\n this.interval = setInterval(() => void this.flushSegment(), 5000);\n // Final segment on unload via beacon (fetch is unreliable during teardown).\n this.boundFinal = () => this.flushFinalBeacon();\n window.addEventListener('pagehide', this.boundFinal);\n }\n\n private async flushSegment(): Promise<void> {\n if (this.events.length === 0) return;\n const segment = this.events.splice(0, this.events.length);\n const seq = this.seq++;\n const url = `${this.cfg.ingestHost}${replaySegmentPath(this.getSessionId(), seq)}`;\n\n // Serialize + gzip OFF the main thread (Web Worker) so a big segment never\n // janks the page; on any failure we fall back to plain JSON. Compression is\n // a large COGS/bandwidth win (rrweb segments are very repetitive).\n const encoded = await this.encoder.encode(segment);\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Glass-Key ${this.cfg.projectKey}`,\n };\n if (encoded.gzip) headers['Content-Encoding'] = 'gzip';\n\n try {\n await fetch(url, {\n method: 'POST',\n keepalive: true,\n headers,\n body: encoded.body as BodyInit,\n });\n } catch {\n // a dropped replay segment is non-fatal; the player tolerates gaps.\n }\n }\n\n /** Flush the trailing segment with sendBeacon so it survives page teardown. */\n private flushFinalBeacon(): void {\n if (this.events.length === 0) return;\n const segment = this.events.splice(0, this.events.length);\n const seq = this.seq++;\n const url = `${this.cfg.ingestHost}${replaySegmentPath(this.getSessionId(), seq)}?k=${encodeURIComponent(this.cfg.projectKey)}`;\n const payload = JSON.stringify(segment);\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n navigator.sendBeacon(url, payload);\n }\n }\n\n async stopRecording(): Promise<void> {\n await this.flushSegment();\n this.stop?.();\n this.stop = null;\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n if (this.boundFinal && typeof window !== 'undefined') {\n window.removeEventListener('pagehide', this.boundFinal);\n this.boundFinal = null;\n }\n this.encoder.dispose();\n }\n\n get recording(): boolean {\n return this.stop !== null;\n }\n}\n","import type { QueuedBatch } from './transport.js';\n\n/**\n * Durable offline queue for event batches (`SDK.md` §10). Prefers IndexedDB\n * (larger quota, survives reloads) and transparently falls back to localStorage\n * when IDB is unavailable (private mode / old browsers) and to an in-memory\n * array when neither is present (SSR/tests). Only already-masked payloads are\n * stored, entries are TTL'd, and the queue is size-capped.\n */\n\nconst DB_NAME = 'glass';\nconst STORE = 'offline_q';\nconst LS_KEY = 'glass_offline_q';\n\nexport class OfflineStore {\n private mem: QueuedBatch[] = [];\n private dbPromise: Promise<IDBDatabase> | null = null;\n\n constructor(\n private max: number,\n private ttlMs: number,\n ) {}\n\n private idb(): Promise<IDBDatabase> | null {\n if (typeof indexedDB === 'undefined') return null;\n if (!this.dbPromise) {\n this.dbPromise = new Promise<IDBDatabase>((resolve, reject) => {\n const req = indexedDB.open(DB_NAME, 1);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(STORE)) db.createObjectStore(STORE, { autoIncrement: true });\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n }).catch((err) => {\n // Disable IDB for the rest of the session on failure.\n this.dbPromise = null;\n throw err;\n });\n }\n return this.dbPromise;\n }\n\n private fresh(items: QueuedBatch[]): QueuedBatch[] {\n const cutoff = Date.now() - this.ttlMs;\n const kept = items.filter((b) => b.at >= cutoff);\n return kept.length > this.max ? kept.slice(kept.length - this.max) : kept;\n }\n\n async append(batch: QueuedBatch): Promise<void> {\n try {\n const db = await this.idb();\n if (db) {\n await this.idbWrite(db, batch);\n return;\n }\n } catch {\n /* fall through to localStorage */\n }\n if (this.tryLS((q) => this.fresh([...q, batch]))) return;\n this.mem = this.fresh([...this.mem, batch]);\n }\n\n async drain(): Promise<QueuedBatch[]> {\n try {\n const db = await this.idb();\n if (db) return this.fresh(await this.idbDrain(db));\n } catch {\n /* fall through */\n }\n const ls = this.readLS();\n if (ls !== null) {\n this.writeLS([]);\n return this.fresh(ls);\n }\n const m = this.mem;\n this.mem = [];\n return this.fresh(m);\n }\n\n async clear(): Promise<void> {\n this.mem = [];\n try {\n const db = await this.idb();\n if (db) {\n await new Promise<void>((resolve) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => resolve();\n });\n }\n } catch {\n /* ignore */\n }\n this.writeLS([]);\n }\n\n // --- IndexedDB helpers ------------------------------------------------------\n\n private idbWrite(db: IDBDatabase, batch: QueuedBatch): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).add(batch);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n private idbDrain(db: IDBDatabase): Promise<QueuedBatch[]> {\n return new Promise<QueuedBatch[]>((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n const store = tx.objectStore(STORE);\n const getAll = store.getAll();\n getAll.onsuccess = () => {\n store.clear();\n resolve((getAll.result as QueuedBatch[]) ?? []);\n };\n getAll.onerror = () => reject(getAll.error);\n });\n }\n\n // --- localStorage fallback --------------------------------------------------\n\n private readLS(): QueuedBatch[] | null {\n if (typeof localStorage === 'undefined') return null;\n try {\n const raw = localStorage.getItem(LS_KEY);\n return raw ? (JSON.parse(raw) as QueuedBatch[]) : [];\n } catch {\n return null;\n }\n }\n\n private writeLS(q: QueuedBatch[]): void {\n if (typeof localStorage === 'undefined') return;\n try {\n localStorage.setItem(LS_KEY, JSON.stringify(q));\n } catch {\n /* storage full/disabled — drop silently */\n }\n }\n\n private tryLS(update: (q: QueuedBatch[]) => QueuedBatch[]): boolean {\n const cur = this.readLS();\n if (cur === null) return false;\n this.writeLS(update(cur));\n return true;\n }\n}\n","import { INGEST_AUTH_SCHEME, type IngestBatch } from '@glassanalytics/core';\nimport { OfflineStore } from './offline-store.js';\nimport type { GlassEvent, ResolvedConfig } from './types.js';\n\n/**\n * Reliable, cheap transport (`SDK.md` §10): batch on a timer/size, use\n * `sendBeacon` on unload, queue offline, and BACK OFF (exponential + jitter) on\n * failures. Under memory pressure we drop the LOWEST-value events first so\n * high-signal events (errors, identify, exposure) survive. The goal is to never\n * block the app's main work and never lose more than the lowest-value tail.\n */\n\nconst QUEUE_TTL_MS = 24 * 3_600_000;\nconst QUEUE_MAX = 500;\n/** In-memory ceiling before value-based shedding kicks in. */\nconst BUFFER_MAX = 1000;\nconst BACKOFF_BASE_MS = 1000;\nconst BACKOFF_CAP_MS = 5 * 60_000;\n\ninterface QueuedBatch {\n at: number;\n body: IngestBatch;\n}\n\n/** Priority for value-based backpressure — higher survives shedding. */\nfunction eventValue(e: GlassEvent): number {\n switch (e.type) {\n case 'error':\n return 100;\n case 'identify':\n case 'group':\n return 90;\n case 'exposure':\n return 80;\n case 'track':\n // Autocapture / passive pageviews are the most sheddable.\n return e.event === '$autocapture' || e.event === '$pageview' ? 10 : 50;\n default:\n return 40;\n }\n}\n\nexport class Transport {\n private buffer: GlassEvent[] = [];\n private timer: ReturnType<typeof setTimeout> | null = null;\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n private backoffUntil = 0;\n private failures = 0;\n private store = new OfflineStore(QUEUE_MAX, QUEUE_TTL_MS);\n\n private onPageHide = () => void this.flush(true);\n private onOnline = () => void this.drainOffline();\n\n constructor(\n private cfg: ResolvedConfig,\n private getIdentity: () => Pick<IngestBatch, 'device_id' | 'session_id' | 'user_id' | 'traits' | 'group'>,\n ) {\n if (typeof window !== 'undefined') {\n window.addEventListener('pagehide', this.onPageHide);\n window.addEventListener('online', this.onOnline);\n }\n }\n\n /** Remove window listeners and pending timers (called from Glass.shutdown()). */\n destroy(): void {\n if (typeof window !== 'undefined') {\n window.removeEventListener('pagehide', this.onPageHide);\n window.removeEventListener('online', this.onOnline);\n }\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n if (this.retryTimer) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n }\n\n enqueue(event: GlassEvent): void {\n const finalEvent = this.cfg.beforeSend(event);\n if (!finalEvent) return; // dropped by beforeSend\n this.buffer.push(finalEvent);\n this.applyBackpressure();\n if (this.buffer.length >= this.cfg.flushAt) {\n void this.flush();\n } else if (!this.timer) {\n this.timer = setTimeout(() => void this.flush(), this.cfg.flushIntervalMs);\n }\n }\n\n /**\n * Cap the in-memory buffer by shedding the lowest-value events when it grows\n * past BUFFER_MAX (e.g. a long offline burst of autocapture). Errors and\n * identity events are kept preferentially.\n */\n private applyBackpressure(): void {\n if (this.buffer.length <= BUFFER_MAX) return;\n // Stable sort by value descending, keep the top BUFFER_MAX, preserve order.\n const indexed = this.buffer.map((e, i) => ({ e, i }));\n indexed.sort((a, b) => eventValue(b.e) - eventValue(a.e) || a.i - b.i);\n const kept = indexed.slice(0, BUFFER_MAX).sort((a, b) => a.i - b.i);\n this.buffer = kept.map((x) => x.e);\n }\n\n async flush(useBeacon = false): Promise<void> {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n if (this.buffer.length === 0) return;\n const events = this.buffer.splice(0, this.buffer.length);\n const body: IngestBatch = {\n sent_at: new Date().toISOString(),\n ...this.getIdentity(),\n events,\n };\n\n // Respect server backpressure: persist for a scheduled retry rather than hammer.\n if (Date.now() < this.backoffUntil) {\n await this.store.append({ at: Date.now(), body });\n this.scheduleRetry();\n return;\n }\n await this.send(body, useBeacon);\n }\n\n private async send(body: IngestBatch, useBeacon: boolean): Promise<void> {\n const url = `${this.cfg.ingestHost}/v1/batch`;\n const payload = JSON.stringify(body);\n\n if (useBeacon && typeof navigator !== 'undefined' && navigator.sendBeacon) {\n // Beacon can't set Authorization; the key rides as a query param fallback.\n navigator.sendBeacon(`${url}?k=${encodeURIComponent(this.cfg.projectKey)}`, payload);\n return;\n }\n\n try {\n const res = await fetch(url, {\n method: 'POST',\n keepalive: true,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `${INGEST_AUTH_SCHEME} ${this.cfg.projectKey}`,\n },\n body: payload,\n });\n if (res.status === 429) {\n const retry = Number(res.headers.get('retry-after') ?? '0');\n this.failures++;\n this.backoffUntil = Date.now() + (retry > 0 ? retry * 1000 : this.backoffMs());\n await this.store.append({ at: Date.now(), body });\n this.scheduleRetry();\n } else if (res.status >= 500) {\n // Server-side failure: back off (exp + jitter) and retry the batch later.\n this.failures++;\n this.backoffUntil = Date.now() + this.backoffMs();\n await this.store.append({ at: Date.now(), body });\n this.scheduleRetry();\n } else {\n // 2xx (and non-retryable 4xx) — the batch is done; clear the failure streak.\n this.failures = 0;\n }\n } catch {\n // Offline / network error → persist for the next online drain + retry.\n this.failures++;\n this.backoffUntil = Date.now() + this.backoffMs();\n await this.store.append({ at: Date.now(), body });\n this.scheduleRetry();\n }\n }\n\n /** Exponential backoff with full jitter, capped. */\n private backoffMs(): number {\n const exp = Math.min(BACKOFF_CAP_MS, BACKOFF_BASE_MS * 2 ** Math.min(this.failures, 12));\n return Math.floor(Math.random() * exp);\n }\n\n private scheduleRetry(): void {\n if (this.retryTimer) return;\n const delay = Math.max(0, this.backoffUntil - Date.now()) + 250;\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n void this.drainOffline();\n }, delay);\n }\n\n // --- durable offline queue (masked data only; TTL'd; size-capped) ----------\n\n async drainOffline(): Promise<void> {\n if (Date.now() < this.backoffUntil) {\n this.scheduleRetry();\n return;\n }\n const q = await this.store.drain();\n for (const item of q) {\n if (Date.now() < this.backoffUntil) {\n // Backoff re-armed mid-drain: re-persist the remainder and reschedule.\n await this.store.append(item);\n this.scheduleRetry();\n return;\n }\n await this.send(item.body, false);\n }\n }\n\n /** optOut/reset clears any queued (but already-masked) payloads. */\n clearOffline(): void {\n void this.store.clear();\n }\n\n /** Drop the in-memory buffer so no buffered PII survives optOut()/reset(). */\n clearBuffer(): void {\n this.buffer = [];\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n }\n}\n\nexport type { QueuedBatch };\n","import { type FlagDefinition, type ScalarValue, type Value, evaluateFlag, prefixedId, randomToken } from '@glassanalytics/core';\nimport { ReplayRecorder } from './replay.js';\nimport { Transport } from './transport.js';\nimport type { FlagOptions, FlagValue, GlassConfig, GlassEvent, ResolvedConfig } from './types.js';\n\nexport type { GlassConfig, GlassEvent, FlagValue, FlagOptions } from './types.js';\n\nconst SESSION_IDLE_MS = 30 * 60_000;\nconst DEVICE_KEY = 'glass_device_id';\nconst SESSION_KEY = 'glass_session';\n\nfunction ls(): Storage | null {\n try {\n return typeof localStorage !== 'undefined' ? localStorage : null;\n } catch {\n return null;\n }\n}\n\n/**\n * The Glass browser client (`SDK.md` §3). One small object: identity, events,\n * errors, replay and flags. Non-blocking by construction; nothing here should\n * ever be on the app's critical path.\n */\nexport class Glass {\n private cfg!: ResolvedConfig;\n private transport!: Transport;\n private replay!: ReplayRecorder;\n private deviceId = '';\n private sessionId = '';\n private userId: string | null = null;\n private traits: Record<string, Value> = {};\n private groupCtx: { type: string; key: string } | null = null;\n private superProps: Record<string, Value> = {};\n private seq = 0;\n private lastActivity = 0;\n private flags: Record<string, FlagValue> = {};\n private flagsLoaded = false;\n private flagListeners: Array<(flags: Record<string, FlagValue>) => void> = [];\n private optedOut = false;\n private started = false;\n /** Calls made before init() are queued and replayed once started (`SDK.md` §2). */\n private preInitQueue: Array<() => void> = [];\n /** Removers for every listener/patch we install, so shutdown() leaves no trace. */\n private teardowns: Array<() => void> = [];\n\n init(config: GlassConfig): void {\n if (this.started) return;\n this.cfg = {\n projectKey: config.projectKey,\n ingestHost: config.ingestHost ?? 'https://in.glass.dev',\n apiHost: config.apiHost ?? 'https://api.glass.dev',\n replay: config.replay ?? true,\n autocapture: config.autocapture ?? true,\n errors: config.errors ?? true,\n captureConsole: config.captureConsole ?? false,\n sampleRate: config.sampleRate ?? 1,\n consent: config.consent ?? 'implied',\n maskAllInputs: config.maskAllInputs ?? true,\n maskTextSelector: config.maskTextSelector,\n blockSelector: config.blockSelector,\n respectDoNotTrack: config.respectDoNotTrack ?? true,\n flushIntervalMs: config.flushIntervalMs ?? 5000,\n flushAt: config.flushAt ?? 25,\n beforeSend: config.beforeSend ?? ((e) => e),\n bootstrapFlags: config.bootstrapFlags ?? {},\n flagDefinitions: config.flagDefinitions ?? [],\n };\n this.flags = { ...this.cfg.bootstrapFlags };\n\n if (this.cfg.respectDoNotTrack && typeof navigator !== 'undefined' && navigator.doNotTrack === '1') {\n this.optedOut = true;\n }\n\n this.deviceId = this.loadDeviceId();\n this.sessionId = this.loadSession();\n this.transport = new Transport(this.cfg, () => ({\n device_id: this.deviceId,\n session_id: this.sessionId,\n ...(this.userId ? { user_id: this.userId } : {}),\n traits: this.traits,\n ...(this.groupCtx ? { group: this.groupCtx } : {}),\n }));\n this.replay = new ReplayRecorder(this.cfg, () => this.sessionId);\n this.started = true;\n\n if (this.optedOut || (this.cfg.consent === 'opt-in')) {\n // No collection until optIn() is called.\n } else {\n this.afterConsent();\n }\n void this.reloadFeatureFlags();\n\n // Replay any calls made before init() resolved, in order.\n const queued = this.preInitQueue.splice(0, this.preInitQueue.length);\n for (const fn of queued) fn();\n }\n\n private afterConsent(): void {\n if (this.cfg.errors) this.installErrorHandlers();\n if (this.cfg.autocapture) this.installAutocapture();\n if (this.cfg.captureConsole) this.installConsoleCapture();\n this.installVisibilityFlush();\n if (this.cfg.replay && Math.random() < this.cfg.sampleRate) void this.replay.start();\n void this.transport.drainOffline();\n this.track('$pageview', this.pageProps());\n // Deliver the first pageview immediately (batched with anything queued during\n // init) so a fast bounce — open then close within the flush window — still\n // records the view, instead of relying only on the lossy pagehide beacon.\n this.flushSoon();\n }\n\n /**\n * Flush once on the next microtask. Runs after init()'s synchronous work\n * (pre-init queue drain + any `track()` right after `init()`), so the initial\n * pageview and those events go out in ONE batch, within a tick of load.\n */\n private initialFlushScheduled = false;\n private flushSoon(): void {\n if (this.initialFlushScheduled) return;\n this.initialFlushScheduled = true;\n const run = () => {\n this.initialFlushScheduled = false;\n void this.transport.flush();\n };\n if (typeof queueMicrotask === 'function') queueMicrotask(run);\n else void Promise.resolve().then(run);\n }\n\n /** Register a DOM listener and remember how to remove it on shutdown(). */\n private addListener(\n target: EventTarget,\n type: string,\n handler: EventListenerOrEventListenerObject,\n opts?: AddEventListenerOptions | boolean,\n ): void {\n target.addEventListener(type, handler, opts);\n this.teardowns.push(() => target.removeEventListener(type, handler, opts));\n }\n\n /**\n * Flush on tab hide (`SDK.md` §10). `visibilitychange`→hidden is the most\n * reliable \"user is leaving\" signal on mobile (where `pagehide`/`unload` are\n * unreliable), so we drain the buffer with a beacon while we still can.\n */\n private installVisibilityFlush(): void {\n if (typeof document === 'undefined') return;\n this.addListener(document, 'visibilitychange', () => {\n if (document.visibilityState === 'hidden') void this.transport.flush(true);\n });\n }\n\n // --- identity --------------------------------------------------------------\n\n private loadDeviceId(): string {\n const store = ls();\n let id = store?.getItem(DEVICE_KEY) ?? null;\n if (!id) {\n id = `dev_${randomToken(16)}`;\n store?.setItem(DEVICE_KEY, id);\n }\n return id;\n }\n\n private loadSession(): string {\n const store = ls();\n try {\n const raw = store?.getItem(SESSION_KEY);\n if (raw) {\n const parsed = JSON.parse(raw) as { id: string; last: number };\n if (Date.now() - parsed.last < SESSION_IDLE_MS) {\n this.lastActivity = parsed.last;\n return parsed.id;\n }\n }\n } catch {\n /* ignore */\n }\n const id = prefixedId('sess');\n this.persistSession(id);\n return id;\n }\n\n private persistSession(id: string): void {\n this.lastActivity = Date.now();\n ls()?.setItem(SESSION_KEY, JSON.stringify({ id, last: this.lastActivity }));\n }\n\n private touchSession(): void {\n if (Date.now() - this.lastActivity > SESSION_IDLE_MS) {\n this.sessionId = prefixedId('sess');\n this.seq = 0;\n }\n this.persistSession(this.sessionId);\n }\n\n /** Queue a call made before init() so nothing is lost; returns true if deferred. */\n private deferred(fn: () => void): boolean {\n if (this.started) return false;\n this.preInitQueue.push(fn);\n return true;\n }\n\n identify(userId: string, traits: Record<string, Value> = {}): void {\n if (this.deferred(() => this.identify(userId, traits))) return;\n this.userId = userId;\n this.traits = { ...this.traits, ...traits };\n this.emit('identify', undefined, traits);\n void this.reloadFeatureFlags();\n }\n\n reset(): void {\n // Flush what we have under the OLD identity, then drop everything so no\n // buffered/queued data leaks across the user-switch boundary.\n void this.transport.flush();\n this.transport.clearBuffer();\n this.transport.clearOffline();\n this.exposedKeys.clear();\n this.flags = { ...this.cfg.bootstrapFlags };\n this.userId = null;\n this.traits = {};\n this.groupCtx = null;\n this.superProps = {};\n const store = ls();\n store?.removeItem(SESSION_KEY);\n this.deviceId = `dev_${randomToken(16)}`;\n store?.setItem(DEVICE_KEY, this.deviceId);\n this.sessionId = prefixedId('sess');\n this.seq = 0;\n }\n\n getDeviceId(): string {\n return this.deviceId;\n }\n getSessionId(): string {\n return this.sessionId;\n }\n getSessionReplayUrl(): string {\n return `${this.cfg.apiHost}/replays/${this.sessionId}`;\n }\n\n groupIdentify(type: string, key: string, traits: Record<string, Value> = {}): void {\n if (this.deferred(() => this.groupIdentify(type, key, traits))) return;\n this.groupCtx = { type, key };\n this.emit('group', undefined, { group_type: type, group_key: key, ...traits });\n }\n\n /** Alias for `groupIdentify` (`SDK.md` API parity). */\n group(type: string, key: string, traits: Record<string, Value> = {}): void {\n this.groupIdentify(type, key, traits);\n }\n\n // --- events ----------------------------------------------------------------\n\n register(props: Record<string, Value>): void {\n if (this.deferred(() => this.register(props))) return;\n this.superProps = { ...this.superProps, ...props };\n }\n unregister(key: string): void {\n if (this.deferred(() => this.unregister(key))) return;\n delete this.superProps[key];\n }\n\n track(event: string, props: Record<string, Value> = {}): void {\n if (this.deferred(() => this.track(event, props))) return;\n this.emit('track', event, props);\n }\n\n private emit(type: GlassEvent['type'], event: string | undefined, props: Record<string, Value>): void {\n if (this.optedOut || !this.started) return;\n this.touchSession();\n this.transport.enqueue({\n type,\n ...(event ? { event } : {}),\n seq: this.seq++,\n t_client: new Date().toISOString(),\n props: { ...this.contextProps(), ...this.superProps, ...props },\n });\n }\n\n /** Device/screen context attached to EVERY event (`SDK.md` §4). */\n private contextProps(): Record<string, Value> {\n const ctx: Record<string, Value> = {};\n if (typeof screen !== 'undefined') {\n ctx.$screen_width = screen.width;\n ctx.$screen_height = screen.height;\n }\n if (typeof window !== 'undefined') {\n ctx.$viewport_width = window.innerWidth;\n ctx.$viewport_height = window.innerHeight;\n }\n if (typeof navigator !== 'undefined') {\n ctx.$locale = navigator.language ?? null;\n }\n return ctx;\n }\n\n private pageProps(): Record<string, Value> {\n if (typeof document === 'undefined' || typeof location === 'undefined') return {};\n return { url: location.href, $pathname: location.pathname, referrer: document.referrer };\n }\n\n // --- errors ----------------------------------------------------------------\n\n captureException(error: unknown, context: Record<string, Value> = {}): void {\n if (this.deferred(() => this.captureException(error, context))) return;\n const err = error instanceof Error ? error : new Error(String(error));\n this.emit('error', err.name, {\n message: err.message,\n stack: err.stack ?? '',\n ...context,\n });\n }\n\n /** Breadcrumb with optional category (`SDK.md` API parity). */\n addBreadcrumb(\n arg: string | { category?: string; message: string; data?: Record<string, Value> },\n data: Record<string, Value> = {},\n ): void {\n if (this.deferred(() => this.addBreadcrumb(arg, data))) return;\n if (typeof arg === 'string') {\n this.emit('track', '$breadcrumb', { message: arg, ...data });\n } else {\n this.emit('track', '$breadcrumb', {\n message: arg.message,\n ...(arg.category ? { category: arg.category } : {}),\n ...(arg.data ?? {}),\n });\n }\n }\n\n private installErrorHandlers(): void {\n if (typeof window === 'undefined') return;\n this.addListener(window, 'error', (e) =>\n this.captureException((e as ErrorEvent).error ?? (e as ErrorEvent).message),\n );\n this.addListener(window, 'unhandledrejection', (e) =>\n this.captureException((e as PromiseRejectionEvent).reason),\n );\n }\n\n /**\n * Opt-in console capture (`SDK.md` §5): mirror `console.error`/`console.warn`\n * into Glass (errors as exceptions, warnings as breadcrumbs) while ALWAYS\n * calling through to the original console, so we never swallow the developer's\n * own logs. Restored verbatim on shutdown().\n */\n private installConsoleCapture(): void {\n if (typeof console === 'undefined') return;\n const wrap = (level: 'error' | 'warn') => {\n const original = console[level];\n if (typeof original !== 'function') return;\n console[level] = (...args: unknown[]) => {\n try {\n const first = args[0];\n const message = args\n .map((a) => (typeof a === 'string' ? a : a instanceof Error ? a.message : safeString(a)))\n .join(' ')\n .slice(0, 500);\n if (level === 'error') {\n this.captureException(first instanceof Error ? first : new Error(message), { $console: true });\n } else {\n this.addBreadcrumb({ category: 'console.warn', message });\n }\n } catch {\n /* never let capture break the app's logging */\n }\n return (original as (...a: unknown[]) => void).apply(console, args);\n };\n this.teardowns.push(() => {\n console[level] = original;\n });\n };\n wrap('error');\n wrap('warn');\n }\n\n private rageWindow: number[] = [];\n\n private installAutocapture(): void {\n if (typeof document === 'undefined') return;\n\n this.addListener(\n document,\n 'click',\n (e) => {\n const target = (e as MouseEvent).target as HTMLElement | null;\n if (!target) return;\n this.detectRageClick();\n const el = target.closest('a,button,input[type=submit],[role=button],[data-glass]') as HTMLElement | null;\n if (!el) return;\n this.track('$click', this.elementProps(el));\n },\n { capture: true },\n );\n\n this.addListener(\n document,\n 'submit',\n (e) => {\n const form = (e as SubmitEvent).target as HTMLFormElement | null;\n if (!form || form.tagName !== 'FORM') return;\n // Never capture field VALUES — only structural metadata.\n this.track('$form_submit', {\n form_id: form.id || null,\n form_name: form.getAttribute('name'),\n action: form.getAttribute('action'),\n field_count: form.elements.length,\n });\n },\n { capture: true },\n );\n\n this.installSpaPageviews();\n }\n\n /** Stable, value-free descriptor of a clicked element. */\n private elementProps(el: HTMLElement): Record<string, Value> {\n return {\n tag: el.tagName.toLowerCase(),\n text: (el.textContent ?? '').trim().slice(0, 80),\n href: el instanceof HTMLAnchorElement ? el.href : null,\n el_id: el.id || null,\n el_class: el.getAttribute('class'),\n data_glass: el.getAttribute('data-glass'),\n };\n }\n\n /** Three+ clicks within 1s at roughly one spot = a rage click (frustration signal). */\n private detectRageClick(): void {\n const now = Date.now();\n this.rageWindow = this.rageWindow.filter((t) => now - t < 1000);\n this.rageWindow.push(now);\n if (this.rageWindow.length >= 3) {\n this.rageWindow = [];\n this.track('$rageclick', { url: typeof location !== 'undefined' ? location.href : null });\n }\n }\n\n /** SPA route changes: patch History + listen to popstate, de-duping same-URL. */\n private lastPath = '';\n private installSpaPageviews(): void {\n if (typeof history === 'undefined' || typeof location === 'undefined') return;\n this.lastPath = location.href;\n const fire = () => {\n if (location.href === this.lastPath) return;\n this.lastPath = location.href;\n this.track('$pageview', this.pageProps());\n };\n const wrap = (key: 'pushState' | 'replaceState') => {\n const orig = history[key];\n history[key] = function patched(this: History, ...args: Parameters<History['pushState']>) {\n const ret = orig.apply(this, args);\n // Defer so location has updated before we read it.\n setTimeout(fire, 0);\n return ret;\n } as History[typeof key];\n // Restore the native method on shutdown() so we don't leak a patch.\n this.teardowns.push(() => {\n history[key] = orig;\n });\n };\n wrap('pushState');\n wrap('replaceState');\n this.addListener(window, 'popstate', fire);\n }\n\n // --- session replay control ------------------------------------------------\n\n startSessionRecording(): void {\n void this.replay.start();\n }\n stopSessionRecording(): void {\n void this.replay.stopRecording();\n }\n\n // --- feature flags (deterministic, edge-evaluated) -------------------------\n\n async reloadFeatureFlags(): Promise<void> {\n try {\n const unit = this.userId ?? this.deviceId;\n const res = await fetch(`${this.cfg.apiHost}/v1/sdk/flags?user_id=${encodeURIComponent(unit)}`, {\n headers: { Authorization: `Glass-Key ${this.cfg.projectKey}` },\n });\n if (res.ok) {\n const json = (await res.json()) as { flags?: Record<string, FlagValue> };\n this.flags = { ...this.flags, ...(json.flags ?? {}) };\n }\n } catch {\n /* keep bootstrap/cached flags */\n } finally {\n this.flagsLoaded = true;\n for (const fn of this.flagListeners) fn(this.flags);\n }\n }\n\n onFlagsLoaded(fn: (flags: Record<string, FlagValue>) => void): void {\n this.flagListeners.push(fn);\n if (this.flagsLoaded) fn(this.flags);\n }\n\n /**\n * Resolve a flag value with precedence: locally-evaluated definition (if the\n * app shipped one, so targeting reflects CURRENT properties) → server/bootstrap\n * resolved value → fallback.\n */\n private resolve(key: string, opts?: FlagOptions): FlagValue {\n const local = this.evaluateLocal(key);\n const v = local !== undefined ? local : this.flags[key];\n const value = v !== undefined ? v : opts?.fallback;\n if (value !== undefined && opts?.trackExposure !== false) this.exposure(key, value);\n return value;\n }\n\n /** Local bucketing via @glassanalytics/core when definitions were provided to init(). */\n private evaluateLocal(key: string): FlagValue {\n const def = this.cfg.flagDefinitions.find((d: FlagDefinition) => d.key === key);\n if (!def) return undefined;\n const properties: Record<string, ScalarValue> = {};\n for (const [k, val] of Object.entries(this.traits)) {\n if (val === null || typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean') {\n properties[k] = val as ScalarValue;\n }\n }\n return evaluateFlag(def, { unitId: this.userId ?? this.deviceId, properties });\n }\n\n isFeatureEnabledSync(key: string, opts?: FlagOptions): boolean {\n const v = this.resolve(key, opts);\n return v === true || (typeof v === 'string' && v !== '');\n }\n async isFeatureEnabled(key: string, opts?: FlagOptions): Promise<boolean> {\n if (!this.flagsLoaded) await this.reloadFeatureFlags();\n return this.isFeatureEnabledSync(key, opts);\n }\n getFeatureFlagSync(key: string, opts?: FlagOptions): FlagValue {\n return this.resolve(key, opts);\n }\n async getFeatureFlag(key: string, opts?: FlagOptions): Promise<FlagValue> {\n if (!this.flagsLoaded) await this.reloadFeatureFlags();\n return this.getFeatureFlagSync(key, opts);\n }\n getVariantSync(key: string, opts?: FlagOptions): FlagValue {\n return this.resolve(key, opts);\n }\n async getVariant(key: string, opts?: FlagOptions): Promise<FlagValue> {\n if (!this.flagsLoaded) await this.reloadFeatureFlags();\n return this.getVariantSync(key, opts);\n }\n\n /** Fire a `$exposure` once per (flag, value) so experiment analysis is honest (§8). */\n private exposedKeys = new Set<string>();\n private exposure(key: string, value: FlagValue): void {\n const k = `${key}=${String(value)}`;\n if (this.exposedKeys.has(k)) return;\n this.exposedKeys.add(k);\n this.emit('exposure', key, { $feature_flag: key, $feature_flag_value: String(value) });\n }\n\n // --- consent ---------------------------------------------------------------\n\n optIn(): void {\n this.optedOut = false;\n this.afterConsent();\n }\n optOut(): void {\n this.optedOut = true;\n // Discard anything buffered/queued the moment consent is withdrawn.\n this.transport.clearBuffer();\n this.transport.clearOffline();\n void this.replay.stopRecording();\n }\n hasConsent(): boolean {\n return !this.optedOut;\n }\n\n // --- lifecycle -------------------------------------------------------------\n\n flush(): Promise<void> {\n return this.transport.flush();\n }\n shutdown(): void {\n void this.transport.flush(true);\n void this.replay.stopRecording();\n // Remove every listener/patch we installed (in reverse) so re-init or a SPA\n // teardown leaves the page exactly as we found it.\n for (const off of this.teardowns.splice(0, this.teardowns.length).reverse()) {\n try {\n off();\n } catch {\n /* best-effort cleanup */\n }\n }\n this.transport.destroy();\n this.started = false;\n }\n}\n\n/** JSON-stringify that never throws (cyclic refs, BigInt, etc.) for console capture. */\nfunction safeString(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** Default singleton, mirroring the ergonomic `glass.init(...)` usage in `SDK.md`. */\nexport const glass = new Glass();\nexport default glass;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/replay-encoder.ts","../src/replay.ts","../src/offline-store.ts","../src/transport.ts","../src/index.ts"],"names":["ls"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Off-main-thread replay-segment encoder (`SDK.md` §6). rrweb segments are large\n * and highly repetitive, so we (a) JSON-serialize and (b) gzip them in a Web\n * Worker — keeping both the (potentially multi-MB) stringify and the compression\n * off the page's main thread. Everything degrades gracefully: no Worker → encode\n * on the main thread; no `CompressionStream` → send uncompressed JSON. The result\n * is the same bytes the ingest endpoint already accepts, just optionally gzipped\n * (signalled to callers via `gzip`, which they translate to `Content-Encoding`).\n */\n\nexport interface EncodedSegment {\n body: Uint8Array | string;\n gzip: boolean;\n}\n\n/**\n * Worker body, kept dependency-free so it can be inlined via a Blob URL (no\n * separate build step / bundler entry). It receives `{ id, json }`, gzips when\n * possible, and posts back `{ id, buf, gzip }` transferring the buffer.\n */\nconst WORKER_SRC = `\nself.onmessage = async function (e) {\n var id = e.data.id, json = e.data.json;\n try {\n var bytes = new TextEncoder().encode(json);\n if (typeof CompressionStream !== 'undefined') {\n var cs = new CompressionStream('gzip');\n var w = cs.writable.getWriter();\n w.write(bytes); w.close();\n var buf = await new Response(cs.readable).arrayBuffer();\n self.postMessage({ id: id, buf: buf, gzip: true }, [buf]);\n } else {\n self.postMessage({ id: id, buf: bytes.buffer, gzip: false }, [bytes.buffer]);\n }\n } catch (err) {\n self.postMessage({ id: id, error: String(err) });\n }\n};\n`;\n\ninterface WorkerReply {\n id: number;\n buf?: ArrayBuffer;\n gzip?: boolean;\n error?: string;\n}\n\nexport class ReplayEncoder {\n private worker: Worker | null = null;\n private workerUrl: string | null = null;\n private workerBroken = false;\n private nextId = 1;\n private pending = new Map<number, (r: WorkerReply) => void>();\n\n /** Lazily spin up the encode worker; null if Workers/Blob URLs aren't available. */\n private ensureWorker(): Worker | null {\n if (this.worker || this.workerBroken) return this.worker;\n try {\n if (typeof Worker === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined') {\n this.workerBroken = true;\n return null;\n }\n this.workerUrl = URL.createObjectURL(new Blob([WORKER_SRC], { type: 'text/javascript' }));\n this.worker = new Worker(this.workerUrl);\n this.worker.onmessage = (ev: MessageEvent<WorkerReply>) => {\n const resolve = this.pending.get(ev.data.id);\n if (resolve) {\n this.pending.delete(ev.data.id);\n resolve(ev.data);\n }\n };\n this.worker.onerror = () => {\n // A broken worker disables itself; future encodes run on the main thread.\n this.workerBroken = true;\n for (const [, resolve] of this.pending) resolve({ id: -1, error: 'worker_error' });\n this.pending.clear();\n };\n return this.worker;\n } catch {\n this.workerBroken = true;\n return null;\n }\n }\n\n async encode(segment: unknown): Promise<EncodedSegment> {\n let json: string;\n try {\n json = JSON.stringify(segment);\n } catch {\n json = '[]';\n }\n\n const worker = this.ensureWorker();\n if (worker) {\n try {\n const reply = await this.postToWorker(worker, json);\n if (!reply.error && reply.buf) {\n return { body: new Uint8Array(reply.buf), gzip: reply.gzip === true };\n }\n } catch {\n /* fall through to main-thread encoding */\n }\n }\n return this.encodeMainThread(json);\n }\n\n private postToWorker(worker: Worker, json: string): Promise<WorkerReply> {\n const id = this.nextId++;\n return new Promise<WorkerReply>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error('encode_timeout'));\n }, 2000);\n this.pending.set(id, (r) => {\n clearTimeout(timeout);\n resolve(r);\n });\n worker.postMessage({ id, json });\n });\n }\n\n /** Main-thread fallback: gzip via CompressionStream when present, else raw JSON. */\n private async encodeMainThread(json: string): Promise<EncodedSegment> {\n const CS = (globalThis as { CompressionStream?: typeof CompressionStream }).CompressionStream;\n if (typeof CS !== 'undefined') {\n try {\n const cs = new CS('gzip');\n const writer = cs.writable.getWriter();\n void writer.write(new TextEncoder().encode(json));\n void writer.close();\n const buf = await new Response(cs.readable).arrayBuffer();\n return { body: new Uint8Array(buf), gzip: true };\n } catch {\n /* fall through to uncompressed */\n }\n }\n return { body: json, gzip: false };\n }\n\n dispose(): void {\n this.worker?.terminate();\n this.worker = null;\n if (this.workerUrl) {\n try {\n URL.revokeObjectURL(this.workerUrl);\n } catch {\n /* ignore */\n }\n this.workerUrl = null;\n }\n this.pending.clear();\n }\n}\n","import { replaySegmentPath } from '@glassanalytics/core';\nimport type { ResolvedConfig } from './types.js';\nimport { ReplayEncoder } from './replay-encoder.js';\n\n/**\n * Session replay (`SDK.md` §6). rrweb is loaded LAZILY (dynamic import) so apps\n * that don't record pay nothing. Recording is MASKED BY DEFAULT — all inputs\n * masked, configurable text/blocked selectors — and segments are streamed to the\n * ingest `/v1/replay/:session/:seq` endpoint, not buffered in memory.\n */\n/** Input types/name patterns ALWAYS masked, even when maskAllInputs is false. */\nconst SENSITIVE_INPUT_TYPES = new Set(['password', 'email', 'tel', 'hidden']);\nconst SENSITIVE_NAME_RE = /pass|secret|token|ssn|card|cvv|cvc|account|email|phone|tax/i;\n\nexport class ReplayRecorder {\n private stop: (() => void) | null = null;\n private seq = 0;\n private events: unknown[] = [];\n private interval: ReturnType<typeof setInterval> | null = null;\n private boundFinal: (() => void) | null = null;\n private encoder = new ReplayEncoder();\n /** rrweb's addCustomEvent, captured on start — lets us weave Glass events into the stream. */\n private addCustom: ((tag: string, payload: unknown) => void) | null = null;\n\n constructor(\n private cfg: ResolvedConfig,\n private getSessionId: () => string,\n ) {}\n\n async start(): Promise<void> {\n if (this.stop) return;\n if (typeof window === 'undefined') return;\n const { record } = await import('rrweb');\n const rec = record as unknown as { addCustomEvent?: (tag: string, payload: unknown) => void };\n this.addCustom = typeof rec.addCustomEvent === 'function' ? rec.addCustomEvent.bind(record) : null;\n this.stop =\n record({\n emit: (event: unknown) => {\n this.events.push(event);\n if (this.events.length >= 50) void this.flushSegment();\n },\n // Privacy defaults: never leak user input.\n maskAllInputs: this.cfg.maskAllInputs,\n maskTextSelector: this.cfg.maskTextSelector,\n blockSelector: this.cfg.blockSelector,\n // ALWAYS mask sensitive fields regardless of maskAllInputs (defense in depth).\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.cfg.maskAllInputs) return '*'.repeat(text.length);\n const type = (element.getAttribute('type') ?? '').toLowerCase();\n const name = `${element.getAttribute('name') ?? ''} ${element.getAttribute('autocomplete') ?? ''} ${element.id}`;\n if (SENSITIVE_INPUT_TYPES.has(type) || SENSITIVE_NAME_RE.test(name)) return '*'.repeat(text.length);\n return text;\n },\n recordCanvas: false,\n collectFonts: false,\n }) ?? null;\n\n this.interval = setInterval(() => void this.flushSegment(), 5000);\n // Final segment on unload via beacon (fetch is unreliable during teardown).\n this.boundFinal = () => this.flushFinalBeacon();\n window.addEventListener('pagehide', this.boundFinal);\n }\n\n /**\n * Weave a Glass event into the rrweb stream as a Custom (type 5) event, so the\n * player can render it as a timeline marker (`UI.md` §4.1). No-op unless we're\n * actively recording. Payload is kept tiny (name + optional level) to avoid\n * bloating replay segments.\n */\n addEvent(name: string, payload: { event: string; level?: string }): void {\n if (!this.stop || !this.addCustom) return;\n try {\n this.addCustom(name, payload);\n } catch {\n /* a dropped marker is non-fatal */\n }\n }\n\n private async flushSegment(): Promise<void> {\n if (this.events.length === 0) return;\n const segment = this.events.splice(0, this.events.length);\n const seq = this.seq++;\n const url = `${this.cfg.ingestHost}${replaySegmentPath(this.getSessionId(), seq)}`;\n\n // Serialize + gzip OFF the main thread (Web Worker) so a big segment never\n // janks the page; on any failure we fall back to plain JSON. Compression is\n // a large COGS/bandwidth win (rrweb segments are very repetitive).\n const encoded = await this.encoder.encode(segment);\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Glass-Key ${this.cfg.projectKey}`,\n };\n if (encoded.gzip) headers['Content-Encoding'] = 'gzip';\n\n try {\n await fetch(url, {\n method: 'POST',\n keepalive: true,\n headers,\n body: encoded.body as BodyInit,\n });\n } catch {\n // a dropped replay segment is non-fatal; the player tolerates gaps.\n }\n }\n\n /** Flush the trailing segment with sendBeacon so it survives page teardown. */\n private flushFinalBeacon(): void {\n if (this.events.length === 0) return;\n const segment = this.events.splice(0, this.events.length);\n const seq = this.seq++;\n const url = `${this.cfg.ingestHost}${replaySegmentPath(this.getSessionId(), seq)}?k=${encodeURIComponent(this.cfg.projectKey)}`;\n const payload = JSON.stringify(segment);\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n navigator.sendBeacon(url, payload);\n }\n }\n\n async stopRecording(): Promise<void> {\n await this.flushSegment();\n this.stop?.();\n this.stop = null;\n this.addCustom = null;\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n if (this.boundFinal && typeof window !== 'undefined') {\n window.removeEventListener('pagehide', this.boundFinal);\n this.boundFinal = null;\n }\n this.encoder.dispose();\n }\n\n get recording(): boolean {\n return this.stop !== null;\n }\n}\n","import type { QueuedBatch } from './transport.js';\n\n/**\n * Durable offline queue for event batches (`SDK.md` §10). Prefers IndexedDB\n * (larger quota, survives reloads) and transparently falls back to localStorage\n * when IDB is unavailable (private mode / old browsers) and to an in-memory\n * array when neither is present (SSR/tests). Only already-masked payloads are\n * stored, entries are TTL'd, and the queue is size-capped.\n */\n\nconst DB_NAME = 'glass';\nconst STORE = 'offline_q';\nconst LS_KEY = 'glass_offline_q';\n\nexport class OfflineStore {\n private mem: QueuedBatch[] = [];\n private dbPromise: Promise<IDBDatabase> | null = null;\n\n constructor(\n private max: number,\n private ttlMs: number,\n ) {}\n\n private idb(): Promise<IDBDatabase> | null {\n if (typeof indexedDB === 'undefined') return null;\n if (!this.dbPromise) {\n this.dbPromise = new Promise<IDBDatabase>((resolve, reject) => {\n const req = indexedDB.open(DB_NAME, 1);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(STORE)) db.createObjectStore(STORE, { autoIncrement: true });\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n }).catch((err) => {\n // Disable IDB for the rest of the session on failure.\n this.dbPromise = null;\n throw err;\n });\n }\n return this.dbPromise;\n }\n\n private fresh(items: QueuedBatch[]): QueuedBatch[] {\n const cutoff = Date.now() - this.ttlMs;\n const kept = items.filter((b) => b.at >= cutoff);\n return kept.length > this.max ? kept.slice(kept.length - this.max) : kept;\n }\n\n async append(batch: QueuedBatch): Promise<void> {\n try {\n const db = await this.idb();\n if (db) {\n await this.idbWrite(db, batch);\n return;\n }\n } catch {\n /* fall through to localStorage */\n }\n if (this.tryLS((q) => this.fresh([...q, batch]))) return;\n this.mem = this.fresh([...this.mem, batch]);\n }\n\n async drain(): Promise<QueuedBatch[]> {\n try {\n const db = await this.idb();\n if (db) return this.fresh(await this.idbDrain(db));\n } catch {\n /* fall through */\n }\n const ls = this.readLS();\n if (ls !== null) {\n this.writeLS([]);\n return this.fresh(ls);\n }\n const m = this.mem;\n this.mem = [];\n return this.fresh(m);\n }\n\n async clear(): Promise<void> {\n this.mem = [];\n try {\n const db = await this.idb();\n if (db) {\n await new Promise<void>((resolve) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => resolve();\n });\n }\n } catch {\n /* ignore */\n }\n this.writeLS([]);\n }\n\n // --- IndexedDB helpers ------------------------------------------------------\n\n private idbWrite(db: IDBDatabase, batch: QueuedBatch): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).add(batch);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n private idbDrain(db: IDBDatabase): Promise<QueuedBatch[]> {\n return new Promise<QueuedBatch[]>((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n const store = tx.objectStore(STORE);\n const getAll = store.getAll();\n getAll.onsuccess = () => {\n store.clear();\n resolve((getAll.result as QueuedBatch[]) ?? []);\n };\n getAll.onerror = () => reject(getAll.error);\n });\n }\n\n // --- localStorage fallback --------------------------------------------------\n\n private readLS(): QueuedBatch[] | null {\n if (typeof localStorage === 'undefined') return null;\n try {\n const raw = localStorage.getItem(LS_KEY);\n return raw ? (JSON.parse(raw) as QueuedBatch[]) : [];\n } catch {\n return null;\n }\n }\n\n private writeLS(q: QueuedBatch[]): void {\n if (typeof localStorage === 'undefined') return;\n try {\n localStorage.setItem(LS_KEY, JSON.stringify(q));\n } catch {\n /* storage full/disabled — drop silently */\n }\n }\n\n private tryLS(update: (q: QueuedBatch[]) => QueuedBatch[]): boolean {\n const cur = this.readLS();\n if (cur === null) return false;\n this.writeLS(update(cur));\n return true;\n }\n}\n","import { INGEST_AUTH_SCHEME, type IngestBatch } from '@glassanalytics/core';\nimport { OfflineStore } from './offline-store.js';\nimport type { GlassEvent, ResolvedConfig } from './types.js';\n\n/**\n * Reliable, cheap transport (`SDK.md` §10): batch on a timer/size, use\n * `sendBeacon` on unload, queue offline, and BACK OFF (exponential + jitter) on\n * failures. Under memory pressure we drop the LOWEST-value events first so\n * high-signal events (errors, identify, exposure) survive. The goal is to never\n * block the app's main work and never lose more than the lowest-value tail.\n */\n\nconst QUEUE_TTL_MS = 24 * 3_600_000;\nconst QUEUE_MAX = 500;\n/** In-memory ceiling before value-based shedding kicks in. */\nconst BUFFER_MAX = 1000;\nconst BACKOFF_BASE_MS = 1000;\nconst BACKOFF_CAP_MS = 5 * 60_000;\n\ninterface QueuedBatch {\n at: number;\n body: IngestBatch;\n}\n\n/** Priority for value-based backpressure — higher survives shedding. */\nfunction eventValue(e: GlassEvent): number {\n switch (e.type) {\n case 'error':\n return 100;\n case 'identify':\n case 'group':\n return 90;\n case 'exposure':\n return 80;\n case 'track':\n // Autocapture / passive pageviews are the most sheddable.\n return e.event === '$autocapture' || e.event === '$pageview' ? 10 : 50;\n default:\n return 40;\n }\n}\n\nexport class Transport {\n private buffer: GlassEvent[] = [];\n private timer: ReturnType<typeof setTimeout> | null = null;\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n private backoffUntil = 0;\n private failures = 0;\n private store = new OfflineStore(QUEUE_MAX, QUEUE_TTL_MS);\n\n private onPageHide = () => void this.flush(true);\n private onOnline = () => void this.drainOffline();\n\n constructor(\n private cfg: ResolvedConfig,\n private getIdentity: () => Pick<IngestBatch, 'device_id' | 'session_id' | 'user_id' | 'traits' | 'group'>,\n ) {\n if (typeof window !== 'undefined') {\n window.addEventListener('pagehide', this.onPageHide);\n window.addEventListener('online', this.onOnline);\n }\n }\n\n /** Remove window listeners and pending timers (called from Glass.shutdown()). */\n destroy(): void {\n if (typeof window !== 'undefined') {\n window.removeEventListener('pagehide', this.onPageHide);\n window.removeEventListener('online', this.onOnline);\n }\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n if (this.retryTimer) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n }\n\n enqueue(event: GlassEvent): void {\n const finalEvent = this.cfg.beforeSend(event);\n if (!finalEvent) return; // dropped by beforeSend\n this.buffer.push(finalEvent);\n this.applyBackpressure();\n if (this.buffer.length >= this.cfg.flushAt) {\n void this.flush();\n } else if (!this.timer) {\n this.timer = setTimeout(() => void this.flush(), this.cfg.flushIntervalMs);\n }\n }\n\n /**\n * Cap the in-memory buffer by shedding the lowest-value events when it grows\n * past BUFFER_MAX (e.g. a long offline burst of autocapture). Errors and\n * identity events are kept preferentially.\n */\n private applyBackpressure(): void {\n if (this.buffer.length <= BUFFER_MAX) return;\n // Stable sort by value descending, keep the top BUFFER_MAX, preserve order.\n const indexed = this.buffer.map((e, i) => ({ e, i }));\n indexed.sort((a, b) => eventValue(b.e) - eventValue(a.e) || a.i - b.i);\n const kept = indexed.slice(0, BUFFER_MAX).sort((a, b) => a.i - b.i);\n this.buffer = kept.map((x) => x.e);\n }\n\n async flush(useBeacon = false): Promise<void> {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n if (this.buffer.length === 0) return;\n const events = this.buffer.splice(0, this.buffer.length);\n const body: IngestBatch = {\n sent_at: new Date().toISOString(),\n ...this.getIdentity(),\n events,\n };\n\n // Respect server backpressure: persist for a scheduled retry rather than hammer.\n if (Date.now() < this.backoffUntil) {\n await this.store.append({ at: Date.now(), body });\n this.scheduleRetry();\n return;\n }\n await this.send(body, useBeacon);\n }\n\n private async send(body: IngestBatch, useBeacon: boolean): Promise<void> {\n const url = `${this.cfg.ingestHost}/v1/batch`;\n const payload = JSON.stringify(body);\n\n if (useBeacon && typeof navigator !== 'undefined' && navigator.sendBeacon) {\n // Beacon can't set Authorization; the key rides as a query param fallback.\n navigator.sendBeacon(`${url}?k=${encodeURIComponent(this.cfg.projectKey)}`, payload);\n return;\n }\n\n try {\n const res = await fetch(url, {\n method: 'POST',\n keepalive: true,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `${INGEST_AUTH_SCHEME} ${this.cfg.projectKey}`,\n },\n body: payload,\n });\n if (res.status === 429) {\n const retry = Number(res.headers.get('retry-after') ?? '0');\n this.failures++;\n this.backoffUntil = Date.now() + (retry > 0 ? retry * 1000 : this.backoffMs());\n await this.store.append({ at: Date.now(), body });\n this.scheduleRetry();\n } else if (res.status >= 500) {\n // Server-side failure: back off (exp + jitter) and retry the batch later.\n this.failures++;\n this.backoffUntil = Date.now() + this.backoffMs();\n await this.store.append({ at: Date.now(), body });\n this.scheduleRetry();\n } else {\n // 2xx (and non-retryable 4xx) — the batch is done; clear the failure streak.\n this.failures = 0;\n }\n } catch {\n // Offline / network error → persist for the next online drain + retry.\n this.failures++;\n this.backoffUntil = Date.now() + this.backoffMs();\n await this.store.append({ at: Date.now(), body });\n this.scheduleRetry();\n }\n }\n\n /** Exponential backoff with full jitter, capped. */\n private backoffMs(): number {\n const exp = Math.min(BACKOFF_CAP_MS, BACKOFF_BASE_MS * 2 ** Math.min(this.failures, 12));\n return Math.floor(Math.random() * exp);\n }\n\n private scheduleRetry(): void {\n if (this.retryTimer) return;\n const delay = Math.max(0, this.backoffUntil - Date.now()) + 250;\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n void this.drainOffline();\n }, delay);\n }\n\n // --- durable offline queue (masked data only; TTL'd; size-capped) ----------\n\n async drainOffline(): Promise<void> {\n if (Date.now() < this.backoffUntil) {\n this.scheduleRetry();\n return;\n }\n const q = await this.store.drain();\n for (const item of q) {\n if (Date.now() < this.backoffUntil) {\n // Backoff re-armed mid-drain: re-persist the remainder and reschedule.\n await this.store.append(item);\n this.scheduleRetry();\n return;\n }\n await this.send(item.body, false);\n }\n }\n\n /** optOut/reset clears any queued (but already-masked) payloads. */\n clearOffline(): void {\n void this.store.clear();\n }\n\n /** Drop the in-memory buffer so no buffered PII survives optOut()/reset(). */\n clearBuffer(): void {\n this.buffer = [];\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n }\n}\n\nexport type { QueuedBatch };\n","import { type FlagDefinition, type ScalarValue, type Value, evaluateFlag, prefixedId, randomToken } from '@glassanalytics/core';\nimport { ReplayRecorder } from './replay.js';\nimport { Transport } from './transport.js';\nimport type { FlagOptions, FlagValue, GlassConfig, GlassEvent, ResolvedConfig } from './types.js';\n\nexport type { GlassConfig, GlassEvent, FlagValue, FlagOptions } from './types.js';\n\nconst SESSION_IDLE_MS = 30 * 60_000;\nconst DEVICE_KEY = 'glass_device_id';\nconst SESSION_KEY = 'glass_session';\n\nfunction ls(): Storage | null {\n try {\n return typeof localStorage !== 'undefined' ? localStorage : null;\n } catch {\n return null;\n }\n}\n\n/**\n * The Glass browser client (`SDK.md` §3). One small object: identity, events,\n * errors, replay and flags. Non-blocking by construction; nothing here should\n * ever be on the app's critical path.\n */\nexport class Glass {\n private cfg!: ResolvedConfig;\n private transport!: Transport;\n private replay!: ReplayRecorder;\n private deviceId = '';\n private sessionId = '';\n private userId: string | null = null;\n private traits: Record<string, Value> = {};\n private groupCtx: { type: string; key: string } | null = null;\n private superProps: Record<string, Value> = {};\n private seq = 0;\n private lastActivity = 0;\n private flags: Record<string, FlagValue> = {};\n private flagsLoaded = false;\n private flagListeners: Array<(flags: Record<string, FlagValue>) => void> = [];\n private optedOut = false;\n private started = false;\n /** Calls made before init() are queued and replayed once started (`SDK.md` §2). */\n private preInitQueue: Array<() => void> = [];\n /** Removers for every listener/patch we install, so shutdown() leaves no trace. */\n private teardowns: Array<() => void> = [];\n\n init(config: GlassConfig): void {\n if (this.started) return;\n this.cfg = {\n projectKey: config.projectKey,\n ingestHost: config.ingestHost ?? 'https://in.glass.dev',\n apiHost: config.apiHost ?? 'https://api.glass.dev',\n replay: config.replay ?? true,\n autocapture: config.autocapture ?? true,\n errors: config.errors ?? true,\n captureConsole: config.captureConsole ?? false,\n sampleRate: config.sampleRate ?? 1,\n consent: config.consent ?? 'implied',\n maskAllInputs: config.maskAllInputs ?? true,\n maskTextSelector: config.maskTextSelector,\n blockSelector: config.blockSelector,\n respectDoNotTrack: config.respectDoNotTrack ?? true,\n flushIntervalMs: config.flushIntervalMs ?? 5000,\n flushAt: config.flushAt ?? 25,\n beforeSend: config.beforeSend ?? ((e) => e),\n bootstrapFlags: config.bootstrapFlags ?? {},\n flagDefinitions: config.flagDefinitions ?? [],\n };\n this.flags = { ...this.cfg.bootstrapFlags };\n\n if (this.cfg.respectDoNotTrack && typeof navigator !== 'undefined' && navigator.doNotTrack === '1') {\n this.optedOut = true;\n }\n\n this.deviceId = this.loadDeviceId();\n this.sessionId = this.loadSession();\n this.transport = new Transport(this.cfg, () => ({\n device_id: this.deviceId,\n session_id: this.sessionId,\n ...(this.userId ? { user_id: this.userId } : {}),\n traits: this.traits,\n ...(this.groupCtx ? { group: this.groupCtx } : {}),\n }));\n this.replay = new ReplayRecorder(this.cfg, () => this.sessionId);\n this.started = true;\n\n if (this.optedOut || (this.cfg.consent === 'opt-in')) {\n // No collection until optIn() is called.\n } else {\n this.afterConsent();\n }\n void this.reloadFeatureFlags();\n\n // Replay any calls made before init() resolved, in order.\n const queued = this.preInitQueue.splice(0, this.preInitQueue.length);\n for (const fn of queued) fn();\n }\n\n private afterConsent(): void {\n if (this.cfg.errors) this.installErrorHandlers();\n if (this.cfg.autocapture) this.installAutocapture();\n if (this.cfg.captureConsole) this.installConsoleCapture();\n this.installVisibilityFlush();\n if (this.cfg.replay && Math.random() < this.cfg.sampleRate) void this.replay.start();\n void this.transport.drainOffline();\n this.track('$pageview', this.pageProps());\n // Deliver the first pageview immediately (batched with anything queued during\n // init) so a fast bounce — open then close within the flush window — still\n // records the view, instead of relying only on the lossy pagehide beacon.\n this.flushSoon();\n }\n\n /**\n * Flush once on the next microtask. Runs after init()'s synchronous work\n * (pre-init queue drain + any `track()` right after `init()`), so the initial\n * pageview and those events go out in ONE batch, within a tick of load.\n */\n private initialFlushScheduled = false;\n private flushSoon(): void {\n if (this.initialFlushScheduled) return;\n this.initialFlushScheduled = true;\n const run = () => {\n this.initialFlushScheduled = false;\n void this.transport.flush();\n };\n if (typeof queueMicrotask === 'function') queueMicrotask(run);\n else void Promise.resolve().then(run);\n }\n\n /** Register a DOM listener and remember how to remove it on shutdown(). */\n private addListener(\n target: EventTarget,\n type: string,\n handler: EventListenerOrEventListenerObject,\n opts?: AddEventListenerOptions | boolean,\n ): void {\n target.addEventListener(type, handler, opts);\n this.teardowns.push(() => target.removeEventListener(type, handler, opts));\n }\n\n /**\n * Flush on tab hide (`SDK.md` §10). `visibilitychange`→hidden is the most\n * reliable \"user is leaving\" signal on mobile (where `pagehide`/`unload` are\n * unreliable), so we drain the buffer with a beacon while we still can.\n */\n private installVisibilityFlush(): void {\n if (typeof document === 'undefined') return;\n this.addListener(document, 'visibilitychange', () => {\n if (document.visibilityState === 'hidden') void this.transport.flush(true);\n });\n }\n\n // --- identity --------------------------------------------------------------\n\n private loadDeviceId(): string {\n const store = ls();\n let id = store?.getItem(DEVICE_KEY) ?? null;\n if (!id) {\n id = `dev_${randomToken(16)}`;\n store?.setItem(DEVICE_KEY, id);\n }\n return id;\n }\n\n private loadSession(): string {\n const store = ls();\n try {\n const raw = store?.getItem(SESSION_KEY);\n if (raw) {\n const parsed = JSON.parse(raw) as { id: string; last: number };\n if (Date.now() - parsed.last < SESSION_IDLE_MS) {\n this.lastActivity = parsed.last;\n return parsed.id;\n }\n }\n } catch {\n /* ignore */\n }\n const id = prefixedId('sess');\n this.persistSession(id);\n return id;\n }\n\n private persistSession(id: string): void {\n this.lastActivity = Date.now();\n ls()?.setItem(SESSION_KEY, JSON.stringify({ id, last: this.lastActivity }));\n }\n\n private touchSession(): void {\n if (Date.now() - this.lastActivity > SESSION_IDLE_MS) {\n this.sessionId = prefixedId('sess');\n this.seq = 0;\n }\n this.persistSession(this.sessionId);\n }\n\n /** Queue a call made before init() so nothing is lost; returns true if deferred. */\n private deferred(fn: () => void): boolean {\n if (this.started) return false;\n this.preInitQueue.push(fn);\n return true;\n }\n\n identify(userId: string, traits: Record<string, Value> = {}): void {\n if (this.deferred(() => this.identify(userId, traits))) return;\n this.userId = userId;\n this.traits = { ...this.traits, ...traits };\n this.emit('identify', undefined, traits);\n void this.reloadFeatureFlags();\n }\n\n reset(): void {\n // Flush what we have under the OLD identity, then drop everything so no\n // buffered/queued data leaks across the user-switch boundary.\n void this.transport.flush();\n this.transport.clearBuffer();\n this.transport.clearOffline();\n this.exposedKeys.clear();\n this.flags = { ...this.cfg.bootstrapFlags };\n this.userId = null;\n this.traits = {};\n this.groupCtx = null;\n this.superProps = {};\n const store = ls();\n store?.removeItem(SESSION_KEY);\n this.deviceId = `dev_${randomToken(16)}`;\n store?.setItem(DEVICE_KEY, this.deviceId);\n this.sessionId = prefixedId('sess');\n this.seq = 0;\n }\n\n getDeviceId(): string {\n return this.deviceId;\n }\n getSessionId(): string {\n return this.sessionId;\n }\n getSessionReplayUrl(): string {\n return `${this.cfg.apiHost}/replays/${this.sessionId}`;\n }\n\n groupIdentify(type: string, key: string, traits: Record<string, Value> = {}): void {\n if (this.deferred(() => this.groupIdentify(type, key, traits))) return;\n this.groupCtx = { type, key };\n this.emit('group', undefined, { group_type: type, group_key: key, ...traits });\n }\n\n /** Alias for `groupIdentify` (`SDK.md` API parity). */\n group(type: string, key: string, traits: Record<string, Value> = {}): void {\n this.groupIdentify(type, key, traits);\n }\n\n // --- events ----------------------------------------------------------------\n\n register(props: Record<string, Value>): void {\n if (this.deferred(() => this.register(props))) return;\n this.superProps = { ...this.superProps, ...props };\n }\n unregister(key: string): void {\n if (this.deferred(() => this.unregister(key))) return;\n delete this.superProps[key];\n }\n\n track(event: string, props: Record<string, Value> = {}): void {\n if (this.deferred(() => this.track(event, props))) return;\n this.emit('track', event, props);\n }\n\n private emit(type: GlassEvent['type'], event: string | undefined, props: Record<string, Value>): void {\n if (this.optedOut || !this.started) return;\n this.touchSession();\n this.transport.enqueue({\n type,\n ...(event ? { event } : {}),\n seq: this.seq++,\n t_client: new Date().toISOString(),\n props: { ...this.contextProps(), ...this.superProps, ...props },\n });\n // Mirror the event onto the replay timeline as a lightweight marker (errors\n // flagged so the player's \"jump to error\" works). No-op unless recording.\n if (this.cfg.replay) {\n const name = event ?? type;\n this.replay.addEvent(name, { event: name, ...(type === 'error' ? { level: 'error' } : {}) });\n }\n }\n\n /** Device/screen context attached to EVERY event (`SDK.md` §4). */\n private contextProps(): Record<string, Value> {\n const ctx: Record<string, Value> = {};\n if (typeof screen !== 'undefined') {\n ctx.$screen_width = screen.width;\n ctx.$screen_height = screen.height;\n }\n if (typeof window !== 'undefined') {\n ctx.$viewport_width = window.innerWidth;\n ctx.$viewport_height = window.innerHeight;\n }\n if (typeof navigator !== 'undefined') {\n ctx.$locale = navigator.language ?? null;\n }\n return ctx;\n }\n\n private pageProps(): Record<string, Value> {\n if (typeof document === 'undefined' || typeof location === 'undefined') return {};\n return { url: location.href, $pathname: location.pathname, referrer: document.referrer };\n }\n\n // --- errors ----------------------------------------------------------------\n\n captureException(error: unknown, context: Record<string, Value> = {}): void {\n if (this.deferred(() => this.captureException(error, context))) return;\n const err = error instanceof Error ? error : new Error(String(error));\n this.emit('error', err.name, {\n message: err.message,\n stack: err.stack ?? '',\n ...context,\n });\n }\n\n /** Breadcrumb with optional category (`SDK.md` API parity). */\n addBreadcrumb(\n arg: string | { category?: string; message: string; data?: Record<string, Value> },\n data: Record<string, Value> = {},\n ): void {\n if (this.deferred(() => this.addBreadcrumb(arg, data))) return;\n if (typeof arg === 'string') {\n this.emit('track', '$breadcrumb', { message: arg, ...data });\n } else {\n this.emit('track', '$breadcrumb', {\n message: arg.message,\n ...(arg.category ? { category: arg.category } : {}),\n ...(arg.data ?? {}),\n });\n }\n }\n\n private installErrorHandlers(): void {\n if (typeof window === 'undefined') return;\n this.addListener(window, 'error', (e) =>\n this.captureException((e as ErrorEvent).error ?? (e as ErrorEvent).message),\n );\n this.addListener(window, 'unhandledrejection', (e) =>\n this.captureException((e as PromiseRejectionEvent).reason),\n );\n }\n\n /**\n * Opt-in console capture (`SDK.md` §5): mirror `console.error`/`console.warn`\n * into Glass (errors as exceptions, warnings as breadcrumbs) while ALWAYS\n * calling through to the original console, so we never swallow the developer's\n * own logs. Restored verbatim on shutdown().\n */\n private installConsoleCapture(): void {\n if (typeof console === 'undefined') return;\n const wrap = (level: 'error' | 'warn') => {\n const original = console[level];\n if (typeof original !== 'function') return;\n console[level] = (...args: unknown[]) => {\n try {\n const first = args[0];\n const message = args\n .map((a) => (typeof a === 'string' ? a : a instanceof Error ? a.message : safeString(a)))\n .join(' ')\n .slice(0, 500);\n if (level === 'error') {\n this.captureException(first instanceof Error ? first : new Error(message), { $console: true });\n } else {\n this.addBreadcrumb({ category: 'console.warn', message });\n }\n } catch {\n /* never let capture break the app's logging */\n }\n return (original as (...a: unknown[]) => void).apply(console, args);\n };\n this.teardowns.push(() => {\n console[level] = original;\n });\n };\n wrap('error');\n wrap('warn');\n }\n\n private rageWindow: number[] = [];\n\n private installAutocapture(): void {\n if (typeof document === 'undefined') return;\n\n this.addListener(\n document,\n 'click',\n (e) => {\n const target = (e as MouseEvent).target as HTMLElement | null;\n if (!target) return;\n this.detectRageClick();\n const el = target.closest('a,button,input[type=submit],[role=button],[data-glass]') as HTMLElement | null;\n if (!el) return;\n this.track('$click', this.elementProps(el));\n },\n { capture: true },\n );\n\n this.addListener(\n document,\n 'submit',\n (e) => {\n const form = (e as SubmitEvent).target as HTMLFormElement | null;\n if (!form || form.tagName !== 'FORM') return;\n // Never capture field VALUES — only structural metadata.\n this.track('$form_submit', {\n form_id: form.id || null,\n form_name: form.getAttribute('name'),\n action: form.getAttribute('action'),\n field_count: form.elements.length,\n });\n },\n { capture: true },\n );\n\n this.installSpaPageviews();\n }\n\n /** Stable, value-free descriptor of a clicked element. */\n private elementProps(el: HTMLElement): Record<string, Value> {\n return {\n tag: el.tagName.toLowerCase(),\n text: (el.textContent ?? '').trim().slice(0, 80),\n href: el instanceof HTMLAnchorElement ? el.href : null,\n el_id: el.id || null,\n el_class: el.getAttribute('class'),\n data_glass: el.getAttribute('data-glass'),\n };\n }\n\n /** Three+ clicks within 1s at roughly one spot = a rage click (frustration signal). */\n private detectRageClick(): void {\n const now = Date.now();\n this.rageWindow = this.rageWindow.filter((t) => now - t < 1000);\n this.rageWindow.push(now);\n if (this.rageWindow.length >= 3) {\n this.rageWindow = [];\n this.track('$rageclick', { url: typeof location !== 'undefined' ? location.href : null });\n }\n }\n\n /** SPA route changes: patch History + listen to popstate, de-duping same-URL. */\n private lastPath = '';\n private installSpaPageviews(): void {\n if (typeof history === 'undefined' || typeof location === 'undefined') return;\n this.lastPath = location.href;\n const fire = () => {\n if (location.href === this.lastPath) return;\n this.lastPath = location.href;\n this.track('$pageview', this.pageProps());\n };\n const wrap = (key: 'pushState' | 'replaceState') => {\n const orig = history[key];\n history[key] = function patched(this: History, ...args: Parameters<History['pushState']>) {\n const ret = orig.apply(this, args);\n // Defer so location has updated before we read it.\n setTimeout(fire, 0);\n return ret;\n } as History[typeof key];\n // Restore the native method on shutdown() so we don't leak a patch.\n this.teardowns.push(() => {\n history[key] = orig;\n });\n };\n wrap('pushState');\n wrap('replaceState');\n this.addListener(window, 'popstate', fire);\n }\n\n // --- session replay control ------------------------------------------------\n\n startSessionRecording(): void {\n void this.replay.start();\n }\n stopSessionRecording(): void {\n void this.replay.stopRecording();\n }\n\n // --- feature flags (deterministic, edge-evaluated) -------------------------\n\n async reloadFeatureFlags(): Promise<void> {\n try {\n const unit = this.userId ?? this.deviceId;\n const res = await fetch(`${this.cfg.apiHost}/v1/sdk/flags?user_id=${encodeURIComponent(unit)}`, {\n headers: { Authorization: `Glass-Key ${this.cfg.projectKey}` },\n });\n if (res.ok) {\n const json = (await res.json()) as { flags?: Record<string, FlagValue> };\n this.flags = { ...this.flags, ...(json.flags ?? {}) };\n }\n } catch {\n /* keep bootstrap/cached flags */\n } finally {\n this.flagsLoaded = true;\n for (const fn of this.flagListeners) fn(this.flags);\n }\n }\n\n onFlagsLoaded(fn: (flags: Record<string, FlagValue>) => void): void {\n this.flagListeners.push(fn);\n if (this.flagsLoaded) fn(this.flags);\n }\n\n /**\n * Resolve a flag value with precedence: locally-evaluated definition (if the\n * app shipped one, so targeting reflects CURRENT properties) → server/bootstrap\n * resolved value → fallback.\n */\n private resolve(key: string, opts?: FlagOptions): FlagValue {\n const local = this.evaluateLocal(key);\n const v = local !== undefined ? local : this.flags[key];\n const value = v !== undefined ? v : opts?.fallback;\n if (value !== undefined && opts?.trackExposure !== false) this.exposure(key, value);\n return value;\n }\n\n /** Local bucketing via @glassanalytics/core when definitions were provided to init(). */\n private evaluateLocal(key: string): FlagValue {\n const def = this.cfg.flagDefinitions.find((d: FlagDefinition) => d.key === key);\n if (!def) return undefined;\n const properties: Record<string, ScalarValue> = {};\n for (const [k, val] of Object.entries(this.traits)) {\n if (val === null || typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean') {\n properties[k] = val as ScalarValue;\n }\n }\n return evaluateFlag(def, { unitId: this.userId ?? this.deviceId, properties });\n }\n\n isFeatureEnabledSync(key: string, opts?: FlagOptions): boolean {\n const v = this.resolve(key, opts);\n return v === true || (typeof v === 'string' && v !== '');\n }\n async isFeatureEnabled(key: string, opts?: FlagOptions): Promise<boolean> {\n if (!this.flagsLoaded) await this.reloadFeatureFlags();\n return this.isFeatureEnabledSync(key, opts);\n }\n getFeatureFlagSync(key: string, opts?: FlagOptions): FlagValue {\n return this.resolve(key, opts);\n }\n async getFeatureFlag(key: string, opts?: FlagOptions): Promise<FlagValue> {\n if (!this.flagsLoaded) await this.reloadFeatureFlags();\n return this.getFeatureFlagSync(key, opts);\n }\n getVariantSync(key: string, opts?: FlagOptions): FlagValue {\n return this.resolve(key, opts);\n }\n async getVariant(key: string, opts?: FlagOptions): Promise<FlagValue> {\n if (!this.flagsLoaded) await this.reloadFeatureFlags();\n return this.getVariantSync(key, opts);\n }\n\n /** Fire a `$exposure` once per (flag, value) so experiment analysis is honest (§8). */\n private exposedKeys = new Set<string>();\n private exposure(key: string, value: FlagValue): void {\n const k = `${key}=${String(value)}`;\n if (this.exposedKeys.has(k)) return;\n this.exposedKeys.add(k);\n this.emit('exposure', key, { $feature_flag: key, $feature_flag_value: String(value) });\n }\n\n // --- consent ---------------------------------------------------------------\n\n optIn(): void {\n this.optedOut = false;\n this.afterConsent();\n }\n optOut(): void {\n this.optedOut = true;\n // Discard anything buffered/queued the moment consent is withdrawn.\n this.transport.clearBuffer();\n this.transport.clearOffline();\n void this.replay.stopRecording();\n }\n hasConsent(): boolean {\n return !this.optedOut;\n }\n\n // --- lifecycle -------------------------------------------------------------\n\n flush(): Promise<void> {\n return this.transport.flush();\n }\n shutdown(): void {\n void this.transport.flush(true);\n void this.replay.stopRecording();\n // Remove every listener/patch we installed (in reverse) so re-init or a SPA\n // teardown leaves the page exactly as we found it.\n for (const off of this.teardowns.splice(0, this.teardowns.length).reverse()) {\n try {\n off();\n } catch {\n /* best-effort cleanup */\n }\n }\n this.transport.destroy();\n this.started = false;\n }\n}\n\n/** JSON-stringify that never throws (cyclic refs, BigInt, etc.) for console capture. */\nfunction safeString(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** Default singleton, mirroring the ergonomic `glass.init(...)` usage in `SDK.md`. */\nexport const glass = new Glass();\nexport default glass;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glassanalytics/browser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Glass browser SDK — session replay (rrweb), autocapture, identity, errors and edge-evaluated feature flags. Small, lazy, safe-by-default.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|