@sightspool/sdk 0.2.1 → 0.4.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/CHANGELOG.md +15 -0
- package/README.md +111 -333
- package/SECURITY.md +16 -0
- package/dist/index.cjs +159 -1080
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -41
- package/dist/index.d.ts +20 -41
- package/dist/index.js +160 -734
- package/dist/index.js.map +1 -1
- package/dist/release.json +21 -0
- package/dist/sdk.global.js +2 -38
- package/dist/sdk.global.js.map +1 -1
- package/dist/source.json +11 -0
- package/package.json +14 -12
- package/site/CNAME +1 -0
- package/site/demo.html +6 -0
- package/site/demo.js +27 -0
- package/site/index.html +74 -0
- package/site/release.js +20 -0
- package/site/releases/0.4.0/2acf3463db7571c459ca01a4516341891bb4c2ec6265962f494ca8b553cc0e9f/release.json +21 -0
- package/site/releases/0.4.0/2acf3463db7571c459ca01a4516341891bb4c2ec6265962f494ca8b553cc0e9f/sdk.global.js +3 -0
- package/site/releases/0.4.0/2acf3463db7571c459ca01a4516341891bb4c2ec6265962f494ca8b553cc0e9f/sdk.global.js.map +1 -0
- package/site/releases/0.4.0/2acf3463db7571c459ca01a4516341891bb4c2ec6265962f494ca8b553cc0e9f/source.json +11 -0
- package/site/releases/0.4.0/c21bee307a5c53e3ebb49d21f0f1ef2cce06a4483fa9824122bd6897ad6ca3ac/release.json +21 -0
- package/site/releases/0.4.0/c21bee307a5c53e3ebb49d21f0f1ef2cce06a4483fa9824122bd6897ad6ca3ac/sdk.global.js +3 -0
- package/site/releases/0.4.0/c21bee307a5c53e3ebb49d21f0f1ef2cce06a4483fa9824122bd6897ad6ca3ac/sdk.global.js.map +1 -0
- package/site/releases/0.4.0/c21bee307a5c53e3ebb49d21f0f1ef2cce06a4483fa9824122bd6897ad6ca3ac/source.json +11 -0
- package/site/styles.css +69 -0
- package/site/trust.html +36 -0
- package/dist/chunk-4PADVIIO.js +0 -41
- package/dist/chunk-4PADVIIO.js.map +0 -1
- package/dist/prompt-GDFYC75D.js +0 -139
- package/dist/prompt-GDFYC75D.js.map +0 -1
- package/dist/survey-CICJQ5VI.js +0 -145
- package/dist/survey-CICJQ5VI.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/capture.ts","../src/harvest.ts","../src/egress.ts","../src/triggers.ts","../src/intervention.ts","../src/env.ts","../src/index.ts"],"names":["_a","RAGE_WINDOW_MS"],"mappings":"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","file":"index.js","sourcesContent":["// Passive context capture (FR-2) — the buffer of route/click/error events the\n// rest of the runtime reads. All DOM access is guarded and wrapped: this module\n// must never throw into the host app (NFR-3).\n\nimport type { TrailEvent, TrailEventType } from \"./types\";\nimport { redactText, isIgnoredElement, matchesRedactSelector, REDACTED } from \"./privacy\";\n\nconst TRAIL_MAX = 30;\nconst DEAD_CLICK_MS = 700; // a click with no DOM/route change after this = dead-click\nconst RAGE_WINDOW_MS = 1_000;\nconst RAGE_COUNT = 3;\n\nexport type CaptureHandle = {\n start(): void;\n stop(): void;\n trail(): TrailEvent[];\n route(): string;\n label(): string;\n error(): string | undefined;\n /** Subscribe to \"a meaningful event happened\" (the trigger engine polls off this). */\n onEvent(cb: () => void): void;\n /** Called by harvest.ts when a search/filter query is typed. */\n recordSearch(query: string, zeroResult?: boolean): void;\n};\n\nfunction hasDom(): boolean {\n return typeof window !== \"undefined\" && typeof document !== \"undefined\";\n}\n\nexport function createCapture(opts: {\n debug: boolean;\n redact?: readonly string[];\n block?: readonly string[];\n}): CaptureHandle {\n const redactSelectors = opts.redact ?? [];\n const blockSelectors = opts.block ?? [];\n let buf: TrailEvent[] = [];\n let lastError: string | undefined;\n let started = false;\n const subs: Array<() => void> = [];\n const cleanups: Array<() => void> = [];\n let recentClicks: number[] = []; // timestamps, for rage detection\n\n function notify() {\n for (const cb of subs) {\n try {\n cb();\n } catch {\n /* a subscriber must never break capture */\n }\n }\n }\n\n function push(type: TrailEventType, label?: string) {\n try {\n buf.push({ t: Date.now(), type, label: label ? redactText(label) : undefined });\n if (buf.length > TRAIL_MAX) buf = buf.slice(-TRAIL_MAX);\n if (opts.debug) console.debug(\"[sightspool] event\", type, label);\n notify();\n } catch {\n /* swallow */\n }\n }\n\n function currentRoute(): string {\n try {\n return location.pathname + location.search;\n } catch {\n return \"\";\n }\n }\n\n function currentLabel(): string {\n try {\n return document.title || \"\";\n } catch {\n return \"\";\n }\n }\n\n function onClick(ev: MouseEvent) {\n try {\n const target = ev.target as Element | null;\n // Hard opt-out: a click inside [data-sightspool-ignore] or a `block` selector is\n // never recorded — not even as an unlabelled event (GOV-3).\n if (isIgnoredElement(target, blockSelectors)) return;\n const text =\n (target && (target.getAttribute?.(\"aria-label\") || target.textContent)) || \"\";\n // `redact` selectors mask the label wholesale; emails/digits in any label are\n // also masked by push() → redactText.\n const label = matchesRedactSelector(target, redactSelectors)\n ? REDACTED\n : text.trim().slice(0, 60);\n const t = Date.now();\n\n recentClicks = recentClicks.filter((ts) => t - ts <= RAGE_WINDOW_MS);\n recentClicks.push(t);\n const isRage = recentClicks.length >= RAGE_COUNT;\n push(isRage ? \"rage_click\" : \"click\", label);\n\n // dead-click: did anything change shortly after? watch for a DOM mutation or\n // a route change; if neither, record a dead_click.\n const routeBefore = currentRoute();\n let mutated = false;\n let observer: MutationObserver | null = null;\n try {\n observer = new MutationObserver(() => {\n mutated = true;\n });\n observer.observe(document.body, { childList: true, subtree: true, attributes: true });\n } catch {\n /* no MutationObserver — skip dead-click detection */\n }\n window.setTimeout(() => {\n try {\n observer?.disconnect();\n if (!mutated && currentRoute() === routeBefore && label) {\n push(\"dead_click\", label);\n }\n } catch {\n /* swallow */\n }\n }, DEAD_CLICK_MS);\n } catch {\n /* swallow */\n }\n }\n\n function onError(ev: ErrorEvent) {\n try {\n lastError = String(ev.message || \"error\");\n push(\"error\", lastError);\n } catch {\n /* swallow */\n }\n }\n\n function onRejection(ev: PromiseRejectionEvent) {\n try {\n const reason = ev.reason;\n lastError = reason instanceof Error ? reason.message : String(reason);\n push(\"error\", lastError);\n } catch {\n /* swallow */\n }\n }\n\n // Route changes: patch history.pushState/replaceState + listen for popstate.\n function installRouteTracking() {\n try {\n const fire = () => push(\"route\", currentRoute());\n const origPush = history.pushState;\n const origReplace = history.replaceState;\n history.pushState = function (this: History, ...args: Parameters<History[\"pushState\"]>) {\n const r = origPush.apply(this, args);\n fire();\n return r;\n };\n history.replaceState = function (\n this: History,\n ...args: Parameters<History[\"replaceState\"]>\n ) {\n const r = origReplace.apply(this, args);\n fire();\n return r;\n };\n window.addEventListener(\"popstate\", fire);\n cleanups.push(() => {\n history.pushState = origPush;\n history.replaceState = origReplace;\n window.removeEventListener(\"popstate\", fire);\n });\n push(\"route\", currentRoute()); // seed with the entry route\n } catch {\n /* swallow */\n }\n }\n\n // Light fetch wrapper to catch failed/4xx-5xx requests as request_error events.\n function installFetchTracking() {\n try {\n if (typeof window.fetch !== \"function\") return;\n const orig = window.fetch.bind(window);\n window.fetch = async (...args: Parameters<typeof fetch>) => {\n try {\n const res = await orig(...args);\n if (!res.ok) push(\"request_error\", `HTTP ${res.status}`);\n return res;\n } catch (err) {\n push(\"request_error\", err instanceof Error ? err.message : \"network error\");\n throw err;\n }\n };\n cleanups.push(() => {\n window.fetch = orig;\n });\n } catch {\n /* swallow */\n }\n }\n\n return {\n start() {\n if (started || !hasDom()) return;\n started = true;\n try {\n document.addEventListener(\"click\", onClick, true);\n window.addEventListener(\"error\", onError);\n window.addEventListener(\"unhandledrejection\", onRejection);\n cleanups.push(() => {\n document.removeEventListener(\"click\", onClick, true);\n window.removeEventListener(\"error\", onError);\n window.removeEventListener(\"unhandledrejection\", onRejection);\n });\n installRouteTracking();\n installFetchTracking();\n } catch {\n /* swallow */\n }\n },\n stop() {\n started = false;\n for (const c of cleanups.splice(0)) {\n try {\n c();\n } catch {\n /* swallow */\n }\n }\n },\n trail() {\n return buf.slice();\n },\n route: currentRoute,\n label: currentLabel,\n error() {\n return lastError;\n },\n onEvent(cb) {\n subs.push(cb);\n },\n recordSearch(query, zeroResult) {\n const q = query.trim();\n if (!q) return;\n push(zeroResult ? \"zero_result\" : \"search\", q);\n },\n };\n}\n","// Intent harvest (FR-3) — treat typed queries in search / filter / command-palette\n// / empty-state inputs as STATED intent (the highest-signal intent, no question\n// needed). Harvesting precedes any inference. Defensive throughout (NFR-3).\n//\n// Zero-result detection is genuinely cross-app-specific and best-effort in v1: we\n// capture the query as a search event; flagging it as zero-result reliably is a\n// follow-up (it needs per-app empty-state hints). The query itself is the value.\n\nimport type { CaptureHandle } from \"./capture\";\nimport { isIgnoredElement, matchesRedactSelector } from \"./privacy\";\n\nconst SEARCH_HINT_RE = /search|filter|find|query|command|lookup/i;\nconst DEBOUNCE_MS = 800;\n\nexport type HarvestHandle = {\n start(): void;\n stop(): void;\n /** The most recent stated intent (last search/filter query), for State-B candidates. */\n lastIntentHint(): string | undefined;\n};\n\nfunction looksLikeSearch(el: Element): boolean {\n try {\n const input = el as HTMLInputElement;\n if (input.type === \"search\") return true;\n const role = el.getAttribute(\"role\") || \"\";\n if (role === \"searchbox\" || role === \"combobox\") return true;\n const hay = [\n input.name,\n input.placeholder,\n el.getAttribute(\"aria-label\"),\n el.id,\n el.className,\n ]\n .filter(Boolean)\n .join(\" \");\n return SEARCH_HINT_RE.test(hay);\n } catch {\n return false;\n }\n}\n\nexport function createHarvest(\n capture: CaptureHandle,\n opts: { debug: boolean; redact?: readonly string[]; block?: readonly string[] },\n): HarvestHandle {\n let hint: string | undefined;\n let timer: number | null = null;\n let started = false;\n const redactSelectors = opts.redact ?? [];\n const blockSelectors = opts.block ?? [];\n\n function onInput(ev: Event) {\n try {\n const target = ev.target as HTMLInputElement | null;\n if (!target || (target.tagName !== \"INPUT\" && target.tagName !== \"TEXTAREA\")) return;\n if (!looksLikeSearch(target)) return;\n // A masked query is useless intent, so a `redact`-matched search box is treated\n // as a hard opt-out here (same as `block`/ignore): don't harvest the value at all.\n if (isIgnoredElement(target, blockSelectors) || matchesRedactSelector(target, redactSelectors))\n return;\n const value = (target.value || \"\").trim();\n if (value.length < 2) return;\n\n if (timer !== null) window.clearTimeout(timer);\n timer = window.setTimeout(() => {\n hint = value;\n capture.recordSearch(value);\n if (opts.debug) console.debug(\"[sightspool] harvested intent\", value);\n }, DEBOUNCE_MS);\n } catch {\n /* swallow */\n }\n }\n\n return {\n start() {\n if (started || typeof document === \"undefined\") return;\n started = true;\n try {\n document.addEventListener(\"input\", onInput, true);\n } catch {\n /* swallow */\n }\n },\n stop() {\n started = false;\n try {\n document.removeEventListener(\"input\", onInput, true);\n if (timer !== null) window.clearTimeout(timer);\n } catch {\n /* swallow */\n }\n },\n lastIntentHint() {\n return hint;\n },\n };\n}\n","// Egress — batch captured Signals and ship them to /api/sdk/ingest, preferring\n// navigator.sendBeacon (survives page unload) with a fetch+keepalive fallback.\n// Every path is wrapped: a failed send must never surface in the host app (NFR-3),\n// and a Signal already records its why/cost passively, so a dropped beacon just\n// loses enrichment, not the capture's value (FR-7).\n\nimport type { CapturedSignal, Identity, IngestBody } from \"./types\";\n\nconst FLUSH_BATCH = 10; // flush when this many Signals are queued\nconst FLUSH_INTERVAL_MS = 15_000;\n\nexport type EgressHandle = {\n start(): void;\n stop(): void;\n enqueue(signal: CapturedSignal): void;\n flush(): void;\n setIdentity(identity: Identity): void;\n};\n\nexport function createEgress(opts: {\n key: string;\n endpoint: string;\n debug: boolean;\n}): EgressHandle {\n let queue: CapturedSignal[] = [];\n let identity: Identity | undefined;\n let interval: number | null = null;\n let started = false;\n\n const url = `${opts.endpoint.replace(/\\/+$/, \"\")}/api/sdk/ingest`;\n\n function send(signals: CapturedSignal[]) {\n if (signals.length === 0) return;\n const body: IngestBody = { key: opts.key, identity, signals };\n const json = JSON.stringify(body);\n try {\n // text/plain is a CORS-safelisted content type, so a cross-origin beacon\n // skips the preflight entirely (the host app's domain ≠ ours). The server\n // parses the text as JSON regardless.\n if (typeof navigator !== \"undefined\" && typeof navigator.sendBeacon === \"function\") {\n const blob = new Blob([json], { type: \"text/plain\" });\n const ok = navigator.sendBeacon(url, blob);\n if (ok) {\n if (opts.debug) console.debug(\"[sightspool] beacon\", signals.length);\n return;\n }\n }\n // Fallback: fetch with keepalive so it can outlive the page.\n void fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"text/plain\" },\n body: json,\n keepalive: true,\n mode: \"cors\",\n credentials: \"omit\",\n }).catch(() => {\n /* swallow — drop on failure */\n });\n } catch {\n /* swallow */\n }\n }\n\n function onVisibility() {\n try {\n if (document.visibilityState === \"hidden\") flush();\n } catch {\n /* swallow */\n }\n }\n\n function flush() {\n if (queue.length === 0) return;\n const batch = queue;\n queue = [];\n send(batch);\n }\n\n return {\n start() {\n if (started || typeof window === \"undefined\") return;\n started = true;\n try {\n document.addEventListener(\"visibilitychange\", onVisibility);\n window.addEventListener(\"pagehide\", flush);\n interval = window.setInterval(flush, FLUSH_INTERVAL_MS);\n } catch {\n /* swallow */\n }\n },\n stop() {\n started = false;\n try {\n document.removeEventListener(\"visibilitychange\", onVisibility);\n window.removeEventListener(\"pagehide\", flush);\n if (interval !== null) window.clearInterval(interval);\n } catch {\n /* swallow */\n }\n flush();\n },\n enqueue(signal) {\n queue.push(signal);\n if (queue.length >= FLUSH_BATCH) flush();\n },\n flush,\n setIdentity(next) {\n identity = next;\n },\n };\n}\n","// Trigger + fatigue logic (FR-4, NFR-2) — the make-or-break craft surface.\n//\n// Kept PURE (no DOM) so it unit-tests cleanly under `node --test` and so the\n// heuristics can be tuned against real traffic later without touching the capture\n// wiring. Detection quality is the primary failure mode (false positives that\n// pester users), so the defaults are deliberately conservative.\n\nimport type { TrailEvent } from \"./types\";\n\nexport const RAGE_CLICK_COUNT = 3; // clicks…\nexport const RAGE_WINDOW_MS = 1_000; // …within this window form a rage cluster\nexport const FRICTION_RETRY_COUNT = 3; // repeated identical actions = retry frustration\nexport const FRICTION_WINDOW_MS = 8_000; // how far back a friction scan looks\n\nexport type FrictionKind = \"error\" | \"rage\" | \"dead_end\" | \"retry\";\n\n/**\n * Scan the recent trail for a friction moment. Returns the strongest kind found,\n * or null. Order = severity: a real error beats a rage cluster beats a dead-end\n * beats repeated retries.\n */\nexport function detectFriction(\n trail: TrailEvent[],\n now: number,\n windowMs = FRICTION_WINDOW_MS,\n): FrictionKind | null {\n const recent = trail.filter((e) => now - e.t <= windowMs);\n\n if (recent.some((e) => e.type === \"error\" || e.type === \"request_error\")) return \"error\";\n\n const clicks = recent.filter((e) => e.type === \"click\" || e.type === \"rage_click\");\n for (let i = 0; i < clicks.length; i++) {\n const burst = clicks.filter(\n (e) => e.t >= clicks[i].t && e.t - clicks[i].t <= RAGE_WINDOW_MS,\n );\n if (burst.length >= RAGE_CLICK_COUNT) return \"rage\";\n }\n\n if (recent.some((e) => e.type === \"dead_click\")) return \"dead_end\";\n\n const byLabel = new Map<string, number>();\n for (const e of clicks) {\n if (!e.label) continue;\n const n = (byLabel.get(e.label) ?? 0) + 1;\n byLabel.set(e.label, n);\n if (n >= FRICTION_RETRY_COUNT) return \"retry\";\n }\n\n return null;\n}\n\n// --- Fatigue caps (NFR-2): never pester. Conservative by default. ------------\n\nexport type FatigueCaps = {\n maxPromptsPerSession: number;\n cooldownMs: number; // min gap between prompts\n};\n\nexport const DEFAULT_CAPS: FatigueCaps = {\n maxPromptsPerSession: 1,\n cooldownMs: 5 * 60_000,\n};\n\nexport type FatigueState = {\n promptsShown: number;\n lastPromptAt: number | null;\n};\n\n/** May we show a prompt right now, given how many we've shown and when? */\nexport function canPrompt(\n state: FatigueState,\n now: number,\n caps: FatigueCaps = DEFAULT_CAPS,\n): boolean {\n if (state.promptsShown >= caps.maxPromptsPerSession) return false;\n if (state.lastPromptAt !== null && now - state.lastPromptAt < caps.cooldownMs) return false;\n return true;\n}\n","// Intervention serve/respond (Wave 0005 slice B — the client half). The two-way\n// SDK: besides emitting Signals, the SDK asks \"is there anything to show this user\n// here?\" (/api/sdk/serve) and posts the answer (/api/sdk/respond). Both halves are\n// wrapped — a serve/respond failure must never surface in the host app (NFR-3); the\n// worst case is simply no survey shown.\n//\n// Pure helpers (buildServeContext / normalizeServed / pickRespondentKey) are split\n// out so the contract is unit-testable without a DOM, like triggers.ts.\n\nimport type { Identity } from \"./types\";\nimport type { SurveyConfig } from \"./survey\";\n\nexport type ServeContext = { route?: string; account?: string; plan?: string };\n\nexport type ServedIntervention = {\n id: string;\n type: string; // 'survey' renders today; others ignored until their widget ships\n config: SurveyConfig;\n};\n\nexport type InterventionAnswer = { choice?: string; text?: string };\n\n// Types the SDK can actually render. Mirrors the server's RENDERABLE_TYPES; if the\n// server ever serves an un-renderable type we drop it rather than show a blank.\nconst RENDERABLE = new Set([\"survey\"]);\n\nfunction str(v: unknown, max: number): string | undefined {\n if (typeof v !== \"string\") return undefined;\n const t = v.trim();\n return t ? t.slice(0, max) : undefined;\n}\n\n/** The serve context from the current route + the identified account/plan. Only\n * defined fields are included (an absent field = unconstrained on the server). */\nexport function buildServeContext(\n route: string | undefined,\n identity: Identity | undefined,\n): ServeContext {\n const ctx: ServeContext = {};\n const r = str(route, 500);\n if (r) ctx.route = r;\n const account = str(identity?.account, 200);\n if (account) ctx.account = account;\n const plan = str(identity?.plan, 80);\n if (plan) ctx.plan = plan;\n return ctx;\n}\n\n/** Validate + normalise what /serve returned — never trust the wire blindly. Returns\n * a clean ServedIntervention or null (unknown shape / un-renderable type / no\n * question). */\nexport function normalizeServed(raw: unknown): ServedIntervention | null {\n if (!raw || typeof raw !== \"object\") return null;\n const r = raw as Record<string, unknown>;\n const id = str(r.id, 64);\n const type = str(r.type, 40);\n if (!id || !type || !RENDERABLE.has(type)) return null;\n\n const cfg =\n r.config && typeof r.config === \"object\" ? (r.config as Record<string, unknown>) : {};\n const question = str(cfg.question, 500);\n if (!question) return null;\n\n const options = Array.isArray(cfg.options)\n ? (cfg.options as unknown[])\n .map((o) => str(o, 200))\n .filter((o): o is string => !!o)\n .slice(0, 6)\n : undefined;\n\n const config: SurveyConfig = {\n question,\n ...(options && options.length ? { options } : {}),\n allow_text: cfg.allow_text === true,\n };\n return { id, type, config };\n}\n\n/** Stable id for serve-time de-dup (so a tapped survey doesn't reappear). The\n * identified user wins; else a persisted anon id; else the per-session ref. Pure\n * so it's testable — the localStorage read lives in getRespondentKey. */\nexport function pickRespondentKey(\n userId: string | undefined,\n persisted: string | null,\n sessionRef: string,\n): string {\n const uid = str(userId, 200);\n if (uid) return uid;\n const p = str(persisted, 200);\n if (p) return p;\n return sessionRef;\n}\n\nconst RK_STORAGE_KEY = \"sightspool_rk\";\n\n/** Resolve the respondent key, persisting an anonymous one in localStorage so\n * de-dup survives reloads. Falls back to the session ref if storage is blocked. */\nexport function getRespondentKey(\n identity: Identity | undefined,\n sessionRef: string,\n): string {\n const uid = str(identity?.userId, 200);\n if (uid) return uid;\n try {\n let v = localStorage.getItem(RK_STORAGE_KEY);\n if (!v) {\n v = \"anon-\" + Math.random().toString(36).slice(2) + Date.now().toString(36);\n localStorage.setItem(RK_STORAGE_KEY, v);\n }\n return pickRespondentKey(undefined, v, sessionRef);\n } catch {\n return sessionRef;\n }\n}\n\nfunction serveUrl(endpoint: string, path: string): string {\n return `${endpoint.replace(/\\/+$/, \"\")}/api/sdk/${path}`;\n}\n\n/** Ask the serve endpoint for an intervention to show, or null. Uses a text/plain\n * POST (CORS-safelisted → no preflight) and reads the JSON response (the serve\n * route sets Access-Control-Allow-Origin). */\nexport async function fetchIntervention(opts: {\n endpoint: string;\n key: string;\n ctx: ServeContext;\n respondentKey: string;\n debug?: boolean;\n}): Promise<ServedIntervention | null> {\n try {\n if (typeof fetch !== \"function\") return null;\n const res = await fetch(serveUrl(opts.endpoint, \"serve\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"text/plain\" },\n body: JSON.stringify({\n key: opts.key,\n context: opts.ctx,\n respondent_key: opts.respondentKey,\n }),\n mode: \"cors\",\n credentials: \"omit\",\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { intervention?: unknown };\n const served = normalizeServed(data?.intervention);\n if (opts.debug) console.debug(\"[sightspool] serve\", served?.id ?? \"(none)\");\n return served;\n } catch {\n return null;\n }\n}\n\n/** Post a user's answer. Fire-and-forget (sendBeacon, fetch+keepalive fallback) —\n * the response is a 204 we don't need to read. */\nexport function submitResponse(opts: {\n endpoint: string;\n key: string;\n interventionId: string;\n response: InterventionAnswer;\n respondentKey: string;\n}): void {\n try {\n const url = serveUrl(opts.endpoint, \"respond\");\n const json = JSON.stringify({\n key: opts.key,\n intervention_id: opts.interventionId,\n response: opts.response,\n respondent_key: opts.respondentKey,\n });\n if (typeof navigator !== \"undefined\" && typeof navigator.sendBeacon === \"function\") {\n const blob = new Blob([json], { type: \"text/plain\" });\n if (navigator.sendBeacon(url, blob)) return;\n }\n if (typeof fetch === \"function\") {\n void fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"text/plain\" },\n body: json,\n keepalive: true,\n mode: \"cors\",\n credentials: \"omit\",\n }).catch(() => {\n /* swallow */\n });\n }\n } catch {\n /* swallow */\n }\n}\n","// Environment guards. Kept pure (a hostname string in, a boolean out) so the\n// no-op-on-localhost decision is unit-testable without a DOM.\n\nconst LOCAL_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"0.0.0.0\", \"::1\", \"\"]);\n\n/**\n * Is this a local-development hostname? Capture is suppressed on these by default so\n * a client's `npm run dev` traffic never pollutes their Sightspool workspace (override\n * with `captureOnLocalhost: true`). Covers the common dev hosts + the `.local` /\n * `.localhost` TLDs (e.g. `myapp.local`, `app.localhost`).\n */\nexport function isLocalhost(hostname: string | null | undefined): boolean {\n const h = (hostname ?? \"\").trim().toLowerCase();\n if (LOCAL_HOSTS.has(h)) return true;\n return h.endsWith(\".local\") || h.endsWith(\".localhost\");\n}\n","// @sightspool/sdk — the in-product capture runtime (public surface).\n//\n// Ties the pieces together: passive capture + intent harvest feed a conservative\n// trigger engine; on a friction moment or a session boundary we (fatigue\n// permitting) show the one-tap prompt, then emit one Signal via batched sendBeacon.\n// Every public method is wrapped — the SDK must never throw into the host (NFR-3).\n\nimport type { SightspoolConfig, Identity, CapturedSignal } from \"./types\";\nimport { createCapture, type CaptureHandle } from \"./capture\";\nimport { createHarvest, type HarvestHandle } from \"./harvest\";\nimport { createEgress, type EgressHandle } from \"./egress\";\nimport {\n detectFriction,\n canPrompt,\n DEFAULT_CAPS,\n type FatigueState,\n} from \"./triggers\";\nimport {\n buildServeContext,\n fetchIntervention,\n submitResponse,\n getRespondentKey,\n} from \"./intervention\";\nimport { isLocalhost } from \"./env\";\n\nexport type { SightspoolConfig, Identity } from \"./types\";\n\nconst DEFAULT_ENDPOINT = \"https://www.sightspool.com\";\nconst FRICTION_EMIT_COOLDOWN_MS = 30_000;\nconst EVENT_DEBOUNCE_MS = 600;\n// Let the page settle before the first serve check (don't race the initial render).\nconst SERVE_SETTLE_MS = 2_500;\n// Conservative client cap; the server also de-dups (answered) + targets + bounds by\n// response_target, so this just stops a dismissed survey re-nagging within a session.\nconst MAX_INTERVENTIONS_PER_SESSION = 1;\n\ntype Controller = {\n config: Required<Pick<SightspoolConfig, \"key\" | \"endpoint\" | \"boundaryAsk\" | \"debug\">> &\n SightspoolConfig;\n capture: CaptureHandle;\n harvest: HarvestHandle;\n egress: EgressHandle;\n identity: Identity;\n sessionRef: string;\n fatigue: FatigueState;\n lastFrictionEmitAt: number;\n eventTimer: number | null;\n running: boolean;\n /** Environmental kill-switch: on localhost without `captureOnLocalhost`, never start. */\n suppressed: boolean;\n // --- interventions (slice B serve loop) ---\n interventionsEnabled: boolean;\n lastServeRoute: string | null; // re-check serve when the route changes\n surveyOnScreen: boolean;\n interventionsShown: number;\n};\n\nfunction currentHostname(): string {\n try {\n return typeof location !== \"undefined\" ? location.hostname : \"\";\n } catch {\n return \"\";\n }\n}\n\nlet ctrl: Controller | null = null;\n\nfunction uuid(): string {\n try {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n } catch {\n /* fall through */\n }\n return \"s-\" + Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\n// Locally-derived candidate goals for State B (FR-5). v1 leans on harvested intent\n// (a recent search) + the page label; server-LLM enrichment is a follow-up.\nfunction deriveCandidates(c: Controller): string[] {\n const out: string[] = [];\n const hint = c.harvest.lastIntentHint();\n if (hint) out.push(`Searching for “${hint}”`);\n const label = c.capture.label();\n if (label) out.push(`Something on “${label.slice(0, 40)}”`);\n return out;\n}\n\nfunction buildSignal(\n c: Controller,\n trigger: \"boundary\" | \"friction\",\n extra: Partial<CapturedSignal> = {},\n): CapturedSignal {\n const err = c.capture.error();\n return {\n captured_at: new Date().toISOString(),\n route: c.capture.route(),\n client_label: c.capture.label(),\n trail: c.capture.trail(),\n session_ref: c.sessionRef,\n trigger,\n intent_hint: c.harvest.lastIntentHint(),\n error: err,\n outcome: err || trigger === \"friction\" ? \"failed\" : \"unknown\",\n ...extra,\n };\n}\n\nasync function maybePrompt(c: Controller, trigger: \"boundary\" | \"friction\") {\n const now = Date.now();\n if (canPrompt(c.fatigue, now, DEFAULT_CAPS)) {\n c.fatigue.promptsShown += 1;\n c.fatigue.lastPromptAt = now;\n try {\n const { showPrompt } = await import(\"./prompt\");\n const result = await showPrompt({ candidates: deriveCandidates(c) });\n c.egress.enqueue(\n buildSignal(c, trigger, {\n answer: result.answer,\n verbatim: result.verbatim,\n intent_hint: result.intent ?? c.harvest.lastIntentHint(),\n outcome: result.answer === \"yes\" ? \"achieved\" : \"failed\",\n }),\n );\n } catch {\n // Prompt failed to load/show — still emit the passive Signal (FR-7).\n c.egress.enqueue(buildSignal(c, trigger));\n }\n } else {\n // Fatigued: keep the silent-capture property — emit without asking (FR-7).\n c.egress.enqueue(buildSignal(c, trigger));\n }\n}\n\n// Ask the serve endpoint whether there's a human-approved survey to show this user\n// here, and if so render it + post the answer. Server-gated (targeting, approval,\n// de-dup, response_target); the client guards are just \"don't pester\": one on\n// screen at a time, a per-session cap, and the shared prompt cooldown so a survey\n// and the passive ask never stack back-to-back.\nasync function maybeServeIntervention(c: Controller) {\n if (!c.running || !c.interventionsEnabled || c.suppressed) return;\n if (c.surveyOnScreen) return;\n if (c.interventionsShown >= MAX_INTERVENTIONS_PER_SESSION) return;\n const now = Date.now();\n if (c.fatigue.lastPromptAt !== null && now - c.fatigue.lastPromptAt < DEFAULT_CAPS.cooldownMs)\n return;\n\n const respondentKey = getRespondentKey(c.identity, c.sessionRef);\n const served = await fetchIntervention({\n endpoint: c.config.endpoint,\n key: c.config.key,\n ctx: buildServeContext(c.capture.route(), c.identity),\n respondentKey,\n debug: c.config.debug,\n });\n if (!served || !c.running) return;\n\n c.surveyOnScreen = true;\n c.interventionsShown += 1;\n c.fatigue.lastPromptAt = Date.now(); // share the cooldown with the passive prompt\n try {\n const { showSurvey } = await import(\"./survey\");\n const result = await showSurvey(served.config);\n if (!result.dismissed && (result.choice || result.text)) {\n submitResponse({\n endpoint: c.config.endpoint,\n key: c.config.key,\n interventionId: served.id,\n response: { choice: result.choice, text: result.text },\n respondentKey,\n });\n }\n } catch {\n /* swallow — a render/import failure must not surface in the host */\n } finally {\n c.surveyOnScreen = false;\n }\n}\n\nfunction onCaptureEvent() {\n const c = ctrl;\n if (!c || !c.running) return;\n\n // Re-check for a servable intervention when the route changes (SPA navigation).\n try {\n const route = c.capture.route();\n if (route && route !== c.lastServeRoute) {\n c.lastServeRoute = route;\n void maybeServeIntervention(c);\n }\n } catch {\n /* swallow */\n }\n\n if (c.eventTimer !== null) return; // debounce a burst of events into one check\n c.eventTimer = (typeof window !== \"undefined\" ? window.setTimeout : setTimeout)(() => {\n c.eventTimer = null;\n try {\n const now = Date.now();\n if (now - c.lastFrictionEmitAt < FRICTION_EMIT_COOLDOWN_MS) return;\n const kind = detectFriction(c.capture.trail(), now);\n if (!kind) return;\n c.lastFrictionEmitAt = now;\n void maybePrompt(c, \"friction\");\n } catch {\n /* swallow */\n }\n }, EVENT_DEBOUNCE_MS) as unknown as number;\n}\n\nfunction onExitIntent(ev: MouseEvent) {\n const c = ctrl;\n if (!c || !c.running || !c.config.boundaryAsk) return;\n try {\n if (ev.clientY <= 0) void maybePrompt(c, \"boundary\");\n } catch {\n /* swallow */\n }\n}\n\nfunction startRuntime(c: Controller) {\n if (c.running) return;\n if (c.suppressed) {\n if (c.config.debug)\n console.debug(\n \"[sightspool] capture suppressed on localhost (set captureOnLocalhost:true to override)\",\n );\n return;\n }\n c.running = true;\n c.capture.start();\n c.harvest.start();\n c.egress.start();\n c.capture.onEvent(onCaptureEvent);\n try {\n document.addEventListener(\"mouseout\", onExitIntent);\n } catch {\n /* swallow */\n }\n // First serve check once the page has settled (route-change checks happen in\n // onCaptureEvent thereafter).\n if (c.interventionsEnabled) {\n c.lastServeRoute = (() => {\n try {\n return c.capture.route();\n } catch {\n return null;\n }\n })();\n (typeof window !== \"undefined\" ? window.setTimeout : setTimeout)(() => {\n void maybeServeIntervention(c);\n }, SERVE_SETTLE_MS);\n }\n if (c.config.debug) console.debug(\"[sightspool] started\", c.sessionRef);\n}\n\n// --- public API --------------------------------------------------------------\n\nexport function init(config: SightspoolConfig): void {\n try {\n if (!config || !config.key) {\n console.warn(\"[sightspool] init: a `key` is required\");\n return;\n }\n if (ctrl) return; // already initialised\n const endpoint = config.endpoint || DEFAULT_ENDPOINT;\n const privacyOpts = { redact: config.redact, block: config.block };\n const capture = createCapture({ debug: !!config.debug, ...privacyOpts });\n const harvest = createHarvest(capture, { debug: !!config.debug, ...privacyOpts });\n const egress = createEgress({ key: config.key, endpoint, debug: !!config.debug });\n ctrl = {\n config: {\n ...config,\n key: config.key,\n endpoint,\n boundaryAsk: config.boundaryAsk !== false,\n debug: !!config.debug,\n },\n capture,\n harvest,\n egress,\n identity: {},\n sessionRef: uuid(),\n fatigue: { promptsShown: 0, lastPromptAt: null },\n lastFrictionEmitAt: 0,\n eventTimer: null,\n running: false,\n suppressed: isLocalhost(currentHostname()) && config.captureOnLocalhost !== true,\n interventionsEnabled: config.interventions !== false,\n lastServeRoute: null,\n surveyOnScreen: false,\n interventionsShown: 0,\n };\n if (config.consent !== false) startRuntime(ctrl);\n } catch (err) {\n // init itself must never throw into the host.\n try {\n console.warn(\"[sightspool] init failed\", err);\n } catch {\n /* swallow */\n }\n }\n}\n\nexport function identify(userId: string, traits?: { account?: string; plan?: string }): void {\n try {\n if (!ctrl) return;\n ctrl.identity = { userId, account: traits?.account, plan: traits?.plan };\n ctrl.egress.setIdentity(ctrl.identity);\n } catch {\n /* swallow */\n }\n}\n\n/** Begin capture if init was called with { consent: false }. */\nexport function start(): void {\n try {\n if (ctrl) startRuntime(ctrl);\n } catch {\n /* swallow */\n }\n}\n\n/**\n * Runtime consent gate (a clean toggle over start()/stop()) — wire it to your cookie\n * banner: `Sightspool.consent(true)` resumes capture, `Sightspool.consent(false)`\n * pauses and flushes. Pairs with init `{ consent: false }` to stay dark until granted.\n */\nexport function consent(granted: boolean): void {\n try {\n if (!ctrl) return;\n if (granted) startRuntime(ctrl);\n else stop();\n } catch {\n /* swallow */\n }\n}\n\n/** Pause capture and flush whatever's queued. */\nexport function stop(): void {\n try {\n if (!ctrl) return;\n ctrl.running = false;\n ctrl.capture.stop();\n ctrl.harvest.stop();\n ctrl.egress.stop();\n try {\n document.removeEventListener(\"mouseout\", onExitIntent);\n } catch {\n /* swallow */\n }\n } catch {\n /* swallow */\n }\n}\n\nconst api = { init, identify, start, stop, consent };\nexport default api;\n\n// --- script-tag auto-init ----------------------------------------------------\n// The standalone <script data-sightspool-key=\"pk_…\"> install auto-boots from its\n// own tag's data attributes. (No-op for the ESM build: module scripts have no\n// document.currentScript, so bundler consumers always call init() themselves.)\ntry {\n if (typeof document !== \"undefined\") {\n // currentScript is null for async/defer/dynamically-injected scripts (e.g.\n // Next's <Script> component), so fall back to finding our tag by attribute.\n const el =\n (document.currentScript as HTMLScriptElement | null) ??\n document.querySelector<HTMLScriptElement>(\"script[data-sightspool-key]\");\n const key = el?.getAttribute(\"data-sightspool-key\");\n if (key) {\n // Default the ingest endpoint to where the bundle was served from — the app\n // serves /sdk.global.js, so a same-origin script install needs only the key.\n // An explicit data-sightspool-endpoint still wins (e.g. a CDN-hosted bundle).\n let endpoint = el?.getAttribute(\"data-sightspool-endpoint\") || undefined;\n if (!endpoint && el?.src) {\n try {\n endpoint = new URL(el.src).origin;\n } catch {\n /* keep the built-in default */\n }\n }\n // Comma-separated CSS selectors → string[] (the script-tag equivalent of the\n // init() arrays; bundler users pass arrays directly).\n const list = (attr: string): string[] | undefined => {\n const raw = el?.getAttribute(attr);\n if (!raw) return undefined;\n const out = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n return out.length ? out : undefined;\n };\n init({\n key,\n endpoint,\n redact: list(\"data-sightspool-redact\"),\n block: list(\"data-sightspool-block\"),\n captureOnLocalhost: el?.hasAttribute(\"data-sightspool-capture-localhost\") || undefined,\n interventions: el?.hasAttribute(\"data-sightspool-no-interventions\") ? false : undefined,\n debug: el?.hasAttribute(\"data-sightspool-debug\") || undefined,\n });\n }\n }\n} catch {\n /* swallow */\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/research.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type SightspoolConfig = {\n /** Public workspace widget key from Go live (UUID, not an old pk_live key). */\n key: string;\n /** Match the approved research audience. No default that widens recruitment. */\n audience: \"all_visitors\" | \"signed_in\";\n /** Sightspool origin. Defaults to the hosted application. */\n endpoint?: string;\n};\nexport type ResearchStatus =\n | \"not_initialized\" | \"signed_out\" | \"paused\" | \"checking\"\n | \"unavailable\" | \"available\" | \"error\";\n\ntype Runtime = {\n key: string; endpoint: string; audience: SightspoolConfig[\"audience\"]; identified: boolean; paused: boolean;\n disposed: boolean; generation: number; device: string; offer: string | null;\n button: HTMLButtonElement | null; popup: Window | null;\n pending: AbortController | null; timer: number; visibility: () => void;\n status: ResearchStatus;\n};\nconst slot = Symbol.for(\"sightspool.research.runtime.v1\");\ntype Host = Window & { [slot]?: Runtime };\nconst host = (): Host | null => typeof window === \"undefined\" ? null : window as Host;\nconst current = () => host()?.[slot];\nconst eligible = (r: Runtime) => r.audience === \"all_visitors\" || r.identified;\n\nfunction remove(r: Runtime) {\n r.button?.remove(); r.button = null; r.offer = null;\n}\nfunction invalidate(r: Runtime) {\n r.generation += 1; r.pending?.abort(); r.pending = null; remove(r);\n}\nfunction status(r: Runtime, value: ResearchStatus) { r.status = value; }\n\nasync function check(r: Runtime) {\n if (r.disposed || r.paused || !eligible(r) || r.pending || document.visibilityState !== \"visible\") return;\n const generation = r.generation;\n const request = new AbortController();\n r.pending = request;\n const timeout = window.setTimeout(() => request.abort(), 10_000);\n if (!r.button) status(r, \"checking\");\n try {\n const response = await fetch(r.endpoint + \"/widget-offer\", {\n method: \"POST\", credentials: \"omit\", cache: \"no-store\", referrerPolicy: \"no-referrer\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ operation: \"offer\", key: r.key, device: r.device }),\n signal: request.signal,\n });\n if (!response.ok) throw Error(\"offer unavailable\");\n const result = await response.json();\n if (r.disposed || generation !== r.generation || r.paused || !eligible(r)) return;\n if (result.available !== true || typeof result.offer !== \"string\" || !result.offer) {\n remove(r); status(r, \"unavailable\"); return;\n }\n r.offer = result.offer;\n status(r, \"available\");\n if (r.button) return;\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.textContent = \"Talk to the founder · 5 min\";\n button.setAttribute(\"aria-label\", \"Sightspool: join a five-minute user interview\");\n button.style.cssText = \"position:fixed;bottom:20px;right:20px;z-index:2147483000;padding:14px 18px;border:0;border-radius:16px;background:#171717;color:white;font:500 14px system-ui;box-shadow:0 8px 30px #0003;cursor:pointer;max-width:calc(100vw - 40px)\";\n button.onclick = () => {\n try {\n if (r.disposed || r.paused || !eligible(r) || !r.offer) return;\n if (r.popup && !r.popup.closed) { r.popup.focus(); return; }\n const hash = new URLSearchParams({ offer: r.offer, device: r.device });\n r.popup = window.open(r.endpoint + \"/interview-widget#\" + hash, \"sightspool-interview\", \"popup,width=520,height=760\");\n } catch { /* Host pages remain usable if popups are blocked. */ }\n };\n r.button = button;\n document.body.appendChild(button);\n } catch {\n if (!r.disposed && generation === r.generation) { remove(r); status(r, \"error\"); }\n } finally {\n window.clearTimeout(timeout);\n if (r.pending === request) r.pending = null;\n }\n}\n\n/** Start research for the chosen audience. Signed-in-only waits for identify(). */\nexport function init(config: SightspoolConfig): void {\n try {\n const browser = host();\n if (!browser || !config || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(config.key)) return;\n if (config.audience !== \"all_visitors\" && config.audience !== \"signed_in\") return;\n const url = new URL(config.endpoint || \"https://www.sightspool.com\");\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname))) return;\n if (url.username || url.password) return;\n const previous = current();\n if (previous && previous.key === config.key && previous.endpoint === url.origin && previous.audience === config.audience) return;\n if (previous) destroy();\n let device = \"\";\n try { device = sessionStorage.getItem(\"sightspool-widget-device:\" + config.key) || \"\"; } catch {}\n if (!/^ss_fcd_[A-Za-z0-9_-]{43}$/.test(device)) {\n const bytes = crypto.getRandomValues(new Uint8Array(32));\n device = \"ss_fcd_\" + btoa(String.fromCharCode(...bytes)).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replace(/=+$/, \"\");\n try { sessionStorage.setItem(\"sightspool-widget-device:\" + config.key, device); } catch {}\n }\n const r: Runtime = {\n key: config.key, endpoint: url.origin, audience: config.audience, identified: false, paused: false,\n disposed: false, generation: 0, device, offer: null, button: null,\n popup: null, pending: null, timer: 0, visibility: () => {}, status: \"signed_out\",\n };\n browser[slot] = r;\n r.visibility = () => {\n try {\n if (document.visibilityState === \"visible\") void check(r);\n else { invalidate(r); status(r, r.paused ? \"paused\" : eligible(r) ? \"unavailable\" : \"signed_out\"); }\n } catch {}\n };\n document.addEventListener(\"visibilitychange\", r.visibility);\n r.timer = window.setInterval(() => { void check(r); }, 15_000);\n if (eligible(r)) void check(r);\n } catch { /* Never throw into the host application. */ }\n}\n\n/** Only the presence of an ID is retained. The ID itself is never stored or sent. */\nexport function identify(userId: string | null | undefined): void {\n try {\n const r = current();\n if (!r) return;\n const identified = typeof userId === \"string\" && userId.trim().length > 0;\n if (!identified && !r.identified) { if (!r.paused && eligible(r)) void check(r); return; }\n invalidate(r);\n r.identified = identified;\n status(r, r.paused ? \"paused\" : eligible(r) ? \"unavailable\" : \"signed_out\");\n if (eligible(r) && !r.paused) void check(r);\n } catch {}\n}\nexport function pause(): void {\n try { const r = current(); if (r) { r.paused = true; invalidate(r); status(r, \"paused\"); } } catch {}\n}\nexport function resume(): void {\n try { const r = current(); if (r) { r.paused = false; if (!eligible(r)) status(r, \"signed_out\"); void check(r); } } catch {}\n}\n/** Stop recruitment and remove listeners/UI. Does not end an already opened interview. */\nexport function destroy(): void {\n try {\n const r = current();\n if (!r) return;\n r.disposed = true; invalidate(r);\n window.clearInterval(r.timer);\n document.removeEventListener(\"visibilitychange\", r.visibility);\n delete host()![slot];\n } catch {}\n}\nexport function getStatus(): ResearchStatus {\n try { return current()?.status ?? \"not_initialized\"; } catch { return \"error\"; }\n}\n","// Research is the public SDK. The former capture engine is parked.\nexport { init, identify, pause, resume, destroy, getStatus } from \"./research\";\nexport type { SightspoolConfig, ResearchStatus } from \"./research\";\nimport { init, identify, pause, resume, destroy, getStatus } from \"./research\";\nexport default { init, identify, pause, resume, destroy, getStatus };\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"package": "@sightspool/sdk",
|
|
4
|
+
"version": "0.4.0",
|
|
5
|
+
"sourceCommit": "7b10230d4b59aedbdac0266aef4f4df88d574509",
|
|
6
|
+
"sourceDirty": false,
|
|
7
|
+
"artifactId": "781ab339e13fe18b86b56cc9d84dd308bebf6482a885c8aae46a8b3b84801f6e",
|
|
8
|
+
"bundle": {
|
|
9
|
+
"file": "sdk.global.js",
|
|
10
|
+
"path": "releases/0.4.0/781ab339e13fe18b86b56cc9d84dd308bebf6482a885c8aae46a8b3b84801f6e/sdk.global.js",
|
|
11
|
+
"sha256": "ed80800d20ddd91aebde61c355bb15918c0c5cbd712b91e13604795f2d2a8aa9",
|
|
12
|
+
"integrity": "sha384-kfq0QJNOieKKBsyznFRRW9kAaC5fcXvDzu56zgNsSzbXCVw2aReY66mlq8Fldy6K",
|
|
13
|
+
"bytes": 4902,
|
|
14
|
+
"gzipBytes": 2238
|
|
15
|
+
},
|
|
16
|
+
"source": {
|
|
17
|
+
"file": "source.json",
|
|
18
|
+
"sha256": "563f39e79e11d55279cd9ddfb02e2d5c7c4cdc653b4d9f57ab6c36dc4874dfa4"
|
|
19
|
+
},
|
|
20
|
+
"runtimeDependencies": []
|
|
21
|
+
}
|
package/dist/sdk.global.js
CHANGED
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
var Sightspool=(function(exports){'use strict';var
|
|
2
|
-
|
|
3
|
-
.wrap { position: fixed; bottom: 20px; right: 20px; z-index: 2147483000;
|
|
4
|
-
width: 320px; max-width: calc(100vw - 32px); font-family: system-ui, -apple-system, sans-serif; }
|
|
5
|
-
.card { background: #fff; color: #18181b; border: 1px solid #e4e4e7; border-radius: 12px;
|
|
6
|
-
box-shadow: 0 10px 30px rgba(0,0,0,.12); padding: 16px; }
|
|
7
|
-
.q { font-size: 14px; font-weight: 600; margin: 0 0 12px; line-height: 1.35; }
|
|
8
|
-
.row { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
9
|
-
button { font: inherit; font-size: 13px; cursor: pointer; border-radius: 8px; padding: 8px 12px;
|
|
10
|
-
border: 1px solid #e4e4e7; background: #fafafa; color: #18181b; }
|
|
11
|
-
button:hover { background: #f4f4f5; }
|
|
12
|
-
button.primary { background: #18181b; color: #fff; border-color: #18181b; }
|
|
13
|
-
.cand { display: block; width: 100%; text-align: left; margin-bottom: 6px; }
|
|
14
|
-
.disc { font-size: 11px; color: #71717a; margin: 12px 0 0; }
|
|
15
|
-
.x { position: absolute; top: 8px; right: 10px; border: none; background: none; font-size: 16px;
|
|
16
|
-
color: #a1a1aa; padding: 2px 6px; }
|
|
17
|
-
input { font: inherit; font-size: 13px; width: 100%; box-sizing: border-box; padding: 8px 10px;
|
|
18
|
-
border: 1px solid #e4e4e7; border-radius: 8px; margin-bottom: 8px; }
|
|
19
|
-
`;});var rt={};F(rt,{showSurvey:()=>Nt});function Nt(t){return new Promise(e=>{if(typeof document=="undefined"){e({dismissed:true});return}let n=false,o=document.createElement("div"),r=o.attachShadow({mode:"open"});function s(){try{o.remove();}catch(i){}}function f(i,u){n||(n=true,e(i),u?(m(),setTimeout(s,1100)):s());}let a=document.createElement("style");a.textContent=Lt,r.appendChild(a);let d=document.createElement("div");d.className="wrap",r.appendChild(d);function p(){d.innerHTML="";let i=document.createElement("div");return i.className="card",d.appendChild(i),i}function v(i){let u=document.createElement("button");u.className="x",u.textContent="\xD7",u.setAttribute("aria-label","Dismiss"),u.onclick=()=>f({dismissed:true},false),i.appendChild(u);}function y(){var g,C,E;let i=p();v(i);let u=document.createElement("p");u.className="q",u.textContent=t.question,i.appendChild(u);for(let w of ((g=t.options)!=null?g:[]).slice(0,6)){let c=document.createElement("button");c.className="opt",c.textContent=w,c.onclick=()=>f({choice:w},true),i.appendChild(c);}if(t.allow_text){let w=document.createElement("button");w.className="opt",w.textContent=((E=(C=t.options)==null?void 0:C.length)!=null?E:0)>0?"Something else\u2026":"Answer\u2026",w.onclick=l,i.appendChild(w);}}function l(){let i=p();v(i);let u=document.createElement("p");u.className="q",u.textContent=t.question,i.appendChild(u);let g=document.createElement("input");g.type="text",g.placeholder="In your own words\u2026",i.appendChild(g);let C=document.createElement("div");C.className="row";let E=document.createElement("button");E.className="primary",E.textContent="Send";let w=()=>{let c=g.value.trim();if(!c){f({dismissed:true},false);return}f({text:c},true);};E.onclick=w,g.onkeydown=c=>{c.key==="Enter"&&w();},C.appendChild(E),i.appendChild(C);try{g.focus();}catch(c){}}function m(){let i=p(),u=document.createElement("p");u.className="done",u.textContent="Thanks \u2014 that helps.",i.appendChild(u);}try{document.body.appendChild(o),y();}catch(i){f({dismissed:true},false);}})}var Lt,it=H(()=>{Lt=`
|
|
20
|
-
:host { all: initial; }
|
|
21
|
-
.wrap { position: fixed; bottom: 20px; right: 20px; z-index: 2147483000;
|
|
22
|
-
width: 340px; max-width: calc(100vw - 32px); font-family: system-ui, -apple-system, sans-serif; }
|
|
23
|
-
.card { position: relative; background: #fff; color: #18181b; border: 1px solid #e4e4e7;
|
|
24
|
-
border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.12); padding: 16px; }
|
|
25
|
-
.q { font-size: 14px; font-weight: 600; margin: 0 0 12px; line-height: 1.35; padding-right: 16px; }
|
|
26
|
-
.row { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
27
|
-
button { font: inherit; font-size: 13px; cursor: pointer; border-radius: 8px; padding: 8px 12px;
|
|
28
|
-
border: 1px solid #e4e4e7; background: #fafafa; color: #18181b; }
|
|
29
|
-
button:hover { background: #f4f4f5; }
|
|
30
|
-
button.primary { background: #18181b; color: #fff; border-color: #18181b; }
|
|
31
|
-
.opt { display: block; width: 100%; text-align: left; margin-bottom: 6px; }
|
|
32
|
-
.x { position: absolute; top: 8px; right: 10px; border: none; background: none; font-size: 16px;
|
|
33
|
-
color: #a1a1aa; padding: 2px 6px; cursor: pointer; }
|
|
34
|
-
.done { font-size: 13px; color: #18181b; margin: 0; }
|
|
35
|
-
input { font: inherit; font-size: 13px; width: 100%; box-sizing: border-box; padding: 8px 10px;
|
|
36
|
-
border: 1px solid #e4e4e7; border-radius: 8px; margin-bottom: 8px; }
|
|
37
|
-
`;});R();var K=30,bt=700,vt=1e3,xt=3;function wt(){return typeof window!="undefined"&&typeof document!="undefined"}function W(t){var E,w;let e=(E=t.redact)!=null?E:[],n=(w=t.block)!=null?w:[],o=[],r,s=false,f=[],a=[],d=[];function p(){for(let c of f)try{c();}catch(b){}}function v(c,b){try{o.push({t:Date.now(),type:c,label:b?U(b):void 0}),o.length>K&&(o=o.slice(-K)),t.debug&&console.debug("[sightspool] event",c,b),p();}catch(h){}}function y(){try{return location.pathname+location.search}catch(c){return ""}}function l(){try{return document.title||""}catch(c){return ""}}function m(c){var b;try{let h=c.target;if(I(h,n))return;let T=h&&(((b=h.getAttribute)==null?void 0:b.call(h,"aria-label"))||h.textContent)||"",k=A(h,e)?B:T.trim().slice(0,60),D=Date.now();d=d.filter(N=>D-N<=vt),d.push(D);let pt=d.length>=xt;v(pt?"rage_click":"click",k);let ft=y(),q=!1,_=null;try{_=new MutationObserver(()=>{q=!0;}),_.observe(document.body,{childList:!0,subtree:!0,attributes:!0});}catch(N){}window.setTimeout(()=>{try{_==null||_.disconnect(),!q&&y()===ft&&k&&v("dead_click",k);}catch(N){}},bt);}catch(h){}}function i(c){try{r=String(c.message||"error"),v("error",r);}catch(b){}}function u(c){try{let b=c.reason;r=b instanceof Error?b.message:String(b),v("error",r);}catch(b){}}function g(){try{let c=()=>v("route",y()),b=history.pushState,h=history.replaceState;history.pushState=function(...T){let k=b.apply(this,T);return c(),k},history.replaceState=function(...T){let k=h.apply(this,T);return c(),k},window.addEventListener("popstate",c),a.push(()=>{history.pushState=b,history.replaceState=h,window.removeEventListener("popstate",c);}),v("route",y());}catch(c){}}function C(){try{if(typeof window.fetch!="function")return;let c=window.fetch.bind(window);window.fetch=async(...b)=>{try{let h=await c(...b);return h.ok||v("request_error",`HTTP ${h.status}`),h}catch(h){throw v("request_error",h instanceof Error?h.message:"network error"),h}},a.push(()=>{window.fetch=c;});}catch(c){}}return {start(){if(!(s||!wt())){s=true;try{document.addEventListener("click",m,!0),window.addEventListener("error",i),window.addEventListener("unhandledrejection",u),a.push(()=>{document.removeEventListener("click",m,!0),window.removeEventListener("error",i),window.removeEventListener("unhandledrejection",u);}),g(),C();}catch(c){}}},stop(){s=false;for(let c of a.splice(0))try{c();}catch(b){}},trail(){return o.slice()},route:y,label:l,error(){return r},onEvent(c){f.push(c);},recordSearch(c,b){let h=c.trim();h&&v(b?"zero_result":"search",h);}}}R();var Et=/search|filter|find|query|command|lookup/i,St=800;function Ct(t){try{let e=t;if(e.type==="search")return !0;let n=t.getAttribute("role")||"";if(n==="searchbox"||n==="combobox")return !0;let o=[e.name,e.placeholder,t.getAttribute("aria-label"),t.id,t.className].filter(Boolean).join(" ");return Et.test(o)}catch(e){return false}}function j(t,e){var d,p;let n,o=null,r=false,s=(d=e.redact)!=null?d:[],f=(p=e.block)!=null?p:[];function a(v){try{let y=v.target;if(!y||y.tagName!=="INPUT"&&y.tagName!=="TEXTAREA"||!Ct(y)||I(y,f)||A(y,s))return;let l=(y.value||"").trim();if(l.length<2)return;o!==null&&window.clearTimeout(o),o=window.setTimeout(()=>{n=l,t.recordSearch(l),e.debug&&console.debug("[sightspool] harvested intent",l);},St);}catch(y){}}return {start(){if(!(r||typeof document=="undefined")){r=true;try{document.addEventListener("input",a,!0);}catch(v){}}},stop(){r=false;try{document.removeEventListener("input",a,!0),o!==null&&window.clearTimeout(o);}catch(v){}},lastIntentHint(){return n}}}function G(t){let e=[],n,o=null,r=false,s=`${t.endpoint.replace(/\/+$/,"")}/api/sdk/ingest`;function f(p){if(p.length===0)return;let v={key:t.key,identity:n,signals:p},y=JSON.stringify(v);try{if(typeof navigator!="undefined"&&typeof navigator.sendBeacon=="function"){let l=new Blob([y],{type:"text/plain"});if(navigator.sendBeacon(s,l)){t.debug&&console.debug("[sightspool] beacon",p.length);return}}fetch(s,{method:"POST",headers:{"Content-Type":"text/plain"},body:y,keepalive:!0,mode:"cors",credentials:"omit"}).catch(()=>{});}catch(l){}}function a(){try{document.visibilityState==="hidden"&&d();}catch(p){}}function d(){if(e.length===0)return;let p=e;e=[],f(p);}return {start(){if(!(r||typeof window=="undefined")){r=true;try{document.addEventListener("visibilitychange",a),window.addEventListener("pagehide",d),o=window.setInterval(d,15e3);}catch(p){}}},stop(){r=false;try{document.removeEventListener("visibilitychange",a),window.removeEventListener("pagehide",d),o!==null&&window.clearInterval(o);}catch(p){}d();},enqueue(p){e.push(p),e.length>=10&&d();},flush:d,setIdentity(p){n=p;}}}function $(t,e,n=8e3){var f;let o=t.filter(a=>e-a.t<=n);if(o.some(a=>a.type==="error"||a.type==="request_error"))return "error";let r=o.filter(a=>a.type==="click"||a.type==="rage_click");for(let a=0;a<r.length;a++)if(r.filter(p=>p.t>=r[a].t&&p.t-r[a].t<=1e3).length>=3)return "rage";if(o.some(a=>a.type==="dead_click"))return "dead_end";let s=new Map;for(let a of r){if(!a.label)continue;let d=((f=s.get(a.label))!=null?f:0)+1;if(s.set(a.label,d),d>=3)return "retry"}return null}var L={maxPromptsPerSession:1,cooldownMs:5*6e4};function Y(t,e,n=L){return !(t.promptsShown>=n.maxPromptsPerSession||t.lastPromptAt!==null&&e-t.lastPromptAt<n.cooldownMs)}var kt=new Set(["survey"]);function S(t,e){if(typeof t!="string")return;let n=t.trim();return n?n.slice(0,e):void 0}function X(t,e){let n={},o=S(t,500);o&&(n.route=o);let r=S(e==null?void 0:e.account,200);r&&(n.account=r);let s=S(e==null?void 0:e.plan,80);return s&&(n.plan=s),n}function Tt(t){if(!t||typeof t!="object")return null;let e=t,n=S(e.id,64),o=S(e.type,40);if(!n||!o||!kt.has(o))return null;let r=e.config&&typeof e.config=="object"?e.config:{},s=S(r.question,500);if(!s)return null;let f=Array.isArray(r.options)?r.options.map(d=>S(d,200)).filter(d=>!!d).slice(0,6):void 0,a={question:s,...f&&f.length?{options:f}:{},allow_text:r.allow_text===true};return {id:n,type:o,config:a}}function _t(t,e,n){let o=S(t,200);if(o)return o;let r=S(e,200);return r||n}var V="sightspool_rk";function J(t,e){let n=S(t==null?void 0:t.userId,200);if(n)return n;try{let o=localStorage.getItem(V);return o||(o="anon-"+Math.random().toString(36).slice(2)+Date.now().toString(36),localStorage.setItem(V,o)),_t(void 0,o,e)}catch(o){return e}}function Z(t,e){return `${t.replace(/\/+$/,"")}/api/sdk/${e}`}async function Q(t){var e;try{if(typeof fetch!="function")return null;let n=await fetch(Z(t.endpoint,"serve"),{method:"POST",headers:{"Content-Type":"text/plain"},body:JSON.stringify({key:t.key,context:t.ctx,respondent_key:t.respondentKey}),mode:"cors",credentials:"omit"});if(!n.ok)return null;let o=await n.json(),r=Tt(o==null?void 0:o.intervention);return t.debug&&console.debug("[sightspool] serve",(e=r==null?void 0:r.id)!=null?e:"(none)"),r}catch(n){return null}}function tt(t){try{let e=Z(t.endpoint,"respond"),n=JSON.stringify({key:t.key,intervention_id:t.interventionId,response:t.response,respondent_key:t.respondentKey});if(typeof navigator!="undefined"&&typeof navigator.sendBeacon=="function"){let o=new Blob([n],{type:"text/plain"});if(navigator.sendBeacon(e,o))return}typeof fetch=="function"&&fetch(e,{method:"POST",headers:{"Content-Type":"text/plain"},body:n,keepalive:!0,mode:"cors",credentials:"omit"}).catch(()=>{});}catch(e){}}var It=new Set(["localhost","127.0.0.1","0.0.0.0","::1",""]);function et(t){let e=(t!=null?t:"").trim().toLowerCase();return It.has(e)?true:e.endsWith(".local")||e.endsWith(".localhost")}var Ht="https://www.sightspool.com",Ot=3e4,Pt=600,Mt=2500,Dt=1;function qt(){try{return typeof location!="undefined"?location.hostname:""}catch(t){return ""}}var x=null;function Ft(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(t){}return "s-"+Math.random().toString(36).slice(2)+Date.now().toString(36)}function Ut(t){let e=[],n=t.harvest.lastIntentHint();n&&e.push(`Searching for \u201C${n}\u201D`);let o=t.capture.label();return o&&e.push(`Something on \u201C${o.slice(0,40)}\u201D`),e}function P(t,e,n={}){let o=t.capture.error();return {captured_at:new Date().toISOString(),route:t.capture.route(),client_label:t.capture.label(),trail:t.capture.trail(),session_ref:t.sessionRef,trigger:e,intent_hint:t.harvest.lastIntentHint(),error:o,outcome:o||e==="friction"?"failed":"unknown",...n}}async function at(t,e){var o;let n=Date.now();if(Y(t.fatigue,n,L)){t.fatigue.promptsShown+=1,t.fatigue.lastPromptAt=n;try{let{showPrompt:r}=await Promise.resolve().then(()=>(ot(),nt)),s=await r({candidates:Ut(t)});t.egress.enqueue(P(t,e,{answer:s.answer,verbatim:s.verbatim,intent_hint:(o=s.intent)!=null?o:t.harvest.lastIntentHint(),outcome:s.answer==="yes"?"achieved":"failed"}));}catch(r){t.egress.enqueue(P(t,e));}}else t.egress.enqueue(P(t,e));}async function ct(t){if(!t.running||!t.interventionsEnabled||t.suppressed||t.surveyOnScreen||t.interventionsShown>=Dt)return;let e=Date.now();if(t.fatigue.lastPromptAt!==null&&e-t.fatigue.lastPromptAt<L.cooldownMs)return;let n=J(t.identity,t.sessionRef),o=await Q({endpoint:t.config.endpoint,key:t.config.key,ctx:X(t.capture.route(),t.identity),respondentKey:n,debug:t.config.debug});if(!(!o||!t.running)){t.surveyOnScreen=true,t.interventionsShown+=1,t.fatigue.lastPromptAt=Date.now();try{let{showSurvey:r}=await Promise.resolve().then(()=>(it(),rt)),s=await r(o.config);!s.dismissed&&(s.choice||s.text)&&tt({endpoint:t.config.endpoint,key:t.config.key,interventionId:o.id,response:{choice:s.choice,text:s.text},respondentKey:n});}catch(r){}finally{t.surveyOnScreen=false;}}}function zt(){let t=x;if(!(!t||!t.running)){try{let e=t.capture.route();e&&e!==t.lastServeRoute&&(t.lastServeRoute=e,ct(t));}catch(e){}t.eventTimer===null&&(t.eventTimer=(typeof window!="undefined"?window.setTimeout:setTimeout)(()=>{t.eventTimer=null;try{let e=Date.now();if(e-t.lastFrictionEmitAt<Ot||!$(t.capture.trail(),e))return;t.lastFrictionEmitAt=e,at(t,"friction");}catch(e){}},Pt));}}function ut(t){let e=x;if(!(!e||!e.running||!e.config.boundaryAsk))try{t.clientY<=0&&at(e,"boundary");}catch(n){}}function M(t){if(!t.running){if(t.suppressed){t.config.debug&&console.debug("[sightspool] capture suppressed on localhost (set captureOnLocalhost:true to override)");return}t.running=true,t.capture.start(),t.harvest.start(),t.egress.start(),t.capture.onEvent(zt);try{document.addEventListener("mouseout",ut);}catch(e){}t.interventionsEnabled&&(t.lastServeRoute=(()=>{try{return t.capture.route()}catch(e){return null}})(),(typeof window!="undefined"?window.setTimeout:setTimeout)(()=>{ct(t);},Mt)),t.config.debug&&console.debug("[sightspool] started",t.sessionRef);}}function dt(t){try{if(!t||!t.key){console.warn("[sightspool] init: a `key` is required");return}if(x)return;let e=t.endpoint||Ht,n={redact:t.redact,block:t.block},o=W({debug:!!t.debug,...n}),r=j(o,{debug:!!t.debug,...n}),s=G({key:t.key,endpoint:e,debug:!!t.debug});x={config:{...t,key:t.key,endpoint:e,boundaryAsk:t.boundaryAsk!==!1,debug:!!t.debug},capture:o,harvest:r,egress:s,identity:{},sessionRef:Ft(),fatigue:{promptsShown:0,lastPromptAt:null},lastFrictionEmitAt:0,eventTimer:null,running:!1,suppressed:et(qt())&&t.captureOnLocalhost!==!0,interventionsEnabled:t.interventions!==!1,lastServeRoute:null,surveyOnScreen:!1,interventionsShown:0},t.consent!==!1&&M(x);}catch(e){try{console.warn("[sightspool] init failed",e);}catch(n){}}}function Bt(t,e){try{if(!x)return;x.identity={userId:t,account:e==null?void 0:e.account,plan:e==null?void 0:e.plan},x.egress.setIdentity(x.identity);}catch(n){}}function Kt(){try{x&&M(x);}catch(t){}}function Wt(t){try{if(!x)return;t?M(x):lt();}catch(e){}}function lt(){try{if(!x)return;x.running=!1,x.capture.stop(),x.harvest.stop(),x.egress.stop();try{document.removeEventListener("mouseout",ut);}catch(t){}}catch(t){}}var jt={init:dt,identify:Bt,start:Kt,stop:lt,consent:Wt},ue=jt,st;try{if(typeof document!="undefined"){let t=(st=document.currentScript)!=null?st:document.querySelector("script[data-sightspool-key]"),e=t==null?void 0:t.getAttribute("data-sightspool-key");if(e){let n=(t==null?void 0:t.getAttribute("data-sightspool-endpoint"))||void 0;if(!n&&(t!=null&&t.src))try{n=new URL(t.src).origin;}catch(r){}let o=r=>{let s=t==null?void 0:t.getAttribute(r);if(!s)return;let f=s.split(",").map(a=>a.trim()).filter(Boolean);return f.length?f:void 0};dt({key:e,endpoint:n,redact:o("data-sightspool-redact"),block:o("data-sightspool-block"),captureOnLocalhost:(t==null?void 0:t.hasAttribute("data-sightspool-capture-localhost"))||void 0,interventions:t!=null&&t.hasAttribute("data-sightspool-no-interventions")?!1:void 0,debug:(t==null?void 0:t.hasAttribute("data-sightspool-debug"))||void 0});}}}catch(t){}
|
|
38
|
-
exports.consent=Wt;exports.default=ue;exports.identify=Bt;exports.init=dt;exports.start=Kt;exports.stop=lt;Object.defineProperty(exports,'__esModule',{value:true});return exports;})({});//# sourceMappingURL=sdk.global.js.map
|
|
1
|
+
var Sightspool=(function(exports){'use strict';var y=Symbol.for("sightspool.research.runtime.v1"),v=()=>typeof window=="undefined"?null:window,l=()=>{var e;return (e=v())==null?void 0:e[y]},a=e=>e.audience==="all_visitors"||e.identified;function h(e){var t;(t=e.button)==null||t.remove(),e.button=null,e.offer=null;}function c(e){var t;e.generation+=1,(t=e.pending)==null||t.abort(),e.pending=null,h(e);}function r(e,t){e.status=t;}async function u(e){if(e.disposed||e.paused||!a(e)||e.pending||document.visibilityState!=="visible")return;let t=e.generation,i=new AbortController;e.pending=i;let d=window.setTimeout(()=>i.abort(),1e4);e.button||r(e,"checking");try{let s=await fetch(e.endpoint+"/widget-offer",{method:"POST",credentials:"omit",cache:"no-store",referrerPolicy:"no-referrer",headers:{"Content-Type":"application/json"},body:JSON.stringify({operation:"offer",key:e.key,device:e.device}),signal:i.signal});if(!s.ok)throw Error("offer unavailable");let n=await s.json();if(e.disposed||t!==e.generation||e.paused||!a(e))return;if(n.available!==!0||typeof n.offer!="string"||!n.offer){h(e),r(e,"unavailable");return}if(e.offer=n.offer,r(e,"available"),e.button)return;let o=document.createElement("button");o.type="button",o.textContent="Talk to the founder \xB7 5 min",o.setAttribute("aria-label","Sightspool: join a five-minute user interview"),o.style.cssText="position:fixed;bottom:20px;right:20px;z-index:2147483000;padding:14px 18px;border:0;border-radius:16px;background:#171717;color:white;font:500 14px system-ui;box-shadow:0 8px 30px #0003;cursor:pointer;max-width:calc(100vw - 40px)",o.onclick=()=>{try{if(e.disposed||e.paused||!a(e)||!e.offer)return;if(e.popup&&!e.popup.closed){e.popup.focus();return}let g=new URLSearchParams({offer:e.offer,device:e.device});e.popup=window.open(e.endpoint+"/interview-widget#"+g,"sightspool-interview","popup,width=520,height=760");}catch(g){}},e.button=o,document.body.appendChild(o);}catch(s){!e.disposed&&t===e.generation&&(h(e),r(e,"error"));}finally{window.clearTimeout(d),e.pending===i&&(e.pending=null);}}function m(e){try{let t=v();if(!t||!e||!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e.key)||e.audience!=="all_visitors"&&e.audience!=="signed_in")return;let i=new URL(e.endpoint||"https://www.sightspool.com");if(i.protocol!=="https:"&&!(i.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(i.hostname))||i.username||i.password)return;let d=l();if(d&&d.key===e.key&&d.endpoint===i.origin&&d.audience===e.audience)return;d&&f();let s="";try{s=sessionStorage.getItem("sightspool-widget-device:"+e.key)||"";}catch(o){}if(!/^ss_fcd_[A-Za-z0-9_-]{43}$/.test(s)){let o=crypto.getRandomValues(new Uint8Array(32));s="ss_fcd_"+btoa(String.fromCharCode(...o)).replaceAll("+","-").replaceAll("/","_").replace(/=+$/,"");try{sessionStorage.setItem("sightspool-widget-device:"+e.key,s);}catch(g){}}let n={key:e.key,endpoint:i.origin,audience:e.audience,identified:!1,paused:!1,disposed:!1,generation:0,device:s,offer:null,button:null,popup:null,pending:null,timer:0,visibility:()=>{},status:"signed_out"};t[y]=n,n.visibility=()=>{try{document.visibilityState==="visible"?u(n):(c(n),r(n,n.paused?"paused":a(n)?"unavailable":"signed_out"));}catch(o){}},document.addEventListener("visibilitychange",n.visibility),n.timer=window.setInterval(()=>{u(n);},15e3),a(n)&&u(n);}catch(t){}}function b(e){try{let t=l();if(!t)return;let i=typeof e=="string"&&e.trim().length>0;if(!i&&!t.identified){!t.paused&&a(t)&&u(t);return}c(t),t.identified=i,r(t,t.paused?"paused":a(t)?"unavailable":"signed_out"),a(t)&&!t.paused&&u(t);}catch(t){}}function w(){try{let e=l();e&&(e.paused=!0,c(e),r(e,"paused"));}catch(e){}}function x(){try{let e=l();e&&(e.paused=!1,a(e)||r(e,"signed_out"),u(e));}catch(e){}}function f(){try{let e=l();if(!e)return;e.disposed=!0,c(e),window.clearInterval(e.timer),document.removeEventListener("visibilitychange",e.visibility),delete v()[y];}catch(e){}}function S(){var e,t;try{return (t=(e=l())==null?void 0:e.status)!=null?t:"not_initialized"}catch(i){return "error"}}var p={init:m,identify:b,pause:w,resume:x,destroy:f,getStatus:S};var A=p;try{let e=document.currentScript,t=(e==null?void 0:e.dataset.sightspoolKey)||(e==null?void 0:e.dataset.key),i=e==null?void 0:e.dataset.sightspoolAudience;t&&(i==="all_visitors"||i==="signed_in")&&(p.init({key:t,audience:i,endpoint:(e==null?void 0:e.dataset.sightspoolEndpoint)||new URL(e.src).origin}),e!=null&&e.dataset.userId&&p.identify(e.dataset.userId)),window.SightspoolResearch=p,Promise.resolve().then(()=>window.dispatchEvent(new Event("sightspool:ready")));}catch(e){}
|
|
2
|
+
exports.default=A;exports.destroy=f;exports.getStatus=S;exports.identify=b;exports.init=m;exports.pause=w;exports.resume=x;Object.defineProperty(exports,'__esModule',{value:true});return exports;})({});//# sourceMappingURL=sdk.global.js.map
|
|
39
3
|
//# sourceMappingURL=sdk.global.js.map
|