@getcredify/credify-insurance-widget 1.40.0 → 1.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -3
- package/dist/api-RBpxlUxA.js +51 -0
- package/dist/components/ProductChooser.d.ts +5 -0
- package/dist/components/ScreenShareButton.d.ts +4 -0
- package/dist/components/Widget.d.ts +13 -0
- package/dist/components/WidgetErrorFallback.d.ts +11 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/credify-insurance-widget.css +1 -1
- package/dist/dob-calendar-RIJ5S6YU-CPTnehH2.js +2933 -0
- package/dist/fixtures-ijbZ16Zg-CD1k11fg.js +276 -0
- package/dist/iframe/assets/dob-calendar-RIJ5S6YU-D1-0B2xV.css +1 -0
- package/dist/iframe/assets/dob-calendar-RIJ5S6YU-DkeMmMY0.js +1 -0
- package/dist/iframe/assets/fixtures-ijbZ16Zg-Bj-DhqkB.js +1 -0
- package/dist/iframe/assets/iframe-CfQAC0Hv.js +494 -0
- package/dist/iframe/assets/iframe-DFqQdMHv.css +1 -0
- package/dist/iframe/assets/mockJump-CL8w249w-D4zKPVys.js +1 -0
- package/dist/iframe/assets/zipCities-CU_i9iT--B1AIvNRh.js +1 -0
- package/dist/iframe/iframe.html +2 -2
- package/dist/index.d.ts +76 -0
- package/dist/index.es.js +6 -26321
- package/dist/index.umd.js +436 -107
- package/dist/internal/IframeWidgetController.d.ts +6 -0
- package/dist/internal/WidgetController.d.ts +6 -0
- package/dist/internal/configureKit.d.ts +4 -0
- package/dist/internal/ensureFont.d.ts +2 -0
- package/dist/mock/config.d.ts +30 -0
- package/dist/mock/installMockFetch.d.ts +6 -0
- package/dist/mockJump-CL8w249w-KvYoZQMN.js +19 -0
- package/dist/utils/api.d.ts +24 -0
- package/dist/utils/events.d.ts +126 -0
- package/dist/utils/har/recorder.d.ts +32 -0
- package/dist/utils/har/types.d.ts +70 -0
- package/dist/utils/product.d.ts +30 -0
- package/dist/utils/resumeLink.d.ts +35 -0
- package/dist/utils/sentry/devEnvironment.d.ts +10 -0
- package/dist/utils/sentry/init.d.ts +33 -0
- package/dist/utils/sentry/redact.d.ts +50 -0
- package/dist/utils/sentry/reportQuoteFailure.d.ts +31 -0
- package/dist/utils/sentry/reportSideEffectFailure.d.ts +2 -0
- package/dist/utils/storage.d.ts +8 -0
- package/dist/utils/support/bland.d.ts +50 -0
- package/dist/utils/support/cobrowse.d.ts +37 -0
- package/dist/utils/support/config.d.ts +34 -0
- package/dist/utils/support/index.d.ts +27 -0
- package/dist/utils/support/loader.d.ts +13 -0
- package/dist/utils/testMode.d.ts +11 -0
- package/dist/widget-BEY4lY4B.js +27319 -0
- package/dist/zipCities-CU_i9iT--DNeFQLgu.js +3330 -0
- package/package.json +8 -4
- package/dist/backend-xPum4ql0.js +0 -387
- package/dist/backend-xPum4ql0.js.map +0 -1
- package/dist/iframe/assets/backend-CY4n4nTm.js +0 -2
- package/dist/iframe/assets/backend-CY4n4nTm.js.map +0 -1
- package/dist/iframe/assets/iframe--qj6NOS3.js +0 -164
- package/dist/iframe/assets/iframe--qj6NOS3.js.map +0 -1
- package/dist/iframe/assets/iframe-m4vqnMx_.css +0 -1
- package/dist/index.es.js.map +0 -1
- package/dist/index.umd.js.map +0 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IframeWidgetController handles the widget in iframe mode.
|
|
3
|
+
* It communicates with the parent window via postMessage API.
|
|
4
|
+
*/
|
|
5
|
+
export default function IframeWidgetController(): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=IframeWidgetController.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Product } from '@getcredify/credify-insurance-ui-kit/core';
|
|
2
|
+
export default function WidgetController({ isOpen, product }: {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
product?: Product;
|
|
5
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=WidgetController.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves whether the widget should run in MOCK mode for the current page load.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the live-support config pattern (see ../utils/support/config.ts): the
|
|
5
|
+
* key is baked at build time via the Vite `define` global `__CREDIFY_MOCK__`
|
|
6
|
+
* (from the VITE_MOCK_KEY env var). Mock mode activates only when the page URL
|
|
7
|
+
* carries `?mock=<key>` AND the value matches the baked key exactly.
|
|
8
|
+
*
|
|
9
|
+
* This is a developer/QA affordance for walking the full quote flow with no real
|
|
10
|
+
* API calls — useful for design and flow verification. Because no key is baked
|
|
11
|
+
* into normal production builds (VITE_MOCK_KEY is unset), mock mode can never be
|
|
12
|
+
* triggered there: the guard short-circuits and the live API layer is untouched.
|
|
13
|
+
*
|
|
14
|
+
* Security note: a key shipped in client JS is discoverable by anyone who reads
|
|
15
|
+
* the bundle, so this is an *unguessable* gate, not a secret. That is acceptable
|
|
16
|
+
* here because mock mode is consequence-free — it issues zero backend requests
|
|
17
|
+
* and only affects the browser session that supplied the matching key.
|
|
18
|
+
*/
|
|
19
|
+
export declare const isMockBuild: () => boolean;
|
|
20
|
+
/** URL query param that carries the mock key, e.g. `?mock=<key>`. */
|
|
21
|
+
export declare const MOCK_QUERY_PARAM = "mock";
|
|
22
|
+
/** The mock key baked into this build, or `undefined` when none was configured. */
|
|
23
|
+
export declare function getMockKey(): string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Returns true when this page load should run in mock mode: a key is baked into
|
|
26
|
+
* the build and the current URL's `?mock=` value matches it exactly. Safe to call
|
|
27
|
+
* in any environment — returns false when `window` is unavailable.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isMockEnabled(): boolean;
|
|
30
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install the mock fetch interceptor when mock mode is active for this page load.
|
|
3
|
+
* Safe and idempotent: returns immediately when mock mode is off or already set up.
|
|
4
|
+
*/
|
|
5
|
+
export declare function maybeInstallMockFetch(): void;
|
|
6
|
+
//# sourceMappingURL=installMockFetch.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { f as o } from "./widget-BEY4lY4B.js";
|
|
2
|
+
(function() {
|
|
3
|
+
if (typeof t > "u")
|
|
4
|
+
var t = { env: {} };
|
|
5
|
+
})();
|
|
6
|
+
var r = /^#step-(\d+)$/, i = (t) => {
|
|
7
|
+
let e = r.exec(t.trim());
|
|
8
|
+
if (!e) return null;
|
|
9
|
+
let n = Number.parseInt(e[1] ?? "", 10);
|
|
10
|
+
return n >= 1 ? n - 1 : null;
|
|
11
|
+
}, l = () => !o() || typeof window > "u" ? null : i(window.location.hash), w = (t) => {
|
|
12
|
+
if (!o() || typeof window > "u") return;
|
|
13
|
+
let e = `#step-${t + 1}`;
|
|
14
|
+
window.location.hash !== e && window.history.replaceState(window.history.state, "", e);
|
|
15
|
+
};
|
|
16
|
+
export {
|
|
17
|
+
l as mockStepFromUrl,
|
|
18
|
+
w as writeMockStepHash
|
|
19
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the API lives.
|
|
3
|
+
*
|
|
4
|
+
* All that survives of a 344-line client: the ui-kit owns the transport, the
|
|
5
|
+
* session and every endpoint now, and takes this as injected configuration (see
|
|
6
|
+
* internal/configureKit.ts).
|
|
7
|
+
*
|
|
8
|
+
* Read from the build environment rather than written here, because this file
|
|
9
|
+
* used to be edited to point at a local backend and the commented-out
|
|
10
|
+
* production line was one `git add` away from shipping. CI would not have
|
|
11
|
+
* caught it: a build that talks to `localhost:3000` looks perfectly healthy
|
|
12
|
+
* until it reaches a customer's browser.
|
|
13
|
+
*
|
|
14
|
+
* Local development sets `VITE_API_BASE_URL=http://localhost:3000` in `.env`.
|
|
15
|
+
* A build with no override gets production, and `scripts/check-api-url.mjs`
|
|
16
|
+
* refuses to publish anything that is not https.
|
|
17
|
+
*
|
|
18
|
+
* The kit itself has no default at all — `getApiConfig()` throws when
|
|
19
|
+
* cspell:disable-next-line
|
|
20
|
+
* unconfigured — because a silent fallback would send a real quote to the wrong
|
|
21
|
+
* host.
|
|
22
|
+
*/
|
|
23
|
+
export declare const BASE_URL: string;
|
|
24
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public event emitter for the Credify Insurance Widget.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the old GTM dataLayer integration: instead of pushing analytics
|
|
5
|
+
* events to `window.dataLayer`, the widget now emits typed events that host
|
|
6
|
+
* pages subscribe to via `CredifyInsuranceWidget.on(event, callback)`. Hosts
|
|
7
|
+
* can forward these to whatever analytics tool they use (GTM, Segment, etc.).
|
|
8
|
+
*
|
|
9
|
+
* The emitter is a module-level singleton so internal `emit*` call sites and
|
|
10
|
+
* the public `on`/`off` API share one registry within the host page's realm.
|
|
11
|
+
* In iframe mode the events are bridged to the parent window over postMessage
|
|
12
|
+
* (see internal/IframeWidgetController.tsx), since the iframe runs in a
|
|
13
|
+
* separate JS realm where this singleton is not reachable from the host.
|
|
14
|
+
*/
|
|
15
|
+
/** Payload shared by the per-stage events. */
|
|
16
|
+
export interface StageEventData {
|
|
17
|
+
stageKey: string;
|
|
18
|
+
stageTitle: string;
|
|
19
|
+
stepIndex: number;
|
|
20
|
+
totalSteps: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Correlation metadata delivered as the second argument to every listener,
|
|
24
|
+
* regardless of the event's own payload. Lets hosts stitch the funnel
|
|
25
|
+
* (widgetOpened → stageViewed → … → ratesViewed) to a single quote.
|
|
26
|
+
*
|
|
27
|
+
* `quoteId` is read from storage at emit time, so it is `null` for events that
|
|
28
|
+
* fire before a quote exists (e.g. the first `widgetOpened`/`stageViewed`) and
|
|
29
|
+
* the real id thereafter.
|
|
30
|
+
*/
|
|
31
|
+
export interface WidgetEventMeta {
|
|
32
|
+
/** The quote this event belongs to, or `null` before one has been created. */
|
|
33
|
+
quoteId: string | null;
|
|
34
|
+
/** Epoch milliseconds at which the event was emitted. */
|
|
35
|
+
timestamp: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Map of every public widget event to its callback payload. `void` means the
|
|
39
|
+
* event carries no data; its listeners are invoked with no argument.
|
|
40
|
+
*/
|
|
41
|
+
export interface WidgetEventMap {
|
|
42
|
+
/** The widget overlay was opened. */
|
|
43
|
+
widgetOpened: void;
|
|
44
|
+
/** The widget overlay was closed (Escape, close button, or programmatic). */
|
|
45
|
+
widgetClosed: void;
|
|
46
|
+
/** A form stage became visible to the user. */
|
|
47
|
+
stageViewed: StageEventData;
|
|
48
|
+
/** A form stage was successfully completed (Next/submit). */
|
|
49
|
+
stageCompleted: StageEventData;
|
|
50
|
+
/** All stages were completed and rate generation started. */
|
|
51
|
+
flowCompleted: void;
|
|
52
|
+
/** The rates screen is being shown. */
|
|
53
|
+
ratesViewed: {
|
|
54
|
+
rateCount: number;
|
|
55
|
+
};
|
|
56
|
+
/** The user navigated back from the rates screen. */
|
|
57
|
+
ratesBack: void;
|
|
58
|
+
/**
|
|
59
|
+
* Quote submission failed and the user was shown an error/timeout state.
|
|
60
|
+
* Drives proactive live support; also forwarded to hosts for analytics.
|
|
61
|
+
*/
|
|
62
|
+
submissionFailed: {
|
|
63
|
+
reason: 'submission' | 'timeout' | 'network';
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* A product-analytics event from the quote flow itself, forwarded verbatim.
|
|
67
|
+
*
|
|
68
|
+
* Additive on purpose: the flow reports things like `quote_flow_start` and
|
|
69
|
+
* `quote_step_completed`, and rather than minting a public widget event for
|
|
70
|
+
* each — freezing the flow's vocabulary into this package's API — they arrive
|
|
71
|
+
* here as a name and a payload. Existing listeners are unaffected.
|
|
72
|
+
*/
|
|
73
|
+
telemetry: {
|
|
74
|
+
event: string;
|
|
75
|
+
properties?: Record<string, unknown>;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export type WidgetEventName = keyof WidgetEventMap;
|
|
79
|
+
/**
|
|
80
|
+
* Runtime list of every event name — the single source of truth used to bridge
|
|
81
|
+
* events over postMessage in iframe mode. Declared `satisfies` so the compiler
|
|
82
|
+
* fails if it ever drifts from {@link WidgetEventMap}.
|
|
83
|
+
*/
|
|
84
|
+
export declare const WIDGET_EVENT_NAMES: readonly ["widgetOpened", "widgetClosed", "stageViewed", "stageCompleted", "flowCompleted", "ratesViewed", "ratesBack", "submissionFailed", "telemetry"];
|
|
85
|
+
export type WidgetEventListener<E extends WidgetEventName> = (data: WidgetEventMap[E], meta: WidgetEventMeta) => void;
|
|
86
|
+
/**
|
|
87
|
+
* `emit` accepts a payload argument only for events whose payload is not
|
|
88
|
+
* `void`, so `emit('widgetOpened')` and `emit('ratesViewed', { rateCount })`
|
|
89
|
+
* are both correctly typed.
|
|
90
|
+
*/
|
|
91
|
+
type EmitArgs<E extends WidgetEventName> = WidgetEventMap[E] extends void ? [] : [WidgetEventMap[E]];
|
|
92
|
+
/** Subscribe to a widget event. Re-registering the same callback is a no-op. */
|
|
93
|
+
export declare function on<E extends WidgetEventName>(event: E, callback: WidgetEventListener<E>): void;
|
|
94
|
+
/** Unsubscribe a previously registered callback. Safe to call if absent. */
|
|
95
|
+
export declare function off<E extends WidgetEventName>(event: E, callback: WidgetEventListener<E>): void;
|
|
96
|
+
/** Subscribe to the next occurrence of an event, then auto-unsubscribe. */
|
|
97
|
+
export declare function once<E extends WidgetEventName>(event: E, callback: WidgetEventListener<E>): void;
|
|
98
|
+
/**
|
|
99
|
+
* Emit an event to all subscribers. Each listener is invoked in isolation: a
|
|
100
|
+
* throwing host callback is reported to Sentry and never breaks the widget or
|
|
101
|
+
* prevents the remaining listeners from running.
|
|
102
|
+
*/
|
|
103
|
+
export declare function emit<E extends WidgetEventName>(event: E, ...args: EmitArgs<E>): void;
|
|
104
|
+
/** Remove every listener for every event. Used when the widget is destroyed. */
|
|
105
|
+
export declare function clear(): void;
|
|
106
|
+
/** The widget overlay was opened. */
|
|
107
|
+
export declare function emitWidgetOpened(): void;
|
|
108
|
+
/** The widget overlay was closed. */
|
|
109
|
+
export declare function emitWidgetClosed(): void;
|
|
110
|
+
/** A form stage became visible to the user. */
|
|
111
|
+
export declare function emitStageViewed(payload: StageEventData): void;
|
|
112
|
+
/** A form stage was successfully completed. */
|
|
113
|
+
export declare function emitStageCompleted(payload: StageEventData): void;
|
|
114
|
+
/** All stages were completed and rate generation started. */
|
|
115
|
+
export declare function emitFlowCompleted(): void;
|
|
116
|
+
/** The rates screen is being shown. */
|
|
117
|
+
export declare function emitRatesViewed(payload: {
|
|
118
|
+
rateCount: number;
|
|
119
|
+
}): void;
|
|
120
|
+
/** The user navigated back from the rates screen. */
|
|
121
|
+
export declare function emitRatesBack(): void;
|
|
122
|
+
/** Quote submission failed (worker failure, timeout, or repeated network errors). */
|
|
123
|
+
export declare function emitTelemetry(event: string, properties?: Record<string, unknown>): void;
|
|
124
|
+
export declare function emitSubmissionFailed(payload: WidgetEventMap['submissionFailed']): void;
|
|
125
|
+
export {};
|
|
126
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory HAR recorder.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the global `fetch` exactly once and records a bounded, FIFO ring buffer
|
|
5
|
+
* of HAR 1.2 entries for requests to our own API (`baseUrl`) only — never the
|
|
6
|
+
* host page's traffic (the widget is embedded on third-party sites).
|
|
7
|
+
*
|
|
8
|
+
* Recording is best-effort and fire-and-forget: it never blocks, delays, or
|
|
9
|
+
* throws into the application's fetch path. Bodies are read from a clone so the
|
|
10
|
+
* caller's response stays intact. Redaction happens later, at attach time
|
|
11
|
+
* (see ../sentry/reportQuoteFailure.ts -> redactHar), so the buffer holds raw
|
|
12
|
+
* data in memory only and never leaves the browser unredacted.
|
|
13
|
+
*/
|
|
14
|
+
import type { HarLog } from './types';
|
|
15
|
+
interface RecorderOptions {
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
maxEntries?: number;
|
|
18
|
+
maxBodyBytes?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Install the recorder. Idempotent and safe to call when `fetch` is unavailable
|
|
22
|
+
* (e.g. SSR) — returns false in that case and records nothing.
|
|
23
|
+
*/
|
|
24
|
+
export declare function installHarRecorder(options: RecorderOptions): boolean;
|
|
25
|
+
/** Snapshot the current buffer as a HAR 1.2 log. */
|
|
26
|
+
export declare function getHarLog(): HarLog;
|
|
27
|
+
/** Number of entries currently buffered. */
|
|
28
|
+
export declare function harEntryCount(): number;
|
|
29
|
+
/** Test-only: restore the original fetch and clear all recorder state. */
|
|
30
|
+
export declare function __resetHarRecorder(): void;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=recorder.d.ts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal HAR 1.2 type definitions for the fields the widget records.
|
|
3
|
+
* Only the subset we populate is modeled; the shape stays compatible with the
|
|
4
|
+
* full HAR spec so the output opens directly in Chrome DevTools.
|
|
5
|
+
* See: http://www.softwareishard.com/blog/har-12-spec/
|
|
6
|
+
*/
|
|
7
|
+
export interface HarHeader {
|
|
8
|
+
name: string;
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
export interface HarQueryParam {
|
|
12
|
+
name: string;
|
|
13
|
+
value: string;
|
|
14
|
+
}
|
|
15
|
+
export interface HarPostData {
|
|
16
|
+
mimeType: string;
|
|
17
|
+
text: string;
|
|
18
|
+
}
|
|
19
|
+
export interface HarRequest {
|
|
20
|
+
method: string;
|
|
21
|
+
url: string;
|
|
22
|
+
httpVersion: string;
|
|
23
|
+
headers: HarHeader[];
|
|
24
|
+
queryString: HarQueryParam[];
|
|
25
|
+
cookies: never[];
|
|
26
|
+
headersSize: number;
|
|
27
|
+
bodySize: number;
|
|
28
|
+
postData?: HarPostData;
|
|
29
|
+
}
|
|
30
|
+
export interface HarContent {
|
|
31
|
+
size: number;
|
|
32
|
+
mimeType: string;
|
|
33
|
+
text?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface HarResponse {
|
|
36
|
+
status: number;
|
|
37
|
+
statusText: string;
|
|
38
|
+
httpVersion: string;
|
|
39
|
+
headers: HarHeader[];
|
|
40
|
+
cookies: never[];
|
|
41
|
+
content: HarContent;
|
|
42
|
+
redirectURL: string;
|
|
43
|
+
headersSize: number;
|
|
44
|
+
bodySize: number;
|
|
45
|
+
/** Non-spec marker we add when the underlying fetch rejected (network error). */
|
|
46
|
+
_error?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface HarEntry {
|
|
49
|
+
startedDateTime: string;
|
|
50
|
+
time: number;
|
|
51
|
+
request: HarRequest;
|
|
52
|
+
response: HarResponse;
|
|
53
|
+
cache: Record<string, never>;
|
|
54
|
+
timings: {
|
|
55
|
+
send: number;
|
|
56
|
+
wait: number;
|
|
57
|
+
receive: number;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export interface HarLog {
|
|
61
|
+
log: {
|
|
62
|
+
version: '1.2';
|
|
63
|
+
creator: {
|
|
64
|
+
name: string;
|
|
65
|
+
version: string;
|
|
66
|
+
};
|
|
67
|
+
entries: HarEntry[];
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Product } from '@getcredify/credify-insurance-ui-kit/core';
|
|
2
|
+
/** Parses one value; returns undefined for anything unrecognised. */
|
|
3
|
+
export declare function parseProduct(raw: string | null | undefined): Product | undefined;
|
|
4
|
+
/**
|
|
5
|
+
* Reads the product from the host page URL (`?credify_product=auto`) and strips
|
|
6
|
+
* it via history.replaceState, the same way the resume token and test flag are
|
|
7
|
+
* handled — a partner's address bar is theirs, and a link that has been used
|
|
8
|
+
* should not keep re-announcing itself in everything the visitor copies.
|
|
9
|
+
*
|
|
10
|
+
* Persisted to sessionStorage because the stripping means a reload no longer
|
|
11
|
+
* carries the param: without it a refresh three stages in would fall back to
|
|
12
|
+
* the default product while the stored quote is still the one the link asked
|
|
13
|
+
* for. Only `hasProductFromUrl()` is deliberately not restored — see below.
|
|
14
|
+
*
|
|
15
|
+
* Call once at init, before rendering, alongside captureResumeTokenFromUrl().
|
|
16
|
+
*/
|
|
17
|
+
export declare function captureProductFromUrl(): void;
|
|
18
|
+
/** The product a URL asked for, if any. Host `init({ product })` is the fallback. */
|
|
19
|
+
export declare function getUrlProduct(): Product | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Whether this page view arrived carrying the param — the signal to open the
|
|
22
|
+
* widget straight into that flow rather than wait for the host's button.
|
|
23
|
+
*
|
|
24
|
+
* Not restored from sessionStorage on purpose: landing directly is what the
|
|
25
|
+
* link asked for on the visit that carried it. A visitor who closed the modal
|
|
26
|
+
* and then reloaded gets the page, not the modal reopening over it — while
|
|
27
|
+
* `getUrlProduct()` still remembers which flow to resume.
|
|
28
|
+
*/
|
|
29
|
+
export declare function hasProductFromUrl(): boolean;
|
|
30
|
+
//# sourceMappingURL=product.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The widget's view of the emailed resume link (`?credify_rt=<token>`).
|
|
3
|
+
*
|
|
4
|
+
* The token store lives in the kit, deliberately: the widget has to capture
|
|
5
|
+
* before first render (it auto-opens on a resume link, and the param must be
|
|
6
|
+
* off the URL before the host page copies or logs it), but the redemption and
|
|
7
|
+
* the quote it restores belong to the flow. Two stores meant the widget took
|
|
8
|
+
* the token off the URL and the flow then found neither token nor param, so
|
|
9
|
+
* every widget resume link silently started a fresh quote.
|
|
10
|
+
*
|
|
11
|
+
* These wrappers exist only to bind the widget's Sentry reporter to the kit's
|
|
12
|
+
* capture.
|
|
13
|
+
*/
|
|
14
|
+
import { consumeResumeToken, hasResumeToken } from '@getcredify/credify-insurance-ui-kit/api';
|
|
15
|
+
/**
|
|
16
|
+
* Reads the resume token from the host page URL and immediately strips it via
|
|
17
|
+
* history.replaceState. Call once at widget init, before any rendering.
|
|
18
|
+
*/
|
|
19
|
+
export declare function captureResumeTokenFromUrl(): void;
|
|
20
|
+
export { consumeResumeToken, hasResumeToken };
|
|
21
|
+
/**
|
|
22
|
+
* Whether the shell must hold before deciding whether to ask for a product.
|
|
23
|
+
*
|
|
24
|
+
* The lookup that decides is asynchronous — a resume link has to be redeemed,
|
|
25
|
+
* a stored quote has to be read — so without seeding the hold from this, the
|
|
26
|
+
* first frame paints the chooser and swaps it out a moment later. That asks a
|
|
27
|
+
* customer who followed a resume link which product they want, and is the
|
|
28
|
+
* difference between "resuming" and "starting again" as far as they can tell.
|
|
29
|
+
*
|
|
30
|
+
* Both checks are synchronous, so the answer is available before the first
|
|
31
|
+
* paint. A host that answered at init is excluded deliberately: the effect that
|
|
32
|
+
* clears the hold returns early on `product`, so holding would never end.
|
|
33
|
+
*/
|
|
34
|
+
export declare const hasResumableSession: (product?: string) => boolean;
|
|
35
|
+
//# sourceMappingURL=resumeLink.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev-mode detection that survives every build target the widget ships.
|
|
3
|
+
*
|
|
4
|
+
* `import.meta.env.DEV` is Vite-only: it does not exist in the UMD bundle a
|
|
5
|
+
* partner loads from a script tag, nor under Jest. Mirrors the ui-kit's
|
|
6
|
+
* `isDevEnvironment`, which the widget cannot import from `core` without
|
|
7
|
+
* pulling the quote engine into modules that only need a boolean.
|
|
8
|
+
*/
|
|
9
|
+
export declare const isDevEnvironment: () => boolean;
|
|
10
|
+
//# sourceMappingURL=devEnvironment.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser Sentry initialisation for the widget.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the backend init (packages/sentry/src/init.ts): same scrubbing hooks,
|
|
5
|
+
* `sendDefaultPii: false`, idempotent, and a no-op when no DSN is configured
|
|
6
|
+
* (local dev / tests stay silent).
|
|
7
|
+
*
|
|
8
|
+
* Adds three browser-specific pieces:
|
|
9
|
+
* - the HAR recorder, started before anything can fail,
|
|
10
|
+
* - Session Replay, lazy-loaded from the Sentry CDN and recording only on
|
|
11
|
+
* error. Replay captures DOM/console/network-metadata; request/response
|
|
12
|
+
* bodies live in the redacted HAR attachment instead (Replay's envelope
|
|
13
|
+
* bypasses `beforeSend`, so we cannot scrub bodies it would capture), and
|
|
14
|
+
* - noise filtering for scripts the widget does not own, since the widget
|
|
15
|
+
* runs on partner pages and inside in-app browsers that inject their own.
|
|
16
|
+
*/
|
|
17
|
+
export interface WidgetSentryOptions {
|
|
18
|
+
dsn?: string;
|
|
19
|
+
environment?: string;
|
|
20
|
+
release?: string;
|
|
21
|
+
/** Explicitly disable even when a DSN is present. */
|
|
22
|
+
enabled?: boolean;
|
|
23
|
+
tracesSampleRate?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Initialise Sentry for the widget. Returns true when Sentry was activated.
|
|
27
|
+
* Idempotent: subsequent calls are no-ops.
|
|
28
|
+
*/
|
|
29
|
+
export declare function initWidgetSentry(options?: WidgetSentryOptions): boolean;
|
|
30
|
+
export declare function isWidgetSentryInitialized(): boolean;
|
|
31
|
+
/** Test-only: reset the init guard between tests. */
|
|
32
|
+
export declare function __resetWidgetSentry(): void;
|
|
33
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PII scrubber for the browser widget.
|
|
3
|
+
*
|
|
4
|
+
* SOURCE OF TRUTH: this mirrors packages/sentry/src/scrubber.ts (the backend
|
|
5
|
+
* Lambda scrubber). The pattern lists below MUST be kept in sync with that file
|
|
6
|
+
* so frontend and backend redact the same fields. We copy rather than import
|
|
7
|
+
* because that package targets `@sentry/aws-serverless` (Node) and cannot be
|
|
8
|
+
* bundled into the browser widget. A future shared package could dedupe this.
|
|
9
|
+
*
|
|
10
|
+
* Used in two places:
|
|
11
|
+
* - Sentry `beforeSend` / `beforeBreadcrumb` hooks (scrubEvent)
|
|
12
|
+
* - HAR attachment redaction before upload (redactHar)
|
|
13
|
+
*/
|
|
14
|
+
import type { HarLog } from '../har/types';
|
|
15
|
+
export declare function isSensitiveKey(key: string): boolean;
|
|
16
|
+
export declare function scrubString(value: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Recursively redact PII from any JSON-compatible value.
|
|
19
|
+
* - Sensitive keys -> replaced with [REDACTED]
|
|
20
|
+
* - Sensitive value patterns (SSN, VIN, JWT, bearer tokens) -> replaced inline
|
|
21
|
+
* - Cycles, depth limits, and non-plain objects are handled defensively
|
|
22
|
+
*/
|
|
23
|
+
export declare function scrub<T>(input: T, depth?: number, seen?: WeakSet<object>): T;
|
|
24
|
+
export interface ScrubbableEvent {
|
|
25
|
+
request?: {
|
|
26
|
+
data?: unknown;
|
|
27
|
+
cookies?: unknown;
|
|
28
|
+
headers?: Record<string, unknown>;
|
|
29
|
+
};
|
|
30
|
+
extra?: Record<string, unknown>;
|
|
31
|
+
contexts?: Record<string, unknown>;
|
|
32
|
+
tags?: Record<string, unknown>;
|
|
33
|
+
breadcrumbs?: Array<{
|
|
34
|
+
data?: unknown;
|
|
35
|
+
message?: string;
|
|
36
|
+
}>;
|
|
37
|
+
message?: string;
|
|
38
|
+
user?: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Sentry beforeSend / beforeBreadcrumb hook.
|
|
42
|
+
* Mutates the event in place for keys we recognize, returns the event.
|
|
43
|
+
*/
|
|
44
|
+
export declare function scrubEvent<E extends ScrubbableEvent>(event: E): E;
|
|
45
|
+
/**
|
|
46
|
+
* Redact a HAR log before it leaves the browser. Operates on a deep clone so
|
|
47
|
+
* the in-memory recorder buffer is never mutated.
|
|
48
|
+
*/
|
|
49
|
+
export declare function redactHar(har: HarLog): HarLog;
|
|
50
|
+
//# sourceMappingURL=redact.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report a quote failure to Sentry with the redacted network trace attached.
|
|
3
|
+
*
|
|
4
|
+
* Called from the widget's failure sites (Widget.tsx). Captures the exception,
|
|
5
|
+
* tags it for filtering, and attaches a redacted HAR of the widget's API
|
|
6
|
+
* traffic so the failure can be analysed in Chrome DevTools — automating the
|
|
7
|
+
* manual "export a HAR and debug" workflow.
|
|
8
|
+
*
|
|
9
|
+
* No-ops cleanly when Sentry is not initialised, and is wrapped so it can never
|
|
10
|
+
* throw into the application path.
|
|
11
|
+
*/
|
|
12
|
+
export interface QuoteFailureContext {
|
|
13
|
+
/** Which product was being quoted ('Home' | 'Auto' | 'Bundle'). */
|
|
14
|
+
product?: string;
|
|
15
|
+
/** Current stage key (e.g. 'Driver', 'Vehicle'). */
|
|
16
|
+
stage?: string;
|
|
17
|
+
/** Quote id, when known. */
|
|
18
|
+
quoteId?: string;
|
|
19
|
+
/** Where in the flow the failure surfaced (e.g. 'rates_polling', 'consent_submit', 'api_request'). */
|
|
20
|
+
phase?: string;
|
|
21
|
+
/** API endpoint path for transport failures (e.g. '/get-rates'). */
|
|
22
|
+
endpoint?: string;
|
|
23
|
+
/** HTTP status code (0 for network errors). */
|
|
24
|
+
statusCode?: number;
|
|
25
|
+
/** Carrier-side classification of a rating failure (e.g. 'BOLT_VALIDATION'). */
|
|
26
|
+
failureCode?: string | null;
|
|
27
|
+
/** Fallback message when `error` is not an Error instance. */
|
|
28
|
+
message?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function reportQuoteFailure(error: unknown, ctx?: QuoteFailureContext): void;
|
|
31
|
+
//# sourceMappingURL=reportQuoteFailure.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function saveQuoteId(quoteId: string): void;
|
|
2
|
+
export declare function loadQuoteId(): string | null;
|
|
3
|
+
export declare function clearQuoteId(): void;
|
|
4
|
+
export declare function saveAuthToken(token: string): void;
|
|
5
|
+
export declare function loadAuthToken(): string | null;
|
|
6
|
+
export declare function clearAuthToken(): void;
|
|
7
|
+
export declare function clearAllQuoteData(): void;
|
|
8
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bland web-chat integration (live chat with "Sarah", the 24/7 intake agent).
|
|
3
|
+
*
|
|
4
|
+
* Bland exposes no imperative open API: the Messenger renders a launcher button
|
|
5
|
+
* inside a shadow root, and the only way to open it is to click that button. We
|
|
6
|
+
* poll for it and dispatch a synthetic click, matching how the marketing site
|
|
7
|
+
* drives the same widget.
|
|
8
|
+
*
|
|
9
|
+
* Host-first by design. A host page may already run Bland (getcredify.com does),
|
|
10
|
+
* in which case its `blandSettings` and its loaded SDK are the single source of
|
|
11
|
+
* truth: we drive the existing launcher and never write the global, inject a
|
|
12
|
+
* second loader, or tear the session down. The widget only owns Bland on pages
|
|
13
|
+
* that have none — third-party embeds, the standalone app, and the iframe build.
|
|
14
|
+
*/
|
|
15
|
+
export declare const BLAND_LOADER_SRC = "https://widget.bland.ai/loader.js";
|
|
16
|
+
interface BlandSettings {
|
|
17
|
+
widget_id: string;
|
|
18
|
+
request_data?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
declare global {
|
|
21
|
+
interface Window {
|
|
22
|
+
blandSettings?: BlandSettings;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Whether the host page already provides Bland. Checked against all three
|
|
27
|
+
* observable traces because the widget can initialise at any point in the
|
|
28
|
+
* host's own load sequence: the settings global (set before the loader runs),
|
|
29
|
+
* the script tag, and the mounted launcher host.
|
|
30
|
+
*/
|
|
31
|
+
export declare function hostBlandPresent(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Ensure Bland is loading. No-op when the host already owns it — `blandSettings`
|
|
34
|
+
* is assigned only when absent, so a host's agent id and request data always win.
|
|
35
|
+
*/
|
|
36
|
+
export declare function loadBland(widgetId: string, requestData?: Record<string, unknown>): void;
|
|
37
|
+
/**
|
|
38
|
+
* Open the Messenger, loading the SDK first when the widget owns it.
|
|
39
|
+
* Resolves false when the launcher never appears, so callers can fall back.
|
|
40
|
+
*/
|
|
41
|
+
export declare function openBland(widgetId: string, requestData?: Record<string, unknown>): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Tear down only a widget-owned Messenger. Bland ships no shutdown API, so we
|
|
44
|
+
* remove the mounted host; a host page's session is always left untouched.
|
|
45
|
+
*/
|
|
46
|
+
export declare function shutdownBland(): void;
|
|
47
|
+
/** Test seam: reset ownership without touching a host-owned session. */
|
|
48
|
+
export declare function __resetBland(): void;
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=bland.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cobrowse.io integration (agent screen sharing).
|
|
3
|
+
*
|
|
4
|
+
* Privacy-first by default: every form input is redacted, so PII (DOB, license,
|
|
5
|
+
* VIN, SSN, address…) is never transmitted — agents see layout, labels, and
|
|
6
|
+
* validation errors only. The prospect explicitly starts the session and reads
|
|
7
|
+
* the generated 6-digit code to the agent, so sharing is always consented and
|
|
8
|
+
* agent-initiated control still prompts for confirmation.
|
|
9
|
+
*
|
|
10
|
+
* The 6-digit code flow works on the Cobrowse trial tier. Swap it for
|
|
11
|
+
* backend-issued JWT session auth when upgrading to premium — that change is
|
|
12
|
+
* isolated to this module.
|
|
13
|
+
*/
|
|
14
|
+
interface CobrowseGlobal {
|
|
15
|
+
license?: string;
|
|
16
|
+
redactedViews?: string[];
|
|
17
|
+
customData?: Record<string, unknown>;
|
|
18
|
+
confirmSession?: () => Promise<boolean>;
|
|
19
|
+
client?: () => Promise<unknown>;
|
|
20
|
+
start?: (options?: unknown) => void;
|
|
21
|
+
stop?: () => void;
|
|
22
|
+
createSessionCode?: () => Promise<string>;
|
|
23
|
+
}
|
|
24
|
+
declare global {
|
|
25
|
+
interface Window {
|
|
26
|
+
CobrowseIO?: CobrowseGlobal;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Start a cobrowse session and return a 6-digit code for the prospect to share
|
|
31
|
+
* with the agent. Returns null if the SDK is unavailable or codes are disabled.
|
|
32
|
+
*/
|
|
33
|
+
export declare function startCobrowse(license: string): Promise<string | null>;
|
|
34
|
+
/** End any active session and reset (used on widget destroy). */
|
|
35
|
+
export declare function stopCobrowse(): void;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=cobrowse.d.ts.map
|