@yourroad/sdk 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +93 -89
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
[data-yourroad-overlay-root] { all: initial; position: fixed; inset: 0; z-index: ${
|
|
1
|
+
"use strict";var k=Object.defineProperty;var A=(r,t,e)=>t in r?k(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var o=(r,t,e)=>A(r,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S="https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/bootstrap-embed-access";function O(r){if(typeof r!="object"||r===null||Array.isArray(r))throw new Error("Invalid bootstrap response.");const{iframeUrl:t,expiresAt:e}=r;if(typeof t!="string"||t.trim()==="")throw new Error("Invalid bootstrap response.");let s;try{s=new URL(t)}catch{throw new Error("Invalid bootstrap response.")}if(s.protocol!=="http:"&&s.protocol!=="https:")throw new Error("Invalid bootstrap response.");if(typeof e!="string"||e.trim()===""||Number.isNaN(Date.parse(e)))throw new Error("Invalid bootstrap response.");return{iframeUrl:t,expiresAt:e}}async function I(r,t){const e=await fetch(S,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),credentials:"omit",cache:"no-store",signal:t});if(!e.ok)throw new Error("Bootstrap request was unsuccessful.");return O(await e.json())}const y=r=>Object.fromEntries(Object.entries(r??{}).filter(([,t])=>t!==void 0));function m(r,t){const e={...r,...y(t)};for(const s of["vehicle","dealer","page"])t[s]!==void 0&&(e[s]={...r[s],...y(t[s])});return e}const u=r=>m({},r??{}),d=1;function R(r){const t=new URL(r);if(t.protocol!=="https:"&&t.protocol!=="http:")throw new TypeError("The iframe URL must use HTTP(S).");return t.origin}const v=r=>{if(r===null||typeof r!="object")return!1;const t=Object.getPrototypeOf(r);return t===Object.prototype||t===null},j=r=>v(r)?r.source==="yourroad.embed"&&r.version===d&&r.type==="ready"&&r.payload===void 0&&(r.requestId===void 0||typeof r.requestId=="string"):!1,T=r=>v(r)&&Object.keys(r).length===3&&r.source==="yourroad.embed"&&r.version===d&&r.type==="journey_session_restart";class _{constructor(t,e,s,i,a){o(this,"ready",!1);o(this,"started",!1);o(this,"handleMessage",t=>{if(t.origin!==this.trustedRuntimeOrigin)return;const e=this.iframe.contentWindow;if(!(e===null||t.source!==e)){if(this.ready){T(t.data)&&this.onJourneySessionRestart();return}j(t.data)&&(this.ready=!0,this.post({source:"yourroad.sdk",version:d,type:"ack"}),this.post({source:"yourroad.sdk",version:d,type:"context",payload:u(this.getCurrentContext())}),this.sendJourneySession(this.getJourneySessionId()))}});this.iframe=t,this.trustedRuntimeOrigin=e,this.getCurrentContext=s,this.getJourneySessionId=i,this.onJourneySessionRestart=a}start(){this.started||(window.addEventListener("message",this.handleMessage),this.started=!0)}contextUpdated(t){this.ready&&this.post({source:"yourroad.sdk",version:d,type:"context_updated",payload:u(t)})}destroy(){this.started&&window.removeEventListener("message",this.handleMessage),this.started=!1,this.ready=!1}sendJourneySession(t){this.ready&&this.post({source:"yourroad.sdk",version:d,type:"journey_session",payload:{sessionId:t}})}post(t){const e=this.iframe.contentWindow;if(e!==null)try{e.postMessage(t,this.trustedRuntimeOrigin)}catch{}}}class h extends Error{constructor(e,s,i){super(s,i);o(this,"name","YourRoadError");this.code=e}}class N{constructor(){o(this,"listeners",new Map)}on(t,e){const s=this.listeners.get(t)??new Set;return s.add(e),this.listeners.set(t,s),()=>s.delete(e)}emit(t,e){var s;(s=this.listeners.get(t))==null||s.forEach(i=>i(e))}clear(){this.listeners.clear()}}class C{constructor(){o(this,"previous",null)}capture(){this.previous=document.activeElement instanceof HTMLElement?document.activeElement:null}moveTo(t){t.focus()}restore(){var t;(t=this.previous)!=null&&t.isConnected&&this.previous.focus(),this.previous=null}}class L{constructor(){o(this,"saved");o(this,"scrollX",0);o(this,"scrollY",0)}lock(){if(this.saved)return;const t=document.body.style;this.saved={position:t.position,top:t.top,left:t.left,right:t.right,width:t.width,overflow:t.overflow},this.scrollX=window.scrollX,this.scrollY=window.scrollY,Object.assign(t,{position:"fixed",top:`-${this.scrollY}px`,left:`-${this.scrollX}px`,right:"0",width:"100%",overflow:"hidden"})}unlock(){this.saved&&(Object.assign(document.body.style,this.saved),this.saved=void 0,window.scrollTo(this.scrollX,this.scrollY))}}class Y{constructor(t,e){o(this,"element");this.element=document.createElement("iframe"),this.element.dataset.yourroadFrame="",this.element.title="YourRoad pre-approval",this.element.src=t,this.element.addEventListener("error",e,{once:!0})}destroy(){this.element.remove()}}const D=2147483e3,P=`
|
|
2
|
+
[data-yourroad-overlay-root] { all: initial; position: fixed; inset: 0; z-index: ${D}; display: block; font-family: system-ui, sans-serif; color: #111; }
|
|
3
3
|
[data-yourroad-scrim] { all: initial; position: absolute; inset: 0; display: block; background: rgba(0, 0, 0, .55); }
|
|
4
|
-
[data-yourroad-panel] { all: initial; box-sizing: border-box; position: absolute; inset-block: 0; inset-inline-end: 0; display: flex; flex-direction: column; width: min(520px, 92vw); height: 100vh; height: 100dvh; background: #fff; box-shadow: -8px 0 30px rgba(0,0,0,.2); }
|
|
4
|
+
[data-yourroad-panel] { all: initial; box-sizing: border-box; position: absolute; inset-block: 0; inset-inline-end: 0; display: flex; flex-direction: column; width: min(520px, 92vw); height: 100vh; height: 100dvh; padding-block-start: calc(max(12px, env(safe-area-inset-top)) + 56px); overflow: hidden; border-radius: 24px 0 0 24px; background: #fff; box-shadow: -8px 0 30px rgba(0,0,0,.2); }
|
|
5
5
|
[data-yourroad-close] { all: unset; box-sizing: border-box; position: absolute; z-index: 1; inset-block-start: max(12px, env(safe-area-inset-top)); inset-inline-end: max(12px, env(safe-area-inset-right)); width: 44px; height: 44px; display: grid; place-items: center; border-radius: 999px; background: #fff; color: #111; box-shadow: 0 1px 8px rgba(0,0,0,.25); cursor: pointer; font: 28px/1 system-ui, sans-serif; }
|
|
6
6
|
[data-yourroad-close]:focus-visible { outline: 3px solid #1769e0; outline-offset: 2px; }
|
|
7
|
-
[data-yourroad-frame] { all: initial; box-sizing: border-box; display: block;
|
|
8
|
-
@media (max-width: 600px) { [data-yourroad-panel] { width: 100vw; max-width: none; } }
|
|
9
|
-
`;function
|
|
7
|
+
[data-yourroad-frame] { all: initial; box-sizing: border-box; display: block; flex: 1 1 auto; min-height: 0; width: 100%; border: 0; background: #fff; }
|
|
8
|
+
@media (max-width: 600px) { [data-yourroad-panel] { inset-block-start: auto; inset-block-end: 0; inset-inline-end: 0; width: 100vw; max-width: none; height: 92vh; height: 92dvh; border-radius: 24px 24px 0 0; box-shadow: 0 -8px 30px rgba(0,0,0,.2); } }
|
|
9
|
+
`;function B(){const r=document.head.querySelector("style[data-yourroad-sdk]");if(r)return r;const t=document.createElement("style");return t.dataset.yourroadSdk="",t.textContent=P,document.head.append(t),t}class K{constructor(t,e,s){o(this,"root");o(this,"closeButton");o(this,"iframe");o(this,"abort",new AbortController);B(),this.root=document.createElement("div"),this.root.dataset.yourroadOverlayRoot="",this.root.setAttribute("role","dialog"),this.root.setAttribute("aria-modal","true"),this.root.setAttribute("aria-label","YourRoad pre-approval");const i=document.createElement("div");i.dataset.yourroadScrim="";const a=document.createElement("div");a.dataset.yourroadPanel="",this.closeButton=document.createElement("button"),this.closeButton.type="button",this.closeButton.dataset.yourroadClose="",this.closeButton.setAttribute("aria-label","Close YourRoad");const n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("viewBox","0 0 24 24"),n.setAttribute("width","24"),n.setAttribute("height","24"),n.setAttribute("fill","none"),n.setAttribute("stroke","currentColor"),n.setAttribute("stroke-width","2"),n.setAttribute("stroke-linecap","round"),n.setAttribute("aria-hidden","true");const c=document.createElementNS("http://www.w3.org/2000/svg","path");c.setAttribute("d","M6 6l12 12M18 6L6 18"),n.append(c),this.closeButton.append(n),this.iframe=new Y(t,s),a.append(this.closeButton,this.iframe.element),this.root.append(i,a);const l=this.abort.signal;i.addEventListener("click",e,{signal:l}),this.closeButton.addEventListener("click",e,{signal:l}),document.addEventListener("keydown",E=>{E.key==="Escape"&&e()},{signal:l})}mount(){document.body.append(this.root)}destroy(){var t;this.abort.abort(),this.iframe.destroy(),this.root.remove(),document.querySelector("[data-yourroad-overlay-root]")||(t=document.head.querySelector("style[data-yourroad-sdk]"))==null||t.remove()}}const p="yr_journey_session_pre_approval_v1",f=r=>typeof r=="string"&&/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(r);function U(){try{return globalThis.localStorage}catch{return}}function J(r=U()){const t=()=>{try{r==null||r.removeItem(p)}catch{}};return{read(){let e;try{e=(r==null?void 0:r.getItem(p))??null}catch{return}if(e!==null){if(!f(e)){t();return}return e}},write(e){if(f(e))try{r==null||r.setItem(p,e)}catch{}},clear:t}}const M="https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/create-embed-journey-session",q="https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/probe-embed-journey-session",w=r=>{if(r===null||typeof r!="object")return!1;const t=Object.getPrototypeOf(r);return t===Object.prototype||t===null},g=r=>typeof r=="string"&&r.trim()!==""&&!Number.isNaN(Date.parse(r)),x=(r,t)=>({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),credentials:"omit",cache:"no-store",signal:t});async function b(r,t){const e=await fetch(M,x({partnerKey:r,surface:"pre-approval"},t));if(e.status!==201)throw new Error("Journey session creation was unsuccessful.");const s=await e.json();if(!w(s)||!f(s.sessionId)||!g(s.expiresAt))throw new Error("Invalid journey session response.");return s.sessionId}async function F(r,t){const e=await fetch(q,x({partnerKey:r,surface:"pre-approval",sessionId:t})),s=await e.json();if(!w(s))throw new Error("Invalid journey session probe response.");if(e.status===200&&s.status==="resumable"&&s.sessionId===t&&g(s.expiresAt))return{status:"resumable",sessionId:t};if(e.status===410&&s.status==="expired"&&s.code==="SESSION_EXPIRED")return{status:"expired"};if(e.status===404&&s.status==="invalid"&&s.code==="SESSION_INVALID")return{status:"invalid"};throw new Error("Journey session probe was unsuccessful.")}class X{constructor(t,e=J()){o(this,"state",{kind:"cold"});o(this,"restart");this.partnerKey=t,this.marker=e;const s=e.read();if(!s)return;const i=this.probe(s);this.state={kind:"probing",completion:i}}async resolveForOpen(t){if(this.state.kind==="probing"&&await this.state.completion,this.state.kind==="probe_failed")throw new Error("Journey session validity could not be established.");if(this.state.kind==="active"||this.state.kind==="expired")return this.state.sessionId;const e=await b(this.partnerKey,t);return this.marker.write(e),this.state={kind:"active",sessionId:e},e}restartExpired(t){if(this.state.kind!=="expired")return;if(this.restart)return this.restart;const e=b(this.partnerKey,t).then(s=>(this.marker.write(s),this.state={kind:"active",sessionId:s},s)).finally(()=>{this.restart===e&&(this.restart=void 0)});return this.restart=e,e}async probe(t){try{const e=await F(this.partnerKey,t);e.status==="resumable"?this.state={kind:"active",sessionId:t}:e.status==="expired"?(this.marker.clear(),this.state={kind:"expired",sessionId:t}):(this.marker.clear(),this.state={kind:"cold"})}catch{this.state={kind:"probe_failed"}}}}class z{constructor(t){o(this,"events",new N);o(this,"scroll",new L);o(this,"focus",new C);o(this,"overlay");o(this,"bridge");o(this,"context",{});o(this,"destroyed",!1);o(this,"opening");o(this,"bootstrapAbort");o(this,"restartAbort");o(this,"session");this.config=t,this.session=new X(t.partnerKey)}async open(t){if(this.assertUsable(),!t||t.surface!=="pre-approval")throw this.fail("INVALID_SURFACE",'The only supported surface is "pre-approval".');if(this.overlay)return;if(this.opening)return this.opening;this.context=u(t.context);const e=new AbortController;this.bootstrapAbort=e;const s=this.performOpen(t.surface,e);return this.opening=s,s}updateContext(t){var e;this.assertUsable(),this.context=m(this.context,t),(e=this.bridge)==null||e.contextUpdated(this.context)}close(){var t,e;this.assertUsable(),this.bootstrapAbort&&(this.bootstrapAbort.abort(),this.bootstrapAbort=void 0,this.opening=void 0),(t=this.restartAbort)==null||t.abort(),this.restartAbort=void 0,this.overlay&&((e=this.bridge)==null||e.destroy(),this.bridge=void 0,this.overlay.destroy(),this.overlay=void 0,this.scroll.unlock(),this.focus.restore(),this.events.emit("closed",void 0))}on(t,e){return this.assertUsable(),this.events.on(t,e)}destroy(){this.destroyed||(this.close(),this.events.clear(),this.context={},this.destroyed=!0)}async performOpen(t,e){var s,i;try{const[a,n]=await Promise.all([I({partnerKey:this.config.partnerKey,surface:t},e.signal),this.session.resolveForOpen(e.signal)]),{iframeUrl:c}=a;if(e.signal.aborted||this.destroyed||this.bootstrapAbort!==e)return;this.focus.capture();try{this.overlay=new K(c,()=>this.close(),()=>this.fail("IFRAME_LOAD_FAILED","The embedded experience failed to load.")),this.bridge=new _(this.overlay.iframe.element,R(c),()=>u(this.context),()=>n,()=>this.restartExpiredSession(this.bridge)),this.bridge.start(),this.overlay.mount(),this.scroll.lock(),this.focus.moveTo(this.overlay.closeButton),this.events.emit("opened",void 0)}catch(l){throw(s=this.bridge)==null||s.destroy(),this.bridge=void 0,(i=this.overlay)==null||i.destroy(),this.overlay=void 0,this.scroll.unlock(),this.focus.restore(),this.fail("OVERLAY_CREATION_FAILED","The YourRoad overlay could not be created.",l)}}catch(a){if(e.signal.aborted)return;throw a instanceof h?a:this.fail("BOOTSTRAP_FAILED","The YourRoad experience could not be started securely.",a)}finally{this.bootstrapAbort===e&&(this.bootstrapAbort=void 0,this.opening=void 0)}}restartExpiredSession(t){if(this.destroyed||t===void 0||t!==this.bridge||this.restartAbort)return;const e=new AbortController;this.restartAbort=e;const s=this.session.restartExpired(e.signal);if(!s){this.restartAbort=void 0;return}s.then(i=>{!this.destroyed&&!e.signal.aborted&&this.bridge===t&&t.sendJourneySession(i)}).catch(()=>{}).finally(()=>{this.restartAbort===e&&(this.restartAbort=void 0)})}assertUsable(){if(this.destroyed)throw new h("DESTROYED","This YourRoad SDK instance has been destroyed.")}fail(t,e,s){const i=new h(t,e,s===void 0?void 0:{cause:s});return this.events.emit("error",i),i}}function V(r){return new z(r)}class ${static init(t){if(!t||typeof t.partnerKey!="string"||t.partnerKey.trim()==="")throw new h("INVALID_INITIALISATION","partnerKey must be a non-empty string.");return V({partnerKey:t.partnerKey})}}exports.YourRoad=$;exports.YourRoadError=h;
|
|
10
10
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/bootstrap/bootstrapClient.ts","../src/context/mergeContext.ts","../src/bridge/protocol.ts","../src/bridge/BridgeController.ts","../src/errors/YourRoadError.ts","../src/events/EventEmitter.ts","../src/lifecycle/focus.ts","../src/lifecycle/scrollLock.ts","../src/iframe/IframeController.ts","../src/overlay/styles.ts","../src/overlay/OverlayController.ts","../src/session/sessionMarker.ts","../src/session/sessionClient.ts","../src/session/SessionController.ts","../src/client/YourRoadClient.ts","../src/index.ts"],"sourcesContent":["import type { YourRoadSurface } from '../config/types';\n\nconst BOOTSTRAP_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/bootstrap-embed-access';\n\ninterface BootstrapRequest {\n partnerKey: string;\n surface: YourRoadSurface;\n}\n\nexport interface BootstrapResult {\n iframeUrl: string;\n expiresAt: string;\n}\n\nfunction validateResponse(value: unknown): BootstrapResult {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('Invalid bootstrap response.');\n const { iframeUrl, expiresAt } = value as Record<string, unknown>;\n if (typeof iframeUrl !== 'string' || iframeUrl.trim() === '') throw new Error('Invalid bootstrap response.');\n let parsedUrl: URL;\n try { parsedUrl = new URL(iframeUrl); } catch { throw new Error('Invalid bootstrap response.'); }\n if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') throw new Error('Invalid bootstrap response.');\n if (typeof expiresAt !== 'string' || expiresAt.trim() === '' || Number.isNaN(Date.parse(expiresAt))) {\n throw new Error('Invalid bootstrap response.');\n }\n return { iframeUrl, expiresAt };\n}\n\nexport async function requestBootstrap(request: BootstrapRequest, signal: AbortSignal): Promise<BootstrapResult> {\n const response = await fetch(BOOTSTRAP_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n credentials: 'omit',\n cache: 'no-store',\n signal,\n });\n if (!response.ok) throw new Error('Bootstrap request was unsuccessful.');\n return validateResponse(await response.json());\n}\n","import type { YourRoadContext, YourRoadContextUpdate } from './types';\n\nconst defined = <T extends object>(value: T | undefined): Partial<T> =>\n Object.fromEntries(Object.entries(value ?? {}).filter(([, item]) => item !== undefined)) as Partial<T>;\n\n/** Merges known context sections. Explicit `undefined` values are ignored. */\nexport function mergeContext(current: YourRoadContext, update: YourRoadContextUpdate): YourRoadContext {\n const next: YourRoadContext = { ...current, ...defined(update) };\n for (const key of ['vehicle', 'dealer', 'page'] as const) {\n if (update[key] !== undefined) next[key] = { ...current[key], ...defined(update[key]) };\n }\n return next;\n}\n\nexport const copyContext = (context?: YourRoadContext): YourRoadContext => mergeContext({}, context ?? {});\n","import type { YourRoadContext } from '../context/types';\n\nexport const BRIDGE_VERSION = 1 as const;\n\nexport type BridgeMessage<T = unknown> = {\n source: 'yourroad.sdk' | 'yourroad.embed';\n version: typeof BRIDGE_VERSION;\n type: string;\n requestId?: string;\n payload?: T;\n};\n\nexport type SdkBridgeMessage =\n | BridgeMessage & { source: 'yourroad.sdk'; type: 'ack' }\n | BridgeMessage<YourRoadContext> & { source: 'yourroad.sdk'; type: 'context' | 'context_updated'; payload: YourRoadContext }\n | BridgeMessage<{ sessionId: string }> & { source: 'yourroad.sdk'; type: 'journey_session'; payload: { sessionId: string } };\n","import { copyContext } from '../context/mergeContext';\nimport type { YourRoadContext } from '../context/types';\nimport { BRIDGE_VERSION, type SdkBridgeMessage } from './protocol';\n\nexport function runtimeOriginFromIframeUrl(iframeUrl: string): string {\n const url = new URL(iframeUrl);\n if (url.protocol !== 'https:' && url.protocol !== 'http:') throw new TypeError('The iframe URL must use HTTP(S).');\n return url.origin;\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst isReadyMessage = (value: unknown): boolean => {\n if (!isPlainObject(value)) return false;\n return value.source === 'yourroad.embed'\n && value.version === BRIDGE_VERSION\n && value.type === 'ready'\n && value.payload === undefined\n && (value.requestId === undefined || typeof value.requestId === 'string');\n};\n\nconst isRestartMessage = (value: unknown): boolean => isPlainObject(value)\n && Object.keys(value).length === 3\n && value.source === 'yourroad.embed'\n && value.version === BRIDGE_VERSION\n && value.type === 'journey_session_restart';\n\nexport class BridgeController {\n private ready = false;\n private started = false;\n\n constructor(\n private readonly iframe: HTMLIFrameElement,\n private readonly trustedRuntimeOrigin: string,\n private readonly getCurrentContext: () => YourRoadContext,\n private readonly getJourneySessionId: () => string,\n private readonly onJourneySessionRestart: () => void,\n ) {}\n\n start(): void {\n if (this.started) return;\n window.addEventListener('message', this.handleMessage);\n this.started = true;\n }\n\n contextUpdated(currentContext: YourRoadContext): void {\n if (!this.ready) return;\n this.post({\n source: 'yourroad.sdk',\n version: BRIDGE_VERSION,\n type: 'context_updated',\n payload: copyContext(currentContext),\n });\n }\n\n destroy(): void {\n if (this.started) window.removeEventListener('message', this.handleMessage);\n this.started = false;\n this.ready = false;\n }\n\n private readonly handleMessage = (event: MessageEvent): void => {\n if (event.origin !== this.trustedRuntimeOrigin) return;\n const iframeWindow = this.iframe.contentWindow;\n if (iframeWindow === null || event.source !== iframeWindow) return;\n if (this.ready) {\n if (isRestartMessage(event.data)) this.onJourneySessionRestart();\n return;\n }\n if (!isReadyMessage(event.data)) return;\n this.ready = true;\n this.post({ source: 'yourroad.sdk', version: BRIDGE_VERSION, type: 'ack' });\n this.post({\n source: 'yourroad.sdk',\n version: BRIDGE_VERSION,\n type: 'context',\n payload: copyContext(this.getCurrentContext()),\n });\n this.sendJourneySession(this.getJourneySessionId());\n };\n\n sendJourneySession(sessionId: string): void {\n if (!this.ready) return;\n this.post({ source: 'yourroad.sdk', version: BRIDGE_VERSION, type: 'journey_session', payload: { sessionId } });\n }\n\n private post(message: SdkBridgeMessage): void {\n const iframeWindow = this.iframe.contentWindow;\n if (iframeWindow === null) return;\n try {\n iframeWindow.postMessage(message, this.trustedRuntimeOrigin);\n } catch {\n // The iframe may be removed concurrently; bridge delivery is best-effort.\n }\n }\n}\n","export type YourRoadErrorCode = 'INVALID_INITIALISATION' | 'INVALID_SURFACE' | 'DESTROYED' | 'BOOTSTRAP_FAILED' | 'OVERLAY_CREATION_FAILED' | 'IFRAME_LOAD_FAILED';\n\nexport class YourRoadError extends Error {\n readonly name = 'YourRoadError';\n constructor(public readonly code: YourRoadErrorCode, message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n","export type Handler<T> = (payload: T) => void;\n\nexport class EventEmitter<Events extends object> {\n private listeners = new Map<keyof Events, Set<Handler<never>>>();\n\n on<K extends keyof Events>(event: K, handler: Handler<Events[K]>): () => void {\n const handlers = this.listeners.get(event) ?? new Set();\n handlers.add(handler as Handler<never>);\n this.listeners.set(event, handlers);\n return () => handlers.delete(handler as Handler<never>);\n }\n\n emit<K extends keyof Events>(event: K, payload: Events[K]): void {\n this.listeners.get(event)?.forEach((handler) => handler(payload as never));\n }\n\n clear(): void { this.listeners.clear(); }\n}\n","export class FocusLifecycle {\n private previous: HTMLElement | null = null;\n capture(): void { this.previous = document.activeElement instanceof HTMLElement ? document.activeElement : null; }\n moveTo(element: HTMLElement): void { element.focus(); }\n restore(): void {\n if (this.previous?.isConnected) this.previous.focus();\n this.previous = null;\n }\n}\n","interface SavedStyles { position: string; top: string; left: string; right: string; width: string; overflow: string }\n\nexport class ScrollLock {\n private saved?: SavedStyles;\n private scrollX = 0;\n private scrollY = 0;\n\n lock(): void {\n if (this.saved) return;\n const style = document.body.style;\n this.saved = { position: style.position, top: style.top, left: style.left, right: style.right, width: style.width, overflow: style.overflow };\n this.scrollX = window.scrollX;\n this.scrollY = window.scrollY;\n Object.assign(style, { position: 'fixed', top: `-${this.scrollY}px`, left: `-${this.scrollX}px`, right: '0', width: '100%', overflow: 'hidden' });\n }\n\n unlock(): void {\n if (!this.saved) return;\n Object.assign(document.body.style, this.saved);\n this.saved = undefined;\n window.scrollTo(this.scrollX, this.scrollY);\n }\n}\n","export class IframeController {\n readonly element: HTMLIFrameElement;\n constructor(source: string, onError: () => void) {\n this.element = document.createElement('iframe');\n this.element.dataset.yourroadFrame = '';\n this.element.title = 'YourRoad pre-approval';\n this.element.src = source;\n this.element.addEventListener('error', onError, { once: true });\n }\n destroy(): void { this.element.remove(); }\n}\n","export const SDK_Z_INDEX = 2147483000;\n\nexport const SDK_STYLES = `\n[data-yourroad-overlay-root] { all: initial; position: fixed; inset: 0; z-index: ${SDK_Z_INDEX}; display: block; font-family: system-ui, sans-serif; color: #111; }\n[data-yourroad-scrim] { all: initial; position: absolute; inset: 0; display: block; background: rgba(0, 0, 0, .55); }\n[data-yourroad-panel] { all: initial; box-sizing: border-box; position: absolute; inset-block: 0; inset-inline-end: 0; display: flex; flex-direction: column; width: min(520px, 92vw); height: 100vh; height: 100dvh; background: #fff; box-shadow: -8px 0 30px rgba(0,0,0,.2); }\n[data-yourroad-close] { all: unset; box-sizing: border-box; position: absolute; z-index: 1; inset-block-start: max(12px, env(safe-area-inset-top)); inset-inline-end: max(12px, env(safe-area-inset-right)); width: 44px; height: 44px; display: grid; place-items: center; border-radius: 999px; background: #fff; color: #111; box-shadow: 0 1px 8px rgba(0,0,0,.25); cursor: pointer; font: 28px/1 system-ui, sans-serif; }\n[data-yourroad-close]:focus-visible { outline: 3px solid #1769e0; outline-offset: 2px; }\n[data-yourroad-frame] { all: initial; box-sizing: border-box; display: block; width: 100%; height: 100%; border: 0; background: #fff; }\n@media (max-width: 600px) { [data-yourroad-panel] { width: 100vw; max-width: none; } }\n`;\n\nexport function ensureStyles(): HTMLStyleElement {\n const existing = document.head.querySelector<HTMLStyleElement>('style[data-yourroad-sdk]');\n if (existing) return existing;\n const style = document.createElement('style');\n style.dataset.yourroadSdk = '';\n style.textContent = SDK_STYLES;\n document.head.append(style);\n return style;\n}\n","import { IframeController } from '../iframe/IframeController';\nimport { ensureStyles } from './styles';\n\nexport class OverlayController {\n readonly root: HTMLDivElement;\n readonly closeButton: HTMLButtonElement;\n readonly iframe: IframeController;\n private readonly abort = new AbortController();\n\n constructor(source: string, onClose: () => void, onFrameError: () => void) {\n ensureStyles();\n this.root = document.createElement('div');\n this.root.dataset.yourroadOverlayRoot = '';\n this.root.setAttribute('role', 'dialog');\n this.root.setAttribute('aria-modal', 'true');\n this.root.setAttribute('aria-label', 'YourRoad pre-approval');\n const scrim = document.createElement('div');\n scrim.dataset.yourroadScrim = '';\n const panel = document.createElement('div');\n panel.dataset.yourroadPanel = '';\n this.closeButton = document.createElement('button');\n this.closeButton.type = 'button';\n this.closeButton.dataset.yourroadClose = '';\n this.closeButton.setAttribute('aria-label', 'Close YourRoad');\n this.closeButton.textContent = '×';\n this.iframe = new IframeController(source, onFrameError);\n panel.append(this.closeButton, this.iframe.element);\n this.root.append(scrim, panel);\n const signal = this.abort.signal;\n scrim.addEventListener('click', onClose, { signal });\n this.closeButton.addEventListener('click', onClose, { signal });\n document.addEventListener('keydown', (event) => { if (event.key === 'Escape') onClose(); }, { signal });\n }\n\n mount(): void { document.body.append(this.root); }\n destroy(): void {\n this.abort.abort();\n this.iframe.destroy();\n this.root.remove();\n if (!document.querySelector('[data-yourroad-overlay-root]')) {\n document.head.querySelector('style[data-yourroad-sdk]')?.remove();\n }\n }\n}\n","export const JOURNEY_SESSION_MARKER_KEY = 'yr_journey_session_pre_approval_v1';\n\nexport const isUuid = (value: unknown): value is string =>\n typeof value === 'string'\n && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);\n\nexport interface SessionMarker {\n read(): string | undefined;\n write(sessionId: string): void;\n clear(): void;\n}\n\ntype MarkerStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>;\n\nfunction resolveStorage(): MarkerStorage | undefined {\n try { return globalThis.localStorage; } catch { return undefined; }\n}\n\nexport function createSessionMarker(storage: MarkerStorage | undefined = resolveStorage()): SessionMarker {\n const clear = (): void => {\n try { storage?.removeItem(JOURNEY_SESSION_MARKER_KEY); } catch { /* Storage is optional. */ }\n };\n return {\n read() {\n let value: string | null;\n try { value = storage?.getItem(JOURNEY_SESSION_MARKER_KEY) ?? null; } catch { return undefined; }\n if (value === null) return undefined;\n if (!isUuid(value)) { clear(); return undefined; }\n return value;\n },\n write(sessionId) {\n if (!isUuid(sessionId)) return;\n try { storage?.setItem(JOURNEY_SESSION_MARKER_KEY, sessionId); } catch { /* Keep the in-memory session usable. */ }\n },\n clear,\n };\n}\n","import { isUuid } from './sessionMarker';\n\nconst CREATE_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/create-embed-journey-session';\nconst PROBE_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/probe-embed-journey-session';\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\nconst isDate = (value: unknown): value is string => typeof value === 'string' && value.trim() !== '' && !Number.isNaN(Date.parse(value));\nconst options = (body: object, signal?: AbortSignal): RequestInit => ({\n method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),\n credentials: 'omit', cache: 'no-store', signal,\n});\n\nexport async function createJourneySession(partnerKey: string, signal?: AbortSignal): Promise<string> {\n const response = await fetch(CREATE_ENDPOINT, options({ partnerKey, surface: 'pre-approval' }, signal));\n if (response.status !== 201) throw new Error('Journey session creation was unsuccessful.');\n const value: unknown = await response.json();\n if (!isPlainObject(value) || !isUuid(value.sessionId) || !isDate(value.expiresAt)) throw new Error('Invalid journey session response.');\n return value.sessionId;\n}\n\nexport type ProbeResult = { status: 'resumable'; sessionId: string } | { status: 'expired' } | { status: 'invalid' };\n\nexport async function probeJourneySession(partnerKey: string, sessionId: string): Promise<ProbeResult> {\n const response = await fetch(PROBE_ENDPOINT, options({ partnerKey, surface: 'pre-approval', sessionId }));\n const value: unknown = await response.json();\n if (!isPlainObject(value)) throw new Error('Invalid journey session probe response.');\n if (response.status === 200 && value.status === 'resumable' && value.sessionId === sessionId && isDate(value.expiresAt)) {\n return { status: 'resumable', sessionId };\n }\n if (response.status === 410 && value.status === 'expired' && value.code === 'SESSION_EXPIRED') return { status: 'expired' };\n if (response.status === 404 && value.status === 'invalid' && value.code === 'SESSION_INVALID') return { status: 'invalid' };\n throw new Error('Journey session probe was unsuccessful.');\n}\n","import { createJourneySession, probeJourneySession } from './sessionClient';\nimport { createSessionMarker, type SessionMarker } from './sessionMarker';\n\ntype State =\n | { kind: 'cold' }\n | { kind: 'probing'; completion: Promise<void> }\n | { kind: 'active'; sessionId: string }\n | { kind: 'expired'; sessionId: string }\n | { kind: 'probe_failed' };\n\nexport class SessionController {\n private state: State = { kind: 'cold' };\n private restart?: Promise<string>;\n\n constructor(private readonly partnerKey: string, private readonly marker: SessionMarker = createSessionMarker()) {\n const sessionId = marker.read();\n if (!sessionId) return;\n const completion = this.probe(sessionId);\n this.state = { kind: 'probing', completion };\n }\n\n async resolveForOpen(signal: AbortSignal): Promise<string> {\n if (this.state.kind === 'probing') await this.state.completion;\n if (this.state.kind === 'probe_failed') throw new Error('Journey session validity could not be established.');\n if (this.state.kind === 'active' || this.state.kind === 'expired') return this.state.sessionId;\n const sessionId = await createJourneySession(this.partnerKey, signal);\n this.marker.write(sessionId);\n this.state = { kind: 'active', sessionId };\n return sessionId;\n }\n\n restartExpired(signal: AbortSignal): Promise<string> | undefined {\n if (this.state.kind !== 'expired') return undefined;\n if (this.restart) return this.restart;\n const operation = createJourneySession(this.partnerKey, signal).then((sessionId) => {\n this.marker.write(sessionId);\n this.state = { kind: 'active', sessionId };\n return sessionId;\n }).finally(() => { if (this.restart === operation) this.restart = undefined; });\n this.restart = operation;\n return operation;\n }\n\n private async probe(sessionId: string): Promise<void> {\n try {\n const result = await probeJourneySession(this.partnerKey, sessionId);\n if (result.status === 'resumable') this.state = { kind: 'active', sessionId };\n else if (result.status === 'expired') { this.marker.clear(); this.state = { kind: 'expired', sessionId }; }\n else { this.marker.clear(); this.state = { kind: 'cold' }; }\n } catch { this.state = { kind: 'probe_failed' }; }\n }\n}\n","import type { YourRoadInitConfig, YourRoadSurface } from '../config/types';\nimport { requestBootstrap } from '../bootstrap/bootstrapClient';\nimport { BridgeController, runtimeOriginFromIframeUrl } from '../bridge/BridgeController';\nimport { copyContext, mergeContext } from '../context/mergeContext';\nimport type { YourRoadContext, YourRoadContextUpdate } from '../context/types';\nimport { YourRoadError } from '../errors/YourRoadError';\nimport { EventEmitter } from '../events/EventEmitter';\nimport { FocusLifecycle } from '../lifecycle/focus';\nimport { ScrollLock } from '../lifecycle/scrollLock';\nimport { OverlayController } from '../overlay/OverlayController';\nimport { SessionController } from '../session/SessionController';\n\nexport interface OpenOptions { surface: YourRoadSurface; context?: YourRoadContext }\nexport interface YourRoadEvents { opened: undefined; closed: undefined; error: YourRoadError }\n\nexport interface YourRoadClient {\n open(options: OpenOptions): Promise<void>;\n updateContext(update: YourRoadContextUpdate): void;\n close(): void;\n on<K extends keyof YourRoadEvents>(event: K, handler: (payload: YourRoadEvents[K]) => void): () => void;\n destroy(): void;\n}\n\nclass YourRoadClientImpl implements YourRoadClient {\n private readonly events = new EventEmitter<YourRoadEvents>();\n private readonly scroll = new ScrollLock();\n private readonly focus = new FocusLifecycle();\n private overlay?: OverlayController;\n private bridge?: BridgeController;\n private context: YourRoadContext = {};\n private destroyed = false;\n private opening?: Promise<void>;\n private bootstrapAbort?: AbortController;\n private restartAbort?: AbortController;\n private readonly session: SessionController;\n\n constructor(private readonly config: Readonly<YourRoadInitConfig>) {\n this.session = new SessionController(config.partnerKey);\n }\n\n async open(options: OpenOptions): Promise<void> {\n this.assertUsable();\n if (!options || options.surface !== 'pre-approval') throw this.fail('INVALID_SURFACE', 'The only supported surface is \"pre-approval\".');\n if (this.overlay) return;\n if (this.opening) return this.opening;\n this.context = copyContext(options.context);\n const abort = new AbortController();\n this.bootstrapAbort = abort;\n const operation = this.performOpen(options.surface, abort);\n this.opening = operation;\n return operation;\n }\n\n updateContext(update: YourRoadContextUpdate): void {\n this.assertUsable();\n this.context = mergeContext(this.context, update);\n this.bridge?.contextUpdated(this.context);\n }\n\n close(): void {\n this.assertUsable();\n if (this.bootstrapAbort) {\n this.bootstrapAbort.abort();\n this.bootstrapAbort = undefined;\n this.opening = undefined;\n }\n this.restartAbort?.abort();\n this.restartAbort = undefined;\n if (!this.overlay) return;\n this.bridge?.destroy();\n this.bridge = undefined;\n this.overlay.destroy();\n this.overlay = undefined;\n this.scroll.unlock();\n this.focus.restore();\n this.events.emit('closed', undefined);\n }\n\n on<K extends keyof YourRoadEvents>(event: K, handler: (payload: YourRoadEvents[K]) => void): () => void {\n this.assertUsable();\n return this.events.on(event, handler);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.close();\n this.events.clear();\n this.context = {};\n this.destroyed = true;\n }\n\n private async performOpen(surface: YourRoadSurface, abort: AbortController): Promise<void> {\n try {\n const [bootstrap, sessionId] = await Promise.all([\n requestBootstrap({ partnerKey: this.config.partnerKey, surface }, abort.signal),\n this.session.resolveForOpen(abort.signal),\n ]);\n const { iframeUrl } = bootstrap;\n if (abort.signal.aborted || this.destroyed || this.bootstrapAbort !== abort) return;\n this.focus.capture();\n try {\n this.overlay = new OverlayController(iframeUrl, () => this.close(), () => this.fail('IFRAME_LOAD_FAILED', 'The embedded experience failed to load.'));\n this.bridge = new BridgeController(\n this.overlay.iframe.element,\n runtimeOriginFromIframeUrl(iframeUrl),\n () => copyContext(this.context),\n () => sessionId,\n () => this.restartExpiredSession(this.bridge),\n );\n this.bridge.start();\n this.overlay.mount();\n this.scroll.lock();\n this.focus.moveTo(this.overlay.closeButton);\n this.events.emit('opened', undefined);\n } catch (cause) {\n this.bridge?.destroy();\n this.bridge = undefined;\n this.overlay?.destroy();\n this.overlay = undefined;\n this.scroll.unlock();\n this.focus.restore();\n throw this.fail('OVERLAY_CREATION_FAILED', 'The YourRoad overlay could not be created.', cause);\n }\n } catch (cause) {\n if (abort.signal.aborted) return;\n if (cause instanceof YourRoadError) throw cause;\n throw this.fail('BOOTSTRAP_FAILED', 'The YourRoad experience could not be started securely.', cause);\n } finally {\n if (this.bootstrapAbort === abort) {\n this.bootstrapAbort = undefined;\n this.opening = undefined;\n }\n }\n }\n\n private restartExpiredSession(bridge: BridgeController | undefined): void {\n if (this.destroyed || bridge === undefined || bridge !== this.bridge || this.restartAbort) return;\n const restartAbort = new AbortController();\n this.restartAbort = restartAbort;\n const operation = this.session.restartExpired(restartAbort.signal);\n if (!operation) { this.restartAbort = undefined; return; }\n void operation.then((sessionId) => {\n if (!this.destroyed && !restartAbort.signal.aborted && this.bridge === bridge) bridge.sendJourneySession(sessionId);\n }).catch(() => { /* The runtime may offer a later explicit retry. */ }).finally(() => {\n if (this.restartAbort === restartAbort) this.restartAbort = undefined;\n });\n }\n\n private assertUsable(): void { if (this.destroyed) throw new YourRoadError('DESTROYED', 'This YourRoad SDK instance has been destroyed.'); }\n private fail(code: ConstructorParameters<typeof YourRoadError>[0], message: string, cause?: unknown): YourRoadError {\n const error = new YourRoadError(code, message, cause === undefined ? undefined : { cause });\n this.events.emit('error', error);\n return error;\n }\n}\n\nexport function createYourRoadClient(config: Readonly<YourRoadInitConfig>): YourRoadClient {\n return new YourRoadClientImpl(config);\n}\n","import { createYourRoadClient, type YourRoadClient } from './client/YourRoadClient';\nimport type { YourRoadInitConfig } from './config/types';\nimport { YourRoadError } from './errors/YourRoadError';\n\nexport type { OpenOptions, YourRoadClient, YourRoadEvents } from './client/YourRoadClient';\nexport type { YourRoadInitConfig, YourRoadSurface } from './config/types';\nexport type { DealerContext, PageContext, VehicleContext, YourRoadContext, YourRoadContextUpdate } from './context/types';\nexport { YourRoadError };\n\nexport class YourRoad {\n static init(config: YourRoadInitConfig): YourRoadClient {\n if (!config || typeof config.partnerKey !== 'string' || config.partnerKey.trim() === '') {\n throw new YourRoadError('INVALID_INITIALISATION', 'partnerKey must be a non-empty string.');\n }\n return createYourRoadClient({ partnerKey: config.partnerKey });\n }\n}\n"],"names":["BOOTSTRAP_ENDPOINT","validateResponse","value","iframeUrl","expiresAt","parsedUrl","requestBootstrap","request","signal","response","defined","item","mergeContext","current","update","next","key","copyContext","context","BRIDGE_VERSION","runtimeOriginFromIframeUrl","url","isPlainObject","prototype","isReadyMessage","isRestartMessage","BridgeController","iframe","trustedRuntimeOrigin","getCurrentContext","getJourneySessionId","onJourneySessionRestart","__publicField","event","iframeWindow","currentContext","sessionId","message","YourRoadError","code","options","EventEmitter","handler","handlers","payload","_a","FocusLifecycle","element","ScrollLock","style","IframeController","source","onError","SDK_Z_INDEX","SDK_STYLES","ensureStyles","existing","OverlayController","onClose","onFrameError","scrim","panel","JOURNEY_SESSION_MARKER_KEY","isUuid","resolveStorage","createSessionMarker","storage","clear","CREATE_ENDPOINT","PROBE_ENDPOINT","isDate","body","createJourneySession","partnerKey","probeJourneySession","SessionController","marker","completion","operation","result","YourRoadClientImpl","config","abort","_b","surface","bootstrap","cause","bridge","restartAbort","error","createYourRoadClient","YourRoad"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/bootstrap/bootstrapClient.ts","../src/context/mergeContext.ts","../src/bridge/protocol.ts","../src/bridge/BridgeController.ts","../src/errors/YourRoadError.ts","../src/events/EventEmitter.ts","../src/lifecycle/focus.ts","../src/lifecycle/scrollLock.ts","../src/iframe/IframeController.ts","../src/overlay/styles.ts","../src/overlay/OverlayController.ts","../src/session/sessionMarker.ts","../src/session/sessionClient.ts","../src/session/SessionController.ts","../src/client/YourRoadClient.ts","../src/index.ts"],"sourcesContent":["import type { YourRoadSurface } from '../config/types';\n\nconst BOOTSTRAP_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/bootstrap-embed-access';\n\ninterface BootstrapRequest {\n partnerKey: string;\n surface: YourRoadSurface;\n}\n\nexport interface BootstrapResult {\n iframeUrl: string;\n expiresAt: string;\n}\n\nfunction validateResponse(value: unknown): BootstrapResult {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('Invalid bootstrap response.');\n const { iframeUrl, expiresAt } = value as Record<string, unknown>;\n if (typeof iframeUrl !== 'string' || iframeUrl.trim() === '') throw new Error('Invalid bootstrap response.');\n let parsedUrl: URL;\n try { parsedUrl = new URL(iframeUrl); } catch { throw new Error('Invalid bootstrap response.'); }\n if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') throw new Error('Invalid bootstrap response.');\n if (typeof expiresAt !== 'string' || expiresAt.trim() === '' || Number.isNaN(Date.parse(expiresAt))) {\n throw new Error('Invalid bootstrap response.');\n }\n return { iframeUrl, expiresAt };\n}\n\nexport async function requestBootstrap(request: BootstrapRequest, signal: AbortSignal): Promise<BootstrapResult> {\n const response = await fetch(BOOTSTRAP_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n credentials: 'omit',\n cache: 'no-store',\n signal,\n });\n if (!response.ok) throw new Error('Bootstrap request was unsuccessful.');\n return validateResponse(await response.json());\n}\n","import type { YourRoadContext, YourRoadContextUpdate } from './types';\n\nconst defined = <T extends object>(value: T | undefined): Partial<T> =>\n Object.fromEntries(Object.entries(value ?? {}).filter(([, item]) => item !== undefined)) as Partial<T>;\n\n/** Merges known context sections. Explicit `undefined` values are ignored. */\nexport function mergeContext(current: YourRoadContext, update: YourRoadContextUpdate): YourRoadContext {\n const next: YourRoadContext = { ...current, ...defined(update) };\n for (const key of ['vehicle', 'dealer', 'page'] as const) {\n if (update[key] !== undefined) next[key] = { ...current[key], ...defined(update[key]) };\n }\n return next;\n}\n\nexport const copyContext = (context?: YourRoadContext): YourRoadContext => mergeContext({}, context ?? {});\n","import type { YourRoadContext } from '../context/types';\n\nexport const BRIDGE_VERSION = 1 as const;\n\nexport type BridgeMessage<T = unknown> = {\n source: 'yourroad.sdk' | 'yourroad.embed';\n version: typeof BRIDGE_VERSION;\n type: string;\n requestId?: string;\n payload?: T;\n};\n\nexport type SdkBridgeMessage =\n | BridgeMessage & { source: 'yourroad.sdk'; type: 'ack' }\n | BridgeMessage<YourRoadContext> & { source: 'yourroad.sdk'; type: 'context' | 'context_updated'; payload: YourRoadContext }\n | BridgeMessage<{ sessionId: string }> & { source: 'yourroad.sdk'; type: 'journey_session'; payload: { sessionId: string } };\n","import { copyContext } from '../context/mergeContext';\nimport type { YourRoadContext } from '../context/types';\nimport { BRIDGE_VERSION, type SdkBridgeMessage } from './protocol';\n\nexport function runtimeOriginFromIframeUrl(iframeUrl: string): string {\n const url = new URL(iframeUrl);\n if (url.protocol !== 'https:' && url.protocol !== 'http:') throw new TypeError('The iframe URL must use HTTP(S).');\n return url.origin;\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst isReadyMessage = (value: unknown): boolean => {\n if (!isPlainObject(value)) return false;\n return value.source === 'yourroad.embed'\n && value.version === BRIDGE_VERSION\n && value.type === 'ready'\n && value.payload === undefined\n && (value.requestId === undefined || typeof value.requestId === 'string');\n};\n\nconst isRestartMessage = (value: unknown): boolean => isPlainObject(value)\n && Object.keys(value).length === 3\n && value.source === 'yourroad.embed'\n && value.version === BRIDGE_VERSION\n && value.type === 'journey_session_restart';\n\nexport class BridgeController {\n private ready = false;\n private started = false;\n\n constructor(\n private readonly iframe: HTMLIFrameElement,\n private readonly trustedRuntimeOrigin: string,\n private readonly getCurrentContext: () => YourRoadContext,\n private readonly getJourneySessionId: () => string,\n private readonly onJourneySessionRestart: () => void,\n ) {}\n\n start(): void {\n if (this.started) return;\n window.addEventListener('message', this.handleMessage);\n this.started = true;\n }\n\n contextUpdated(currentContext: YourRoadContext): void {\n if (!this.ready) return;\n this.post({\n source: 'yourroad.sdk',\n version: BRIDGE_VERSION,\n type: 'context_updated',\n payload: copyContext(currentContext),\n });\n }\n\n destroy(): void {\n if (this.started) window.removeEventListener('message', this.handleMessage);\n this.started = false;\n this.ready = false;\n }\n\n private readonly handleMessage = (event: MessageEvent): void => {\n if (event.origin !== this.trustedRuntimeOrigin) return;\n const iframeWindow = this.iframe.contentWindow;\n if (iframeWindow === null || event.source !== iframeWindow) return;\n if (this.ready) {\n if (isRestartMessage(event.data)) this.onJourneySessionRestart();\n return;\n }\n if (!isReadyMessage(event.data)) return;\n this.ready = true;\n this.post({ source: 'yourroad.sdk', version: BRIDGE_VERSION, type: 'ack' });\n this.post({\n source: 'yourroad.sdk',\n version: BRIDGE_VERSION,\n type: 'context',\n payload: copyContext(this.getCurrentContext()),\n });\n this.sendJourneySession(this.getJourneySessionId());\n };\n\n sendJourneySession(sessionId: string): void {\n if (!this.ready) return;\n this.post({ source: 'yourroad.sdk', version: BRIDGE_VERSION, type: 'journey_session', payload: { sessionId } });\n }\n\n private post(message: SdkBridgeMessage): void {\n const iframeWindow = this.iframe.contentWindow;\n if (iframeWindow === null) return;\n try {\n iframeWindow.postMessage(message, this.trustedRuntimeOrigin);\n } catch {\n // The iframe may be removed concurrently; bridge delivery is best-effort.\n }\n }\n}\n","export type YourRoadErrorCode = 'INVALID_INITIALISATION' | 'INVALID_SURFACE' | 'DESTROYED' | 'BOOTSTRAP_FAILED' | 'OVERLAY_CREATION_FAILED' | 'IFRAME_LOAD_FAILED';\n\nexport class YourRoadError extends Error {\n readonly name = 'YourRoadError';\n constructor(public readonly code: YourRoadErrorCode, message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n","export type Handler<T> = (payload: T) => void;\n\nexport class EventEmitter<Events extends object> {\n private listeners = new Map<keyof Events, Set<Handler<never>>>();\n\n on<K extends keyof Events>(event: K, handler: Handler<Events[K]>): () => void {\n const handlers = this.listeners.get(event) ?? new Set();\n handlers.add(handler as Handler<never>);\n this.listeners.set(event, handlers);\n return () => handlers.delete(handler as Handler<never>);\n }\n\n emit<K extends keyof Events>(event: K, payload: Events[K]): void {\n this.listeners.get(event)?.forEach((handler) => handler(payload as never));\n }\n\n clear(): void { this.listeners.clear(); }\n}\n","export class FocusLifecycle {\n private previous: HTMLElement | null = null;\n capture(): void { this.previous = document.activeElement instanceof HTMLElement ? document.activeElement : null; }\n moveTo(element: HTMLElement): void { element.focus(); }\n restore(): void {\n if (this.previous?.isConnected) this.previous.focus();\n this.previous = null;\n }\n}\n","interface SavedStyles { position: string; top: string; left: string; right: string; width: string; overflow: string }\n\nexport class ScrollLock {\n private saved?: SavedStyles;\n private scrollX = 0;\n private scrollY = 0;\n\n lock(): void {\n if (this.saved) return;\n const style = document.body.style;\n this.saved = { position: style.position, top: style.top, left: style.left, right: style.right, width: style.width, overflow: style.overflow };\n this.scrollX = window.scrollX;\n this.scrollY = window.scrollY;\n Object.assign(style, { position: 'fixed', top: `-${this.scrollY}px`, left: `-${this.scrollX}px`, right: '0', width: '100%', overflow: 'hidden' });\n }\n\n unlock(): void {\n if (!this.saved) return;\n Object.assign(document.body.style, this.saved);\n this.saved = undefined;\n window.scrollTo(this.scrollX, this.scrollY);\n }\n}\n","export class IframeController {\n readonly element: HTMLIFrameElement;\n constructor(source: string, onError: () => void) {\n this.element = document.createElement('iframe');\n this.element.dataset.yourroadFrame = '';\n this.element.title = 'YourRoad pre-approval';\n this.element.src = source;\n this.element.addEventListener('error', onError, { once: true });\n }\n destroy(): void { this.element.remove(); }\n}\n","export const SDK_Z_INDEX = 2147483000;\n\nexport const SDK_STYLES = `\n[data-yourroad-overlay-root] { all: initial; position: fixed; inset: 0; z-index: ${SDK_Z_INDEX}; display: block; font-family: system-ui, sans-serif; color: #111; }\n[data-yourroad-scrim] { all: initial; position: absolute; inset: 0; display: block; background: rgba(0, 0, 0, .55); }\n[data-yourroad-panel] { all: initial; box-sizing: border-box; position: absolute; inset-block: 0; inset-inline-end: 0; display: flex; flex-direction: column; width: min(520px, 92vw); height: 100vh; height: 100dvh; padding-block-start: calc(max(12px, env(safe-area-inset-top)) + 56px); overflow: hidden; border-radius: 24px 0 0 24px; background: #fff; box-shadow: -8px 0 30px rgba(0,0,0,.2); }\n[data-yourroad-close] { all: unset; box-sizing: border-box; position: absolute; z-index: 1; inset-block-start: max(12px, env(safe-area-inset-top)); inset-inline-end: max(12px, env(safe-area-inset-right)); width: 44px; height: 44px; display: grid; place-items: center; border-radius: 999px; background: #fff; color: #111; box-shadow: 0 1px 8px rgba(0,0,0,.25); cursor: pointer; font: 28px/1 system-ui, sans-serif; }\n[data-yourroad-close]:focus-visible { outline: 3px solid #1769e0; outline-offset: 2px; }\n[data-yourroad-frame] { all: initial; box-sizing: border-box; display: block; flex: 1 1 auto; min-height: 0; width: 100%; border: 0; background: #fff; }\n@media (max-width: 600px) { [data-yourroad-panel] { inset-block-start: auto; inset-block-end: 0; inset-inline-end: 0; width: 100vw; max-width: none; height: 92vh; height: 92dvh; border-radius: 24px 24px 0 0; box-shadow: 0 -8px 30px rgba(0,0,0,.2); } }\n`;\n\nexport function ensureStyles(): HTMLStyleElement {\n const existing = document.head.querySelector<HTMLStyleElement>('style[data-yourroad-sdk]');\n if (existing) return existing;\n const style = document.createElement('style');\n style.dataset.yourroadSdk = '';\n style.textContent = SDK_STYLES;\n document.head.append(style);\n return style;\n}\n","import { IframeController } from '../iframe/IframeController';\nimport { ensureStyles } from './styles';\n\nexport class OverlayController {\n readonly root: HTMLDivElement;\n readonly closeButton: HTMLButtonElement;\n readonly iframe: IframeController;\n private readonly abort = new AbortController();\n\n constructor(source: string, onClose: () => void, onFrameError: () => void) {\n ensureStyles();\n this.root = document.createElement('div');\n this.root.dataset.yourroadOverlayRoot = '';\n this.root.setAttribute('role', 'dialog');\n this.root.setAttribute('aria-modal', 'true');\n this.root.setAttribute('aria-label', 'YourRoad pre-approval');\n const scrim = document.createElement('div');\n scrim.dataset.yourroadScrim = '';\n const panel = document.createElement('div');\n panel.dataset.yourroadPanel = '';\n this.closeButton = document.createElement('button');\n this.closeButton.type = 'button';\n this.closeButton.dataset.yourroadClose = '';\n this.closeButton.setAttribute('aria-label', 'Close YourRoad');\n const closeIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n closeIcon.setAttribute('viewBox', '0 0 24 24');\n closeIcon.setAttribute('width', '24');\n closeIcon.setAttribute('height', '24');\n closeIcon.setAttribute('fill', 'none');\n closeIcon.setAttribute('stroke', 'currentColor');\n closeIcon.setAttribute('stroke-width', '2');\n closeIcon.setAttribute('stroke-linecap', 'round');\n closeIcon.setAttribute('aria-hidden', 'true');\n const closeIconPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n closeIconPath.setAttribute('d', 'M6 6l12 12M18 6L6 18');\n closeIcon.append(closeIconPath);\n this.closeButton.append(closeIcon);\n this.iframe = new IframeController(source, onFrameError);\n panel.append(this.closeButton, this.iframe.element);\n this.root.append(scrim, panel);\n const signal = this.abort.signal;\n scrim.addEventListener('click', onClose, { signal });\n this.closeButton.addEventListener('click', onClose, { signal });\n document.addEventListener('keydown', (event) => { if (event.key === 'Escape') onClose(); }, { signal });\n }\n\n mount(): void { document.body.append(this.root); }\n destroy(): void {\n this.abort.abort();\n this.iframe.destroy();\n this.root.remove();\n if (!document.querySelector('[data-yourroad-overlay-root]')) {\n document.head.querySelector('style[data-yourroad-sdk]')?.remove();\n }\n }\n}\n","export const JOURNEY_SESSION_MARKER_KEY = 'yr_journey_session_pre_approval_v1';\n\nexport const isUuid = (value: unknown): value is string =>\n typeof value === 'string'\n && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);\n\nexport interface SessionMarker {\n read(): string | undefined;\n write(sessionId: string): void;\n clear(): void;\n}\n\ntype MarkerStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>;\n\nfunction resolveStorage(): MarkerStorage | undefined {\n try { return globalThis.localStorage; } catch { return undefined; }\n}\n\nexport function createSessionMarker(storage: MarkerStorage | undefined = resolveStorage()): SessionMarker {\n const clear = (): void => {\n try { storage?.removeItem(JOURNEY_SESSION_MARKER_KEY); } catch { /* Storage is optional. */ }\n };\n return {\n read() {\n let value: string | null;\n try { value = storage?.getItem(JOURNEY_SESSION_MARKER_KEY) ?? null; } catch { return undefined; }\n if (value === null) return undefined;\n if (!isUuid(value)) { clear(); return undefined; }\n return value;\n },\n write(sessionId) {\n if (!isUuid(sessionId)) return;\n try { storage?.setItem(JOURNEY_SESSION_MARKER_KEY, sessionId); } catch { /* Keep the in-memory session usable. */ }\n },\n clear,\n };\n}\n","import { isUuid } from './sessionMarker';\n\nconst CREATE_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/create-embed-journey-session';\nconst PROBE_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/probe-embed-journey-session';\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\nconst isDate = (value: unknown): value is string => typeof value === 'string' && value.trim() !== '' && !Number.isNaN(Date.parse(value));\nconst options = (body: object, signal?: AbortSignal): RequestInit => ({\n method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),\n credentials: 'omit', cache: 'no-store', signal,\n});\n\nexport async function createJourneySession(partnerKey: string, signal?: AbortSignal): Promise<string> {\n const response = await fetch(CREATE_ENDPOINT, options({ partnerKey, surface: 'pre-approval' }, signal));\n if (response.status !== 201) throw new Error('Journey session creation was unsuccessful.');\n const value: unknown = await response.json();\n if (!isPlainObject(value) || !isUuid(value.sessionId) || !isDate(value.expiresAt)) throw new Error('Invalid journey session response.');\n return value.sessionId;\n}\n\nexport type ProbeResult = { status: 'resumable'; sessionId: string } | { status: 'expired' } | { status: 'invalid' };\n\nexport async function probeJourneySession(partnerKey: string, sessionId: string): Promise<ProbeResult> {\n const response = await fetch(PROBE_ENDPOINT, options({ partnerKey, surface: 'pre-approval', sessionId }));\n const value: unknown = await response.json();\n if (!isPlainObject(value)) throw new Error('Invalid journey session probe response.');\n if (response.status === 200 && value.status === 'resumable' && value.sessionId === sessionId && isDate(value.expiresAt)) {\n return { status: 'resumable', sessionId };\n }\n if (response.status === 410 && value.status === 'expired' && value.code === 'SESSION_EXPIRED') return { status: 'expired' };\n if (response.status === 404 && value.status === 'invalid' && value.code === 'SESSION_INVALID') return { status: 'invalid' };\n throw new Error('Journey session probe was unsuccessful.');\n}\n","import { createJourneySession, probeJourneySession } from './sessionClient';\nimport { createSessionMarker, type SessionMarker } from './sessionMarker';\n\ntype State =\n | { kind: 'cold' }\n | { kind: 'probing'; completion: Promise<void> }\n | { kind: 'active'; sessionId: string }\n | { kind: 'expired'; sessionId: string }\n | { kind: 'probe_failed' };\n\nexport class SessionController {\n private state: State = { kind: 'cold' };\n private restart?: Promise<string>;\n\n constructor(private readonly partnerKey: string, private readonly marker: SessionMarker = createSessionMarker()) {\n const sessionId = marker.read();\n if (!sessionId) return;\n const completion = this.probe(sessionId);\n this.state = { kind: 'probing', completion };\n }\n\n async resolveForOpen(signal: AbortSignal): Promise<string> {\n if (this.state.kind === 'probing') await this.state.completion;\n if (this.state.kind === 'probe_failed') throw new Error('Journey session validity could not be established.');\n if (this.state.kind === 'active' || this.state.kind === 'expired') return this.state.sessionId;\n const sessionId = await createJourneySession(this.partnerKey, signal);\n this.marker.write(sessionId);\n this.state = { kind: 'active', sessionId };\n return sessionId;\n }\n\n restartExpired(signal: AbortSignal): Promise<string> | undefined {\n if (this.state.kind !== 'expired') return undefined;\n if (this.restart) return this.restart;\n const operation = createJourneySession(this.partnerKey, signal).then((sessionId) => {\n this.marker.write(sessionId);\n this.state = { kind: 'active', sessionId };\n return sessionId;\n }).finally(() => { if (this.restart === operation) this.restart = undefined; });\n this.restart = operation;\n return operation;\n }\n\n private async probe(sessionId: string): Promise<void> {\n try {\n const result = await probeJourneySession(this.partnerKey, sessionId);\n if (result.status === 'resumable') this.state = { kind: 'active', sessionId };\n else if (result.status === 'expired') { this.marker.clear(); this.state = { kind: 'expired', sessionId }; }\n else { this.marker.clear(); this.state = { kind: 'cold' }; }\n } catch { this.state = { kind: 'probe_failed' }; }\n }\n}\n","import type { YourRoadInitConfig, YourRoadSurface } from '../config/types';\nimport { requestBootstrap } from '../bootstrap/bootstrapClient';\nimport { BridgeController, runtimeOriginFromIframeUrl } from '../bridge/BridgeController';\nimport { copyContext, mergeContext } from '../context/mergeContext';\nimport type { YourRoadContext, YourRoadContextUpdate } from '../context/types';\nimport { YourRoadError } from '../errors/YourRoadError';\nimport { EventEmitter } from '../events/EventEmitter';\nimport { FocusLifecycle } from '../lifecycle/focus';\nimport { ScrollLock } from '../lifecycle/scrollLock';\nimport { OverlayController } from '../overlay/OverlayController';\nimport { SessionController } from '../session/SessionController';\n\nexport interface OpenOptions { surface: YourRoadSurface; context?: YourRoadContext }\nexport interface YourRoadEvents { opened: undefined; closed: undefined; error: YourRoadError }\n\nexport interface YourRoadClient {\n open(options: OpenOptions): Promise<void>;\n updateContext(update: YourRoadContextUpdate): void;\n close(): void;\n on<K extends keyof YourRoadEvents>(event: K, handler: (payload: YourRoadEvents[K]) => void): () => void;\n destroy(): void;\n}\n\nclass YourRoadClientImpl implements YourRoadClient {\n private readonly events = new EventEmitter<YourRoadEvents>();\n private readonly scroll = new ScrollLock();\n private readonly focus = new FocusLifecycle();\n private overlay?: OverlayController;\n private bridge?: BridgeController;\n private context: YourRoadContext = {};\n private destroyed = false;\n private opening?: Promise<void>;\n private bootstrapAbort?: AbortController;\n private restartAbort?: AbortController;\n private readonly session: SessionController;\n\n constructor(private readonly config: Readonly<YourRoadInitConfig>) {\n this.session = new SessionController(config.partnerKey);\n }\n\n async open(options: OpenOptions): Promise<void> {\n this.assertUsable();\n if (!options || options.surface !== 'pre-approval') throw this.fail('INVALID_SURFACE', 'The only supported surface is \"pre-approval\".');\n if (this.overlay) return;\n if (this.opening) return this.opening;\n this.context = copyContext(options.context);\n const abort = new AbortController();\n this.bootstrapAbort = abort;\n const operation = this.performOpen(options.surface, abort);\n this.opening = operation;\n return operation;\n }\n\n updateContext(update: YourRoadContextUpdate): void {\n this.assertUsable();\n this.context = mergeContext(this.context, update);\n this.bridge?.contextUpdated(this.context);\n }\n\n close(): void {\n this.assertUsable();\n if (this.bootstrapAbort) {\n this.bootstrapAbort.abort();\n this.bootstrapAbort = undefined;\n this.opening = undefined;\n }\n this.restartAbort?.abort();\n this.restartAbort = undefined;\n if (!this.overlay) return;\n this.bridge?.destroy();\n this.bridge = undefined;\n this.overlay.destroy();\n this.overlay = undefined;\n this.scroll.unlock();\n this.focus.restore();\n this.events.emit('closed', undefined);\n }\n\n on<K extends keyof YourRoadEvents>(event: K, handler: (payload: YourRoadEvents[K]) => void): () => void {\n this.assertUsable();\n return this.events.on(event, handler);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.close();\n this.events.clear();\n this.context = {};\n this.destroyed = true;\n }\n\n private async performOpen(surface: YourRoadSurface, abort: AbortController): Promise<void> {\n try {\n const [bootstrap, sessionId] = await Promise.all([\n requestBootstrap({ partnerKey: this.config.partnerKey, surface }, abort.signal),\n this.session.resolveForOpen(abort.signal),\n ]);\n const { iframeUrl } = bootstrap;\n if (abort.signal.aborted || this.destroyed || this.bootstrapAbort !== abort) return;\n this.focus.capture();\n try {\n this.overlay = new OverlayController(iframeUrl, () => this.close(), () => this.fail('IFRAME_LOAD_FAILED', 'The embedded experience failed to load.'));\n this.bridge = new BridgeController(\n this.overlay.iframe.element,\n runtimeOriginFromIframeUrl(iframeUrl),\n () => copyContext(this.context),\n () => sessionId,\n () => this.restartExpiredSession(this.bridge),\n );\n this.bridge.start();\n this.overlay.mount();\n this.scroll.lock();\n this.focus.moveTo(this.overlay.closeButton);\n this.events.emit('opened', undefined);\n } catch (cause) {\n this.bridge?.destroy();\n this.bridge = undefined;\n this.overlay?.destroy();\n this.overlay = undefined;\n this.scroll.unlock();\n this.focus.restore();\n throw this.fail('OVERLAY_CREATION_FAILED', 'The YourRoad overlay could not be created.', cause);\n }\n } catch (cause) {\n if (abort.signal.aborted) return;\n if (cause instanceof YourRoadError) throw cause;\n throw this.fail('BOOTSTRAP_FAILED', 'The YourRoad experience could not be started securely.', cause);\n } finally {\n if (this.bootstrapAbort === abort) {\n this.bootstrapAbort = undefined;\n this.opening = undefined;\n }\n }\n }\n\n private restartExpiredSession(bridge: BridgeController | undefined): void {\n if (this.destroyed || bridge === undefined || bridge !== this.bridge || this.restartAbort) return;\n const restartAbort = new AbortController();\n this.restartAbort = restartAbort;\n const operation = this.session.restartExpired(restartAbort.signal);\n if (!operation) { this.restartAbort = undefined; return; }\n void operation.then((sessionId) => {\n if (!this.destroyed && !restartAbort.signal.aborted && this.bridge === bridge) bridge.sendJourneySession(sessionId);\n }).catch(() => { /* The runtime may offer a later explicit retry. */ }).finally(() => {\n if (this.restartAbort === restartAbort) this.restartAbort = undefined;\n });\n }\n\n private assertUsable(): void { if (this.destroyed) throw new YourRoadError('DESTROYED', 'This YourRoad SDK instance has been destroyed.'); }\n private fail(code: ConstructorParameters<typeof YourRoadError>[0], message: string, cause?: unknown): YourRoadError {\n const error = new YourRoadError(code, message, cause === undefined ? undefined : { cause });\n this.events.emit('error', error);\n return error;\n }\n}\n\nexport function createYourRoadClient(config: Readonly<YourRoadInitConfig>): YourRoadClient {\n return new YourRoadClientImpl(config);\n}\n","import { createYourRoadClient, type YourRoadClient } from './client/YourRoadClient';\nimport type { YourRoadInitConfig } from './config/types';\nimport { YourRoadError } from './errors/YourRoadError';\n\nexport type { OpenOptions, YourRoadClient, YourRoadEvents } from './client/YourRoadClient';\nexport type { YourRoadInitConfig, YourRoadSurface } from './config/types';\nexport type { DealerContext, PageContext, VehicleContext, YourRoadContext, YourRoadContextUpdate } from './context/types';\nexport { YourRoadError };\n\nexport class YourRoad {\n static init(config: YourRoadInitConfig): YourRoadClient {\n if (!config || typeof config.partnerKey !== 'string' || config.partnerKey.trim() === '') {\n throw new YourRoadError('INVALID_INITIALISATION', 'partnerKey must be a non-empty string.');\n }\n return createYourRoadClient({ partnerKey: config.partnerKey });\n }\n}\n"],"names":["BOOTSTRAP_ENDPOINT","validateResponse","value","iframeUrl","expiresAt","parsedUrl","requestBootstrap","request","signal","response","defined","item","mergeContext","current","update","next","key","copyContext","context","BRIDGE_VERSION","runtimeOriginFromIframeUrl","url","isPlainObject","prototype","isReadyMessage","isRestartMessage","BridgeController","iframe","trustedRuntimeOrigin","getCurrentContext","getJourneySessionId","onJourneySessionRestart","__publicField","event","iframeWindow","currentContext","sessionId","message","YourRoadError","code","options","EventEmitter","handler","handlers","payload","_a","FocusLifecycle","element","ScrollLock","style","IframeController","source","onError","SDK_Z_INDEX","SDK_STYLES","ensureStyles","existing","OverlayController","onClose","onFrameError","scrim","panel","closeIcon","closeIconPath","JOURNEY_SESSION_MARKER_KEY","isUuid","resolveStorage","createSessionMarker","storage","clear","CREATE_ENDPOINT","PROBE_ENDPOINT","isDate","body","createJourneySession","partnerKey","probeJourneySession","SessionController","marker","completion","operation","result","YourRoadClientImpl","config","abort","_b","surface","bootstrap","cause","bridge","restartAbort","error","createYourRoadClient","YourRoad"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var o = (s, t, e) =>
|
|
1
|
+
var k = Object.defineProperty;
|
|
2
|
+
var A = (s, t, e) => t in s ? k(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
|
|
3
|
+
var o = (s, t, e) => A(s, typeof t != "symbol" ? t + "" : t, e);
|
|
4
4
|
const S = "https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/bootstrap-embed-access";
|
|
5
|
-
function
|
|
5
|
+
function I(s) {
|
|
6
6
|
if (typeof s != "object" || s === null || Array.isArray(s)) throw new Error("Invalid bootstrap response.");
|
|
7
7
|
const { iframeUrl: t, expiresAt: e } = s;
|
|
8
8
|
if (typeof t != "string" || t.trim() === "") throw new Error("Invalid bootstrap response.");
|
|
@@ -27,28 +27,28 @@ async function O(s, t) {
|
|
|
27
27
|
signal: t
|
|
28
28
|
});
|
|
29
29
|
if (!e.ok) throw new Error("Bootstrap request was unsuccessful.");
|
|
30
|
-
return
|
|
30
|
+
return I(await e.json());
|
|
31
31
|
}
|
|
32
|
-
const
|
|
33
|
-
function
|
|
34
|
-
const e = { ...s, ...
|
|
32
|
+
const y = (s) => Object.fromEntries(Object.entries(s ?? {}).filter(([, t]) => t !== void 0));
|
|
33
|
+
function m(s, t) {
|
|
34
|
+
const e = { ...s, ...y(t) };
|
|
35
35
|
for (const r of ["vehicle", "dealer", "page"])
|
|
36
|
-
t[r] !== void 0 && (e[r] = { ...s[r], ...
|
|
36
|
+
t[r] !== void 0 && (e[r] = { ...s[r], ...y(t[r]) });
|
|
37
37
|
return e;
|
|
38
38
|
}
|
|
39
|
-
const
|
|
40
|
-
function
|
|
39
|
+
const u = (s) => m({}, s ?? {}), d = 1;
|
|
40
|
+
function R(s) {
|
|
41
41
|
const t = new URL(s);
|
|
42
42
|
if (t.protocol !== "https:" && t.protocol !== "http:") throw new TypeError("The iframe URL must use HTTP(S).");
|
|
43
43
|
return t.origin;
|
|
44
44
|
}
|
|
45
|
-
const
|
|
45
|
+
const v = (s) => {
|
|
46
46
|
if (s === null || typeof s != "object") return !1;
|
|
47
47
|
const t = Object.getPrototypeOf(s);
|
|
48
48
|
return t === Object.prototype || t === null;
|
|
49
|
-
},
|
|
50
|
-
class
|
|
51
|
-
constructor(t, e, r, i,
|
|
49
|
+
}, j = (s) => v(s) ? s.source === "yourroad.embed" && s.version === d && s.type === "ready" && s.payload === void 0 && (s.requestId === void 0 || typeof s.requestId == "string") : !1, T = (s) => v(s) && Object.keys(s).length === 3 && s.source === "yourroad.embed" && s.version === d && s.type === "journey_session_restart";
|
|
50
|
+
class _ {
|
|
51
|
+
constructor(t, e, r, i, a) {
|
|
52
52
|
o(this, "ready", !1);
|
|
53
53
|
o(this, "started", !1);
|
|
54
54
|
o(this, "handleMessage", (t) => {
|
|
@@ -56,18 +56,18 @@ class T {
|
|
|
56
56
|
const e = this.iframe.contentWindow;
|
|
57
57
|
if (!(e === null || t.source !== e)) {
|
|
58
58
|
if (this.ready) {
|
|
59
|
-
|
|
59
|
+
T(t.data) && this.onJourneySessionRestart();
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
j(t.data) && (this.ready = !0, this.post({ source: "yourroad.sdk", version: d, type: "ack" }), this.post({
|
|
63
63
|
source: "yourroad.sdk",
|
|
64
|
-
version:
|
|
64
|
+
version: d,
|
|
65
65
|
type: "context",
|
|
66
|
-
payload:
|
|
66
|
+
payload: u(this.getCurrentContext())
|
|
67
67
|
}), this.sendJourneySession(this.getJourneySessionId()));
|
|
68
68
|
}
|
|
69
69
|
});
|
|
70
|
-
this.iframe = t, this.trustedRuntimeOrigin = e, this.getCurrentContext = r, this.getJourneySessionId = i, this.onJourneySessionRestart =
|
|
70
|
+
this.iframe = t, this.trustedRuntimeOrigin = e, this.getCurrentContext = r, this.getJourneySessionId = i, this.onJourneySessionRestart = a;
|
|
71
71
|
}
|
|
72
72
|
start() {
|
|
73
73
|
this.started || (window.addEventListener("message", this.handleMessage), this.started = !0);
|
|
@@ -75,16 +75,16 @@ class T {
|
|
|
75
75
|
contextUpdated(t) {
|
|
76
76
|
this.ready && this.post({
|
|
77
77
|
source: "yourroad.sdk",
|
|
78
|
-
version:
|
|
78
|
+
version: d,
|
|
79
79
|
type: "context_updated",
|
|
80
|
-
payload:
|
|
80
|
+
payload: u(t)
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
83
|
destroy() {
|
|
84
84
|
this.started && window.removeEventListener("message", this.handleMessage), this.started = !1, this.ready = !1;
|
|
85
85
|
}
|
|
86
86
|
sendJourneySession(t) {
|
|
87
|
-
this.ready && this.post({ source: "yourroad.sdk", version:
|
|
87
|
+
this.ready && this.post({ source: "yourroad.sdk", version: d, type: "journey_session", payload: { sessionId: t } });
|
|
88
88
|
}
|
|
89
89
|
post(t) {
|
|
90
90
|
const e = this.iframe.contentWindow;
|
|
@@ -95,14 +95,14 @@ class T {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
-
class
|
|
98
|
+
class h extends Error {
|
|
99
99
|
constructor(e, r, i) {
|
|
100
100
|
super(r, i);
|
|
101
101
|
o(this, "name", "YourRoadError");
|
|
102
102
|
this.code = e;
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
-
class
|
|
105
|
+
class N {
|
|
106
106
|
constructor() {
|
|
107
107
|
o(this, "listeners", /* @__PURE__ */ new Map());
|
|
108
108
|
}
|
|
@@ -118,7 +118,7 @@ class _ {
|
|
|
118
118
|
this.listeners.clear();
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
class
|
|
121
|
+
class C {
|
|
122
122
|
constructor() {
|
|
123
123
|
o(this, "previous", null);
|
|
124
124
|
}
|
|
@@ -133,7 +133,7 @@ class N {
|
|
|
133
133
|
(t = this.previous) != null && t.isConnected && this.previous.focus(), this.previous = null;
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
-
class
|
|
136
|
+
class L {
|
|
137
137
|
constructor() {
|
|
138
138
|
o(this, "saved");
|
|
139
139
|
o(this, "scrollX", 0);
|
|
@@ -148,7 +148,7 @@ class C {
|
|
|
148
148
|
this.saved && (Object.assign(document.body.style, this.saved), this.saved = void 0, window.scrollTo(this.scrollX, this.scrollY));
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
|
-
class
|
|
151
|
+
class D {
|
|
152
152
|
constructor(t, e) {
|
|
153
153
|
o(this, "element");
|
|
154
154
|
this.element = document.createElement("iframe"), this.element.dataset.yourroadFrame = "", this.element.title = "YourRoad pre-approval", this.element.src = t, this.element.addEventListener("error", e, { once: !0 });
|
|
@@ -157,22 +157,22 @@ class L {
|
|
|
157
157
|
this.element.remove();
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
-
const
|
|
161
|
-
[data-yourroad-overlay-root] { all: initial; position: fixed; inset: 0; z-index: ${
|
|
160
|
+
const Y = 2147483e3, B = `
|
|
161
|
+
[data-yourroad-overlay-root] { all: initial; position: fixed; inset: 0; z-index: ${Y}; display: block; font-family: system-ui, sans-serif; color: #111; }
|
|
162
162
|
[data-yourroad-scrim] { all: initial; position: absolute; inset: 0; display: block; background: rgba(0, 0, 0, .55); }
|
|
163
|
-
[data-yourroad-panel] { all: initial; box-sizing: border-box; position: absolute; inset-block: 0; inset-inline-end: 0; display: flex; flex-direction: column; width: min(520px, 92vw); height: 100vh; height: 100dvh; background: #fff; box-shadow: -8px 0 30px rgba(0,0,0,.2); }
|
|
163
|
+
[data-yourroad-panel] { all: initial; box-sizing: border-box; position: absolute; inset-block: 0; inset-inline-end: 0; display: flex; flex-direction: column; width: min(520px, 92vw); height: 100vh; height: 100dvh; padding-block-start: calc(max(12px, env(safe-area-inset-top)) + 56px); overflow: hidden; border-radius: 24px 0 0 24px; background: #fff; box-shadow: -8px 0 30px rgba(0,0,0,.2); }
|
|
164
164
|
[data-yourroad-close] { all: unset; box-sizing: border-box; position: absolute; z-index: 1; inset-block-start: max(12px, env(safe-area-inset-top)); inset-inline-end: max(12px, env(safe-area-inset-right)); width: 44px; height: 44px; display: grid; place-items: center; border-radius: 999px; background: #fff; color: #111; box-shadow: 0 1px 8px rgba(0,0,0,.25); cursor: pointer; font: 28px/1 system-ui, sans-serif; }
|
|
165
165
|
[data-yourroad-close]:focus-visible { outline: 3px solid #1769e0; outline-offset: 2px; }
|
|
166
|
-
[data-yourroad-frame] { all: initial; box-sizing: border-box; display: block;
|
|
167
|
-
@media (max-width: 600px) { [data-yourroad-panel] { width: 100vw; max-width: none; } }
|
|
166
|
+
[data-yourroad-frame] { all: initial; box-sizing: border-box; display: block; flex: 1 1 auto; min-height: 0; width: 100%; border: 0; background: #fff; }
|
|
167
|
+
@media (max-width: 600px) { [data-yourroad-panel] { inset-block-start: auto; inset-block-end: 0; inset-inline-end: 0; width: 100vw; max-width: none; height: 92vh; height: 92dvh; border-radius: 24px 24px 0 0; box-shadow: 0 -8px 30px rgba(0,0,0,.2); } }
|
|
168
168
|
`;
|
|
169
169
|
function K() {
|
|
170
170
|
const s = document.head.querySelector("style[data-yourroad-sdk]");
|
|
171
171
|
if (s) return s;
|
|
172
172
|
const t = document.createElement("style");
|
|
173
|
-
return t.dataset.yourroadSdk = "", t.textContent =
|
|
173
|
+
return t.dataset.yourroadSdk = "", t.textContent = B, document.head.append(t), t;
|
|
174
174
|
}
|
|
175
|
-
class
|
|
175
|
+
class P {
|
|
176
176
|
constructor(t, e, r) {
|
|
177
177
|
o(this, "root");
|
|
178
178
|
o(this, "closeButton");
|
|
@@ -181,12 +181,16 @@ class U {
|
|
|
181
181
|
K(), this.root = document.createElement("div"), this.root.dataset.yourroadOverlayRoot = "", this.root.setAttribute("role", "dialog"), this.root.setAttribute("aria-modal", "true"), this.root.setAttribute("aria-label", "YourRoad pre-approval");
|
|
182
182
|
const i = document.createElement("div");
|
|
183
183
|
i.dataset.yourroadScrim = "";
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
184
|
+
const a = document.createElement("div");
|
|
185
|
+
a.dataset.yourroadPanel = "", this.closeButton = document.createElement("button"), this.closeButton.type = "button", this.closeButton.dataset.yourroadClose = "", this.closeButton.setAttribute("aria-label", "Close YourRoad");
|
|
186
|
+
const n = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
187
|
+
n.setAttribute("viewBox", "0 0 24 24"), n.setAttribute("width", "24"), n.setAttribute("height", "24"), n.setAttribute("fill", "none"), n.setAttribute("stroke", "currentColor"), n.setAttribute("stroke-width", "2"), n.setAttribute("stroke-linecap", "round"), n.setAttribute("aria-hidden", "true");
|
|
188
|
+
const c = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
189
|
+
c.setAttribute("d", "M6 6l12 12M18 6L6 18"), n.append(c), this.closeButton.append(n), this.iframe = new D(t, r), a.append(this.closeButton, this.iframe.element), this.root.append(i, a);
|
|
190
|
+
const l = this.abort.signal;
|
|
191
|
+
i.addEventListener("click", e, { signal: l }), this.closeButton.addEventListener("click", e, { signal: l }), document.addEventListener("keydown", (E) => {
|
|
192
|
+
E.key === "Escape" && e();
|
|
193
|
+
}, { signal: l });
|
|
190
194
|
}
|
|
191
195
|
mount() {
|
|
192
196
|
document.body.append(this.root);
|
|
@@ -196,18 +200,18 @@ class U {
|
|
|
196
200
|
this.abort.abort(), this.iframe.destroy(), this.root.remove(), document.querySelector("[data-yourroad-overlay-root]") || (t = document.head.querySelector("style[data-yourroad-sdk]")) == null || t.remove();
|
|
197
201
|
}
|
|
198
202
|
}
|
|
199
|
-
const
|
|
200
|
-
function
|
|
203
|
+
const p = "yr_journey_session_pre_approval_v1", f = (s) => typeof s == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(s);
|
|
204
|
+
function U() {
|
|
201
205
|
try {
|
|
202
206
|
return globalThis.localStorage;
|
|
203
207
|
} catch {
|
|
204
208
|
return;
|
|
205
209
|
}
|
|
206
210
|
}
|
|
207
|
-
function
|
|
211
|
+
function J(s = U()) {
|
|
208
212
|
const t = () => {
|
|
209
213
|
try {
|
|
210
|
-
s == null || s.removeItem(
|
|
214
|
+
s == null || s.removeItem(p);
|
|
211
215
|
} catch {
|
|
212
216
|
}
|
|
213
217
|
};
|
|
@@ -215,12 +219,12 @@ function P(s = B()) {
|
|
|
215
219
|
read() {
|
|
216
220
|
let e;
|
|
217
221
|
try {
|
|
218
|
-
e = (s == null ? void 0 : s.getItem(
|
|
222
|
+
e = (s == null ? void 0 : s.getItem(p)) ?? null;
|
|
219
223
|
} catch {
|
|
220
224
|
return;
|
|
221
225
|
}
|
|
222
226
|
if (e !== null) {
|
|
223
|
-
if (!
|
|
227
|
+
if (!f(e)) {
|
|
224
228
|
t();
|
|
225
229
|
return;
|
|
226
230
|
}
|
|
@@ -228,20 +232,20 @@ function P(s = B()) {
|
|
|
228
232
|
}
|
|
229
233
|
},
|
|
230
234
|
write(e) {
|
|
231
|
-
if (
|
|
235
|
+
if (f(e))
|
|
232
236
|
try {
|
|
233
|
-
s == null || s.setItem(
|
|
237
|
+
s == null || s.setItem(p, e);
|
|
234
238
|
} catch {
|
|
235
239
|
}
|
|
236
240
|
},
|
|
237
241
|
clear: t
|
|
238
242
|
};
|
|
239
243
|
}
|
|
240
|
-
const
|
|
244
|
+
const q = "https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/create-embed-journey-session", M = "https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/probe-embed-journey-session", w = (s) => {
|
|
241
245
|
if (s === null || typeof s != "object") return !1;
|
|
242
246
|
const t = Object.getPrototypeOf(s);
|
|
243
247
|
return t === Object.prototype || t === null;
|
|
244
|
-
},
|
|
248
|
+
}, x = (s) => typeof s == "string" && s.trim() !== "" && !Number.isNaN(Date.parse(s)), g = (s, t) => ({
|
|
245
249
|
method: "POST",
|
|
246
250
|
headers: { "Content-Type": "application/json" },
|
|
247
251
|
body: JSON.stringify(s),
|
|
@@ -249,24 +253,24 @@ const J = "https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/create-embed-jo
|
|
|
249
253
|
cache: "no-store",
|
|
250
254
|
signal: t
|
|
251
255
|
});
|
|
252
|
-
async function
|
|
253
|
-
const e = await fetch(
|
|
256
|
+
async function b(s, t) {
|
|
257
|
+
const e = await fetch(q, g({ partnerKey: s, surface: "pre-approval" }, t));
|
|
254
258
|
if (e.status !== 201) throw new Error("Journey session creation was unsuccessful.");
|
|
255
259
|
const r = await e.json();
|
|
256
|
-
if (!
|
|
260
|
+
if (!w(r) || !f(r.sessionId) || !x(r.expiresAt)) throw new Error("Invalid journey session response.");
|
|
257
261
|
return r.sessionId;
|
|
258
262
|
}
|
|
259
|
-
async function
|
|
260
|
-
const e = await fetch(
|
|
261
|
-
if (!
|
|
262
|
-
if (e.status === 200 && r.status === "resumable" && r.sessionId === t &&
|
|
263
|
+
async function F(s, t) {
|
|
264
|
+
const e = await fetch(M, g({ partnerKey: s, surface: "pre-approval", sessionId: t })), r = await e.json();
|
|
265
|
+
if (!w(r)) throw new Error("Invalid journey session probe response.");
|
|
266
|
+
if (e.status === 200 && r.status === "resumable" && r.sessionId === t && x(r.expiresAt))
|
|
263
267
|
return { status: "resumable", sessionId: t };
|
|
264
268
|
if (e.status === 410 && r.status === "expired" && r.code === "SESSION_EXPIRED") return { status: "expired" };
|
|
265
269
|
if (e.status === 404 && r.status === "invalid" && r.code === "SESSION_INVALID") return { status: "invalid" };
|
|
266
270
|
throw new Error("Journey session probe was unsuccessful.");
|
|
267
271
|
}
|
|
268
|
-
class
|
|
269
|
-
constructor(t, e =
|
|
272
|
+
class X {
|
|
273
|
+
constructor(t, e = J()) {
|
|
270
274
|
o(this, "state", { kind: "cold" });
|
|
271
275
|
o(this, "restart");
|
|
272
276
|
this.partnerKey = t, this.marker = e;
|
|
@@ -278,31 +282,31 @@ class F {
|
|
|
278
282
|
async resolveForOpen(t) {
|
|
279
283
|
if (this.state.kind === "probing" && await this.state.completion, this.state.kind === "probe_failed") throw new Error("Journey session validity could not be established.");
|
|
280
284
|
if (this.state.kind === "active" || this.state.kind === "expired") return this.state.sessionId;
|
|
281
|
-
const e = await
|
|
285
|
+
const e = await b(this.partnerKey, t);
|
|
282
286
|
return this.marker.write(e), this.state = { kind: "active", sessionId: e }, e;
|
|
283
287
|
}
|
|
284
288
|
restartExpired(t) {
|
|
285
289
|
if (this.state.kind !== "expired") return;
|
|
286
290
|
if (this.restart) return this.restart;
|
|
287
|
-
const e =
|
|
291
|
+
const e = b(this.partnerKey, t).then((r) => (this.marker.write(r), this.state = { kind: "active", sessionId: r }, r)).finally(() => {
|
|
288
292
|
this.restart === e && (this.restart = void 0);
|
|
289
293
|
});
|
|
290
294
|
return this.restart = e, e;
|
|
291
295
|
}
|
|
292
296
|
async probe(t) {
|
|
293
297
|
try {
|
|
294
|
-
const e = await
|
|
298
|
+
const e = await F(this.partnerKey, t);
|
|
295
299
|
e.status === "resumable" ? this.state = { kind: "active", sessionId: t } : e.status === "expired" ? (this.marker.clear(), this.state = { kind: "expired", sessionId: t }) : (this.marker.clear(), this.state = { kind: "cold" });
|
|
296
300
|
} catch {
|
|
297
301
|
this.state = { kind: "probe_failed" };
|
|
298
302
|
}
|
|
299
303
|
}
|
|
300
304
|
}
|
|
301
|
-
class
|
|
305
|
+
class z {
|
|
302
306
|
constructor(t) {
|
|
303
|
-
o(this, "events", new
|
|
304
|
-
o(this, "scroll", new
|
|
305
|
-
o(this, "focus", new
|
|
307
|
+
o(this, "events", new N());
|
|
308
|
+
o(this, "scroll", new L());
|
|
309
|
+
o(this, "focus", new C());
|
|
306
310
|
o(this, "overlay");
|
|
307
311
|
o(this, "bridge");
|
|
308
312
|
o(this, "context", {});
|
|
@@ -311,13 +315,13 @@ class X {
|
|
|
311
315
|
o(this, "bootstrapAbort");
|
|
312
316
|
o(this, "restartAbort");
|
|
313
317
|
o(this, "session");
|
|
314
|
-
this.config = t, this.session = new
|
|
318
|
+
this.config = t, this.session = new X(t.partnerKey);
|
|
315
319
|
}
|
|
316
320
|
async open(t) {
|
|
317
321
|
if (this.assertUsable(), !t || t.surface !== "pre-approval") throw this.fail("INVALID_SURFACE", 'The only supported surface is "pre-approval".');
|
|
318
322
|
if (this.overlay) return;
|
|
319
323
|
if (this.opening) return this.opening;
|
|
320
|
-
this.context =
|
|
324
|
+
this.context = u(t.context);
|
|
321
325
|
const e = new AbortController();
|
|
322
326
|
this.bootstrapAbort = e;
|
|
323
327
|
const r = this.performOpen(t.surface, e);
|
|
@@ -325,7 +329,7 @@ class X {
|
|
|
325
329
|
}
|
|
326
330
|
updateContext(t) {
|
|
327
331
|
var e;
|
|
328
|
-
this.assertUsable(), this.context =
|
|
332
|
+
this.assertUsable(), this.context = m(this.context, t), (e = this.bridge) == null || e.contextUpdated(this.context);
|
|
329
333
|
}
|
|
330
334
|
close() {
|
|
331
335
|
var t, e;
|
|
@@ -340,26 +344,26 @@ class X {
|
|
|
340
344
|
async performOpen(t, e) {
|
|
341
345
|
var r, i;
|
|
342
346
|
try {
|
|
343
|
-
const [
|
|
347
|
+
const [a, n] = await Promise.all([
|
|
344
348
|
O({ partnerKey: this.config.partnerKey, surface: t }, e.signal),
|
|
345
349
|
this.session.resolveForOpen(e.signal)
|
|
346
|
-
]), { iframeUrl: c } =
|
|
350
|
+
]), { iframeUrl: c } = a;
|
|
347
351
|
if (e.signal.aborted || this.destroyed || this.bootstrapAbort !== e) return;
|
|
348
352
|
this.focus.capture();
|
|
349
353
|
try {
|
|
350
|
-
this.overlay = new
|
|
354
|
+
this.overlay = new P(c, () => this.close(), () => this.fail("IFRAME_LOAD_FAILED", "The embedded experience failed to load.")), this.bridge = new _(
|
|
351
355
|
this.overlay.iframe.element,
|
|
352
|
-
|
|
353
|
-
() =>
|
|
354
|
-
() =>
|
|
356
|
+
R(c),
|
|
357
|
+
() => u(this.context),
|
|
358
|
+
() => n,
|
|
355
359
|
() => this.restartExpiredSession(this.bridge)
|
|
356
360
|
), this.bridge.start(), this.overlay.mount(), this.scroll.lock(), this.focus.moveTo(this.overlay.closeButton), this.events.emit("opened", void 0);
|
|
357
|
-
} catch (
|
|
358
|
-
throw (r = this.bridge) == null || r.destroy(), this.bridge = void 0, (i = this.overlay) == null || i.destroy(), this.overlay = void 0, this.scroll.unlock(), this.focus.restore(), this.fail("OVERLAY_CREATION_FAILED", "The YourRoad overlay could not be created.",
|
|
361
|
+
} catch (l) {
|
|
362
|
+
throw (r = this.bridge) == null || r.destroy(), this.bridge = void 0, (i = this.overlay) == null || i.destroy(), this.overlay = void 0, this.scroll.unlock(), this.focus.restore(), this.fail("OVERLAY_CREATION_FAILED", "The YourRoad overlay could not be created.", l);
|
|
359
363
|
}
|
|
360
|
-
} catch (
|
|
364
|
+
} catch (a) {
|
|
361
365
|
if (e.signal.aborted) return;
|
|
362
|
-
throw
|
|
366
|
+
throw a instanceof h ? a : this.fail("BOOTSTRAP_FAILED", "The YourRoad experience could not be started securely.", a);
|
|
363
367
|
} finally {
|
|
364
368
|
this.bootstrapAbort === e && (this.bootstrapAbort = void 0, this.opening = void 0);
|
|
365
369
|
}
|
|
@@ -381,25 +385,25 @@ class X {
|
|
|
381
385
|
});
|
|
382
386
|
}
|
|
383
387
|
assertUsable() {
|
|
384
|
-
if (this.destroyed) throw new
|
|
388
|
+
if (this.destroyed) throw new h("DESTROYED", "This YourRoad SDK instance has been destroyed.");
|
|
385
389
|
}
|
|
386
390
|
fail(t, e, r) {
|
|
387
|
-
const i = new
|
|
391
|
+
const i = new h(t, e, r === void 0 ? void 0 : { cause: r });
|
|
388
392
|
return this.events.emit("error", i), i;
|
|
389
393
|
}
|
|
390
394
|
}
|
|
391
|
-
function
|
|
392
|
-
return new
|
|
395
|
+
function V(s) {
|
|
396
|
+
return new z(s);
|
|
393
397
|
}
|
|
394
|
-
class
|
|
398
|
+
class W {
|
|
395
399
|
static init(t) {
|
|
396
400
|
if (!t || typeof t.partnerKey != "string" || t.partnerKey.trim() === "")
|
|
397
|
-
throw new
|
|
398
|
-
return
|
|
401
|
+
throw new h("INVALID_INITIALISATION", "partnerKey must be a non-empty string.");
|
|
402
|
+
return V({ partnerKey: t.partnerKey });
|
|
399
403
|
}
|
|
400
404
|
}
|
|
401
405
|
export {
|
|
402
|
-
|
|
403
|
-
|
|
406
|
+
W as YourRoad,
|
|
407
|
+
h as YourRoadError
|
|
404
408
|
};
|
|
405
409
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/bootstrap/bootstrapClient.ts","../src/context/mergeContext.ts","../src/bridge/protocol.ts","../src/bridge/BridgeController.ts","../src/errors/YourRoadError.ts","../src/events/EventEmitter.ts","../src/lifecycle/focus.ts","../src/lifecycle/scrollLock.ts","../src/iframe/IframeController.ts","../src/overlay/styles.ts","../src/overlay/OverlayController.ts","../src/session/sessionMarker.ts","../src/session/sessionClient.ts","../src/session/SessionController.ts","../src/client/YourRoadClient.ts","../src/index.ts"],"sourcesContent":["import type { YourRoadSurface } from '../config/types';\n\nconst BOOTSTRAP_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/bootstrap-embed-access';\n\ninterface BootstrapRequest {\n partnerKey: string;\n surface: YourRoadSurface;\n}\n\nexport interface BootstrapResult {\n iframeUrl: string;\n expiresAt: string;\n}\n\nfunction validateResponse(value: unknown): BootstrapResult {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('Invalid bootstrap response.');\n const { iframeUrl, expiresAt } = value as Record<string, unknown>;\n if (typeof iframeUrl !== 'string' || iframeUrl.trim() === '') throw new Error('Invalid bootstrap response.');\n let parsedUrl: URL;\n try { parsedUrl = new URL(iframeUrl); } catch { throw new Error('Invalid bootstrap response.'); }\n if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') throw new Error('Invalid bootstrap response.');\n if (typeof expiresAt !== 'string' || expiresAt.trim() === '' || Number.isNaN(Date.parse(expiresAt))) {\n throw new Error('Invalid bootstrap response.');\n }\n return { iframeUrl, expiresAt };\n}\n\nexport async function requestBootstrap(request: BootstrapRequest, signal: AbortSignal): Promise<BootstrapResult> {\n const response = await fetch(BOOTSTRAP_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n credentials: 'omit',\n cache: 'no-store',\n signal,\n });\n if (!response.ok) throw new Error('Bootstrap request was unsuccessful.');\n return validateResponse(await response.json());\n}\n","import type { YourRoadContext, YourRoadContextUpdate } from './types';\n\nconst defined = <T extends object>(value: T | undefined): Partial<T> =>\n Object.fromEntries(Object.entries(value ?? {}).filter(([, item]) => item !== undefined)) as Partial<T>;\n\n/** Merges known context sections. Explicit `undefined` values are ignored. */\nexport function mergeContext(current: YourRoadContext, update: YourRoadContextUpdate): YourRoadContext {\n const next: YourRoadContext = { ...current, ...defined(update) };\n for (const key of ['vehicle', 'dealer', 'page'] as const) {\n if (update[key] !== undefined) next[key] = { ...current[key], ...defined(update[key]) };\n }\n return next;\n}\n\nexport const copyContext = (context?: YourRoadContext): YourRoadContext => mergeContext({}, context ?? {});\n","import type { YourRoadContext } from '../context/types';\n\nexport const BRIDGE_VERSION = 1 as const;\n\nexport type BridgeMessage<T = unknown> = {\n source: 'yourroad.sdk' | 'yourroad.embed';\n version: typeof BRIDGE_VERSION;\n type: string;\n requestId?: string;\n payload?: T;\n};\n\nexport type SdkBridgeMessage =\n | BridgeMessage & { source: 'yourroad.sdk'; type: 'ack' }\n | BridgeMessage<YourRoadContext> & { source: 'yourroad.sdk'; type: 'context' | 'context_updated'; payload: YourRoadContext }\n | BridgeMessage<{ sessionId: string }> & { source: 'yourroad.sdk'; type: 'journey_session'; payload: { sessionId: string } };\n","import { copyContext } from '../context/mergeContext';\nimport type { YourRoadContext } from '../context/types';\nimport { BRIDGE_VERSION, type SdkBridgeMessage } from './protocol';\n\nexport function runtimeOriginFromIframeUrl(iframeUrl: string): string {\n const url = new URL(iframeUrl);\n if (url.protocol !== 'https:' && url.protocol !== 'http:') throw new TypeError('The iframe URL must use HTTP(S).');\n return url.origin;\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst isReadyMessage = (value: unknown): boolean => {\n if (!isPlainObject(value)) return false;\n return value.source === 'yourroad.embed'\n && value.version === BRIDGE_VERSION\n && value.type === 'ready'\n && value.payload === undefined\n && (value.requestId === undefined || typeof value.requestId === 'string');\n};\n\nconst isRestartMessage = (value: unknown): boolean => isPlainObject(value)\n && Object.keys(value).length === 3\n && value.source === 'yourroad.embed'\n && value.version === BRIDGE_VERSION\n && value.type === 'journey_session_restart';\n\nexport class BridgeController {\n private ready = false;\n private started = false;\n\n constructor(\n private readonly iframe: HTMLIFrameElement,\n private readonly trustedRuntimeOrigin: string,\n private readonly getCurrentContext: () => YourRoadContext,\n private readonly getJourneySessionId: () => string,\n private readonly onJourneySessionRestart: () => void,\n ) {}\n\n start(): void {\n if (this.started) return;\n window.addEventListener('message', this.handleMessage);\n this.started = true;\n }\n\n contextUpdated(currentContext: YourRoadContext): void {\n if (!this.ready) return;\n this.post({\n source: 'yourroad.sdk',\n version: BRIDGE_VERSION,\n type: 'context_updated',\n payload: copyContext(currentContext),\n });\n }\n\n destroy(): void {\n if (this.started) window.removeEventListener('message', this.handleMessage);\n this.started = false;\n this.ready = false;\n }\n\n private readonly handleMessage = (event: MessageEvent): void => {\n if (event.origin !== this.trustedRuntimeOrigin) return;\n const iframeWindow = this.iframe.contentWindow;\n if (iframeWindow === null || event.source !== iframeWindow) return;\n if (this.ready) {\n if (isRestartMessage(event.data)) this.onJourneySessionRestart();\n return;\n }\n if (!isReadyMessage(event.data)) return;\n this.ready = true;\n this.post({ source: 'yourroad.sdk', version: BRIDGE_VERSION, type: 'ack' });\n this.post({\n source: 'yourroad.sdk',\n version: BRIDGE_VERSION,\n type: 'context',\n payload: copyContext(this.getCurrentContext()),\n });\n this.sendJourneySession(this.getJourneySessionId());\n };\n\n sendJourneySession(sessionId: string): void {\n if (!this.ready) return;\n this.post({ source: 'yourroad.sdk', version: BRIDGE_VERSION, type: 'journey_session', payload: { sessionId } });\n }\n\n private post(message: SdkBridgeMessage): void {\n const iframeWindow = this.iframe.contentWindow;\n if (iframeWindow === null) return;\n try {\n iframeWindow.postMessage(message, this.trustedRuntimeOrigin);\n } catch {\n // The iframe may be removed concurrently; bridge delivery is best-effort.\n }\n }\n}\n","export type YourRoadErrorCode = 'INVALID_INITIALISATION' | 'INVALID_SURFACE' | 'DESTROYED' | 'BOOTSTRAP_FAILED' | 'OVERLAY_CREATION_FAILED' | 'IFRAME_LOAD_FAILED';\n\nexport class YourRoadError extends Error {\n readonly name = 'YourRoadError';\n constructor(public readonly code: YourRoadErrorCode, message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n","export type Handler<T> = (payload: T) => void;\n\nexport class EventEmitter<Events extends object> {\n private listeners = new Map<keyof Events, Set<Handler<never>>>();\n\n on<K extends keyof Events>(event: K, handler: Handler<Events[K]>): () => void {\n const handlers = this.listeners.get(event) ?? new Set();\n handlers.add(handler as Handler<never>);\n this.listeners.set(event, handlers);\n return () => handlers.delete(handler as Handler<never>);\n }\n\n emit<K extends keyof Events>(event: K, payload: Events[K]): void {\n this.listeners.get(event)?.forEach((handler) => handler(payload as never));\n }\n\n clear(): void { this.listeners.clear(); }\n}\n","export class FocusLifecycle {\n private previous: HTMLElement | null = null;\n capture(): void { this.previous = document.activeElement instanceof HTMLElement ? document.activeElement : null; }\n moveTo(element: HTMLElement): void { element.focus(); }\n restore(): void {\n if (this.previous?.isConnected) this.previous.focus();\n this.previous = null;\n }\n}\n","interface SavedStyles { position: string; top: string; left: string; right: string; width: string; overflow: string }\n\nexport class ScrollLock {\n private saved?: SavedStyles;\n private scrollX = 0;\n private scrollY = 0;\n\n lock(): void {\n if (this.saved) return;\n const style = document.body.style;\n this.saved = { position: style.position, top: style.top, left: style.left, right: style.right, width: style.width, overflow: style.overflow };\n this.scrollX = window.scrollX;\n this.scrollY = window.scrollY;\n Object.assign(style, { position: 'fixed', top: `-${this.scrollY}px`, left: `-${this.scrollX}px`, right: '0', width: '100%', overflow: 'hidden' });\n }\n\n unlock(): void {\n if (!this.saved) return;\n Object.assign(document.body.style, this.saved);\n this.saved = undefined;\n window.scrollTo(this.scrollX, this.scrollY);\n }\n}\n","export class IframeController {\n readonly element: HTMLIFrameElement;\n constructor(source: string, onError: () => void) {\n this.element = document.createElement('iframe');\n this.element.dataset.yourroadFrame = '';\n this.element.title = 'YourRoad pre-approval';\n this.element.src = source;\n this.element.addEventListener('error', onError, { once: true });\n }\n destroy(): void { this.element.remove(); }\n}\n","export const SDK_Z_INDEX = 2147483000;\n\nexport const SDK_STYLES = `\n[data-yourroad-overlay-root] { all: initial; position: fixed; inset: 0; z-index: ${SDK_Z_INDEX}; display: block; font-family: system-ui, sans-serif; color: #111; }\n[data-yourroad-scrim] { all: initial; position: absolute; inset: 0; display: block; background: rgba(0, 0, 0, .55); }\n[data-yourroad-panel] { all: initial; box-sizing: border-box; position: absolute; inset-block: 0; inset-inline-end: 0; display: flex; flex-direction: column; width: min(520px, 92vw); height: 100vh; height: 100dvh; background: #fff; box-shadow: -8px 0 30px rgba(0,0,0,.2); }\n[data-yourroad-close] { all: unset; box-sizing: border-box; position: absolute; z-index: 1; inset-block-start: max(12px, env(safe-area-inset-top)); inset-inline-end: max(12px, env(safe-area-inset-right)); width: 44px; height: 44px; display: grid; place-items: center; border-radius: 999px; background: #fff; color: #111; box-shadow: 0 1px 8px rgba(0,0,0,.25); cursor: pointer; font: 28px/1 system-ui, sans-serif; }\n[data-yourroad-close]:focus-visible { outline: 3px solid #1769e0; outline-offset: 2px; }\n[data-yourroad-frame] { all: initial; box-sizing: border-box; display: block; width: 100%; height: 100%; border: 0; background: #fff; }\n@media (max-width: 600px) { [data-yourroad-panel] { width: 100vw; max-width: none; } }\n`;\n\nexport function ensureStyles(): HTMLStyleElement {\n const existing = document.head.querySelector<HTMLStyleElement>('style[data-yourroad-sdk]');\n if (existing) return existing;\n const style = document.createElement('style');\n style.dataset.yourroadSdk = '';\n style.textContent = SDK_STYLES;\n document.head.append(style);\n return style;\n}\n","import { IframeController } from '../iframe/IframeController';\nimport { ensureStyles } from './styles';\n\nexport class OverlayController {\n readonly root: HTMLDivElement;\n readonly closeButton: HTMLButtonElement;\n readonly iframe: IframeController;\n private readonly abort = new AbortController();\n\n constructor(source: string, onClose: () => void, onFrameError: () => void) {\n ensureStyles();\n this.root = document.createElement('div');\n this.root.dataset.yourroadOverlayRoot = '';\n this.root.setAttribute('role', 'dialog');\n this.root.setAttribute('aria-modal', 'true');\n this.root.setAttribute('aria-label', 'YourRoad pre-approval');\n const scrim = document.createElement('div');\n scrim.dataset.yourroadScrim = '';\n const panel = document.createElement('div');\n panel.dataset.yourroadPanel = '';\n this.closeButton = document.createElement('button');\n this.closeButton.type = 'button';\n this.closeButton.dataset.yourroadClose = '';\n this.closeButton.setAttribute('aria-label', 'Close YourRoad');\n this.closeButton.textContent = '×';\n this.iframe = new IframeController(source, onFrameError);\n panel.append(this.closeButton, this.iframe.element);\n this.root.append(scrim, panel);\n const signal = this.abort.signal;\n scrim.addEventListener('click', onClose, { signal });\n this.closeButton.addEventListener('click', onClose, { signal });\n document.addEventListener('keydown', (event) => { if (event.key === 'Escape') onClose(); }, { signal });\n }\n\n mount(): void { document.body.append(this.root); }\n destroy(): void {\n this.abort.abort();\n this.iframe.destroy();\n this.root.remove();\n if (!document.querySelector('[data-yourroad-overlay-root]')) {\n document.head.querySelector('style[data-yourroad-sdk]')?.remove();\n }\n }\n}\n","export const JOURNEY_SESSION_MARKER_KEY = 'yr_journey_session_pre_approval_v1';\n\nexport const isUuid = (value: unknown): value is string =>\n typeof value === 'string'\n && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);\n\nexport interface SessionMarker {\n read(): string | undefined;\n write(sessionId: string): void;\n clear(): void;\n}\n\ntype MarkerStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>;\n\nfunction resolveStorage(): MarkerStorage | undefined {\n try { return globalThis.localStorage; } catch { return undefined; }\n}\n\nexport function createSessionMarker(storage: MarkerStorage | undefined = resolveStorage()): SessionMarker {\n const clear = (): void => {\n try { storage?.removeItem(JOURNEY_SESSION_MARKER_KEY); } catch { /* Storage is optional. */ }\n };\n return {\n read() {\n let value: string | null;\n try { value = storage?.getItem(JOURNEY_SESSION_MARKER_KEY) ?? null; } catch { return undefined; }\n if (value === null) return undefined;\n if (!isUuid(value)) { clear(); return undefined; }\n return value;\n },\n write(sessionId) {\n if (!isUuid(sessionId)) return;\n try { storage?.setItem(JOURNEY_SESSION_MARKER_KEY, sessionId); } catch { /* Keep the in-memory session usable. */ }\n },\n clear,\n };\n}\n","import { isUuid } from './sessionMarker';\n\nconst CREATE_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/create-embed-journey-session';\nconst PROBE_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/probe-embed-journey-session';\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\nconst isDate = (value: unknown): value is string => typeof value === 'string' && value.trim() !== '' && !Number.isNaN(Date.parse(value));\nconst options = (body: object, signal?: AbortSignal): RequestInit => ({\n method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),\n credentials: 'omit', cache: 'no-store', signal,\n});\n\nexport async function createJourneySession(partnerKey: string, signal?: AbortSignal): Promise<string> {\n const response = await fetch(CREATE_ENDPOINT, options({ partnerKey, surface: 'pre-approval' }, signal));\n if (response.status !== 201) throw new Error('Journey session creation was unsuccessful.');\n const value: unknown = await response.json();\n if (!isPlainObject(value) || !isUuid(value.sessionId) || !isDate(value.expiresAt)) throw new Error('Invalid journey session response.');\n return value.sessionId;\n}\n\nexport type ProbeResult = { status: 'resumable'; sessionId: string } | { status: 'expired' } | { status: 'invalid' };\n\nexport async function probeJourneySession(partnerKey: string, sessionId: string): Promise<ProbeResult> {\n const response = await fetch(PROBE_ENDPOINT, options({ partnerKey, surface: 'pre-approval', sessionId }));\n const value: unknown = await response.json();\n if (!isPlainObject(value)) throw new Error('Invalid journey session probe response.');\n if (response.status === 200 && value.status === 'resumable' && value.sessionId === sessionId && isDate(value.expiresAt)) {\n return { status: 'resumable', sessionId };\n }\n if (response.status === 410 && value.status === 'expired' && value.code === 'SESSION_EXPIRED') return { status: 'expired' };\n if (response.status === 404 && value.status === 'invalid' && value.code === 'SESSION_INVALID') return { status: 'invalid' };\n throw new Error('Journey session probe was unsuccessful.');\n}\n","import { createJourneySession, probeJourneySession } from './sessionClient';\nimport { createSessionMarker, type SessionMarker } from './sessionMarker';\n\ntype State =\n | { kind: 'cold' }\n | { kind: 'probing'; completion: Promise<void> }\n | { kind: 'active'; sessionId: string }\n | { kind: 'expired'; sessionId: string }\n | { kind: 'probe_failed' };\n\nexport class SessionController {\n private state: State = { kind: 'cold' };\n private restart?: Promise<string>;\n\n constructor(private readonly partnerKey: string, private readonly marker: SessionMarker = createSessionMarker()) {\n const sessionId = marker.read();\n if (!sessionId) return;\n const completion = this.probe(sessionId);\n this.state = { kind: 'probing', completion };\n }\n\n async resolveForOpen(signal: AbortSignal): Promise<string> {\n if (this.state.kind === 'probing') await this.state.completion;\n if (this.state.kind === 'probe_failed') throw new Error('Journey session validity could not be established.');\n if (this.state.kind === 'active' || this.state.kind === 'expired') return this.state.sessionId;\n const sessionId = await createJourneySession(this.partnerKey, signal);\n this.marker.write(sessionId);\n this.state = { kind: 'active', sessionId };\n return sessionId;\n }\n\n restartExpired(signal: AbortSignal): Promise<string> | undefined {\n if (this.state.kind !== 'expired') return undefined;\n if (this.restart) return this.restart;\n const operation = createJourneySession(this.partnerKey, signal).then((sessionId) => {\n this.marker.write(sessionId);\n this.state = { kind: 'active', sessionId };\n return sessionId;\n }).finally(() => { if (this.restart === operation) this.restart = undefined; });\n this.restart = operation;\n return operation;\n }\n\n private async probe(sessionId: string): Promise<void> {\n try {\n const result = await probeJourneySession(this.partnerKey, sessionId);\n if (result.status === 'resumable') this.state = { kind: 'active', sessionId };\n else if (result.status === 'expired') { this.marker.clear(); this.state = { kind: 'expired', sessionId }; }\n else { this.marker.clear(); this.state = { kind: 'cold' }; }\n } catch { this.state = { kind: 'probe_failed' }; }\n }\n}\n","import type { YourRoadInitConfig, YourRoadSurface } from '../config/types';\nimport { requestBootstrap } from '../bootstrap/bootstrapClient';\nimport { BridgeController, runtimeOriginFromIframeUrl } from '../bridge/BridgeController';\nimport { copyContext, mergeContext } from '../context/mergeContext';\nimport type { YourRoadContext, YourRoadContextUpdate } from '../context/types';\nimport { YourRoadError } from '../errors/YourRoadError';\nimport { EventEmitter } from '../events/EventEmitter';\nimport { FocusLifecycle } from '../lifecycle/focus';\nimport { ScrollLock } from '../lifecycle/scrollLock';\nimport { OverlayController } from '../overlay/OverlayController';\nimport { SessionController } from '../session/SessionController';\n\nexport interface OpenOptions { surface: YourRoadSurface; context?: YourRoadContext }\nexport interface YourRoadEvents { opened: undefined; closed: undefined; error: YourRoadError }\n\nexport interface YourRoadClient {\n open(options: OpenOptions): Promise<void>;\n updateContext(update: YourRoadContextUpdate): void;\n close(): void;\n on<K extends keyof YourRoadEvents>(event: K, handler: (payload: YourRoadEvents[K]) => void): () => void;\n destroy(): void;\n}\n\nclass YourRoadClientImpl implements YourRoadClient {\n private readonly events = new EventEmitter<YourRoadEvents>();\n private readonly scroll = new ScrollLock();\n private readonly focus = new FocusLifecycle();\n private overlay?: OverlayController;\n private bridge?: BridgeController;\n private context: YourRoadContext = {};\n private destroyed = false;\n private opening?: Promise<void>;\n private bootstrapAbort?: AbortController;\n private restartAbort?: AbortController;\n private readonly session: SessionController;\n\n constructor(private readonly config: Readonly<YourRoadInitConfig>) {\n this.session = new SessionController(config.partnerKey);\n }\n\n async open(options: OpenOptions): Promise<void> {\n this.assertUsable();\n if (!options || options.surface !== 'pre-approval') throw this.fail('INVALID_SURFACE', 'The only supported surface is \"pre-approval\".');\n if (this.overlay) return;\n if (this.opening) return this.opening;\n this.context = copyContext(options.context);\n const abort = new AbortController();\n this.bootstrapAbort = abort;\n const operation = this.performOpen(options.surface, abort);\n this.opening = operation;\n return operation;\n }\n\n updateContext(update: YourRoadContextUpdate): void {\n this.assertUsable();\n this.context = mergeContext(this.context, update);\n this.bridge?.contextUpdated(this.context);\n }\n\n close(): void {\n this.assertUsable();\n if (this.bootstrapAbort) {\n this.bootstrapAbort.abort();\n this.bootstrapAbort = undefined;\n this.opening = undefined;\n }\n this.restartAbort?.abort();\n this.restartAbort = undefined;\n if (!this.overlay) return;\n this.bridge?.destroy();\n this.bridge = undefined;\n this.overlay.destroy();\n this.overlay = undefined;\n this.scroll.unlock();\n this.focus.restore();\n this.events.emit('closed', undefined);\n }\n\n on<K extends keyof YourRoadEvents>(event: K, handler: (payload: YourRoadEvents[K]) => void): () => void {\n this.assertUsable();\n return this.events.on(event, handler);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.close();\n this.events.clear();\n this.context = {};\n this.destroyed = true;\n }\n\n private async performOpen(surface: YourRoadSurface, abort: AbortController): Promise<void> {\n try {\n const [bootstrap, sessionId] = await Promise.all([\n requestBootstrap({ partnerKey: this.config.partnerKey, surface }, abort.signal),\n this.session.resolveForOpen(abort.signal),\n ]);\n const { iframeUrl } = bootstrap;\n if (abort.signal.aborted || this.destroyed || this.bootstrapAbort !== abort) return;\n this.focus.capture();\n try {\n this.overlay = new OverlayController(iframeUrl, () => this.close(), () => this.fail('IFRAME_LOAD_FAILED', 'The embedded experience failed to load.'));\n this.bridge = new BridgeController(\n this.overlay.iframe.element,\n runtimeOriginFromIframeUrl(iframeUrl),\n () => copyContext(this.context),\n () => sessionId,\n () => this.restartExpiredSession(this.bridge),\n );\n this.bridge.start();\n this.overlay.mount();\n this.scroll.lock();\n this.focus.moveTo(this.overlay.closeButton);\n this.events.emit('opened', undefined);\n } catch (cause) {\n this.bridge?.destroy();\n this.bridge = undefined;\n this.overlay?.destroy();\n this.overlay = undefined;\n this.scroll.unlock();\n this.focus.restore();\n throw this.fail('OVERLAY_CREATION_FAILED', 'The YourRoad overlay could not be created.', cause);\n }\n } catch (cause) {\n if (abort.signal.aborted) return;\n if (cause instanceof YourRoadError) throw cause;\n throw this.fail('BOOTSTRAP_FAILED', 'The YourRoad experience could not be started securely.', cause);\n } finally {\n if (this.bootstrapAbort === abort) {\n this.bootstrapAbort = undefined;\n this.opening = undefined;\n }\n }\n }\n\n private restartExpiredSession(bridge: BridgeController | undefined): void {\n if (this.destroyed || bridge === undefined || bridge !== this.bridge || this.restartAbort) return;\n const restartAbort = new AbortController();\n this.restartAbort = restartAbort;\n const operation = this.session.restartExpired(restartAbort.signal);\n if (!operation) { this.restartAbort = undefined; return; }\n void operation.then((sessionId) => {\n if (!this.destroyed && !restartAbort.signal.aborted && this.bridge === bridge) bridge.sendJourneySession(sessionId);\n }).catch(() => { /* The runtime may offer a later explicit retry. */ }).finally(() => {\n if (this.restartAbort === restartAbort) this.restartAbort = undefined;\n });\n }\n\n private assertUsable(): void { if (this.destroyed) throw new YourRoadError('DESTROYED', 'This YourRoad SDK instance has been destroyed.'); }\n private fail(code: ConstructorParameters<typeof YourRoadError>[0], message: string, cause?: unknown): YourRoadError {\n const error = new YourRoadError(code, message, cause === undefined ? undefined : { cause });\n this.events.emit('error', error);\n return error;\n }\n}\n\nexport function createYourRoadClient(config: Readonly<YourRoadInitConfig>): YourRoadClient {\n return new YourRoadClientImpl(config);\n}\n","import { createYourRoadClient, type YourRoadClient } from './client/YourRoadClient';\nimport type { YourRoadInitConfig } from './config/types';\nimport { YourRoadError } from './errors/YourRoadError';\n\nexport type { OpenOptions, YourRoadClient, YourRoadEvents } from './client/YourRoadClient';\nexport type { YourRoadInitConfig, YourRoadSurface } from './config/types';\nexport type { DealerContext, PageContext, VehicleContext, YourRoadContext, YourRoadContextUpdate } from './context/types';\nexport { YourRoadError };\n\nexport class YourRoad {\n static init(config: YourRoadInitConfig): YourRoadClient {\n if (!config || typeof config.partnerKey !== 'string' || config.partnerKey.trim() === '') {\n throw new YourRoadError('INVALID_INITIALISATION', 'partnerKey must be a non-empty string.');\n }\n return createYourRoadClient({ partnerKey: config.partnerKey });\n }\n}\n"],"names":["BOOTSTRAP_ENDPOINT","validateResponse","value","iframeUrl","expiresAt","parsedUrl","requestBootstrap","request","signal","response","defined","item","mergeContext","current","update","next","key","copyContext","context","BRIDGE_VERSION","runtimeOriginFromIframeUrl","url","isPlainObject","prototype","isReadyMessage","isRestartMessage","BridgeController","iframe","trustedRuntimeOrigin","getCurrentContext","getJourneySessionId","onJourneySessionRestart","__publicField","event","iframeWindow","currentContext","sessionId","message","YourRoadError","code","options","EventEmitter","handler","handlers","payload","_a","FocusLifecycle","element","ScrollLock","style","IframeController","source","onError","SDK_Z_INDEX","SDK_STYLES","ensureStyles","existing","OverlayController","onClose","onFrameError","scrim","panel","JOURNEY_SESSION_MARKER_KEY","isUuid","resolveStorage","createSessionMarker","storage","clear","CREATE_ENDPOINT","PROBE_ENDPOINT","isDate","body","createJourneySession","partnerKey","probeJourneySession","SessionController","marker","completion","operation","result","YourRoadClientImpl","config","abort","_b","surface","bootstrap","cause","bridge","restartAbort","error","createYourRoadClient","YourRoad"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/bootstrap/bootstrapClient.ts","../src/context/mergeContext.ts","../src/bridge/protocol.ts","../src/bridge/BridgeController.ts","../src/errors/YourRoadError.ts","../src/events/EventEmitter.ts","../src/lifecycle/focus.ts","../src/lifecycle/scrollLock.ts","../src/iframe/IframeController.ts","../src/overlay/styles.ts","../src/overlay/OverlayController.ts","../src/session/sessionMarker.ts","../src/session/sessionClient.ts","../src/session/SessionController.ts","../src/client/YourRoadClient.ts","../src/index.ts"],"sourcesContent":["import type { YourRoadSurface } from '../config/types';\n\nconst BOOTSTRAP_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/bootstrap-embed-access';\n\ninterface BootstrapRequest {\n partnerKey: string;\n surface: YourRoadSurface;\n}\n\nexport interface BootstrapResult {\n iframeUrl: string;\n expiresAt: string;\n}\n\nfunction validateResponse(value: unknown): BootstrapResult {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('Invalid bootstrap response.');\n const { iframeUrl, expiresAt } = value as Record<string, unknown>;\n if (typeof iframeUrl !== 'string' || iframeUrl.trim() === '') throw new Error('Invalid bootstrap response.');\n let parsedUrl: URL;\n try { parsedUrl = new URL(iframeUrl); } catch { throw new Error('Invalid bootstrap response.'); }\n if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') throw new Error('Invalid bootstrap response.');\n if (typeof expiresAt !== 'string' || expiresAt.trim() === '' || Number.isNaN(Date.parse(expiresAt))) {\n throw new Error('Invalid bootstrap response.');\n }\n return { iframeUrl, expiresAt };\n}\n\nexport async function requestBootstrap(request: BootstrapRequest, signal: AbortSignal): Promise<BootstrapResult> {\n const response = await fetch(BOOTSTRAP_ENDPOINT, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n credentials: 'omit',\n cache: 'no-store',\n signal,\n });\n if (!response.ok) throw new Error('Bootstrap request was unsuccessful.');\n return validateResponse(await response.json());\n}\n","import type { YourRoadContext, YourRoadContextUpdate } from './types';\n\nconst defined = <T extends object>(value: T | undefined): Partial<T> =>\n Object.fromEntries(Object.entries(value ?? {}).filter(([, item]) => item !== undefined)) as Partial<T>;\n\n/** Merges known context sections. Explicit `undefined` values are ignored. */\nexport function mergeContext(current: YourRoadContext, update: YourRoadContextUpdate): YourRoadContext {\n const next: YourRoadContext = { ...current, ...defined(update) };\n for (const key of ['vehicle', 'dealer', 'page'] as const) {\n if (update[key] !== undefined) next[key] = { ...current[key], ...defined(update[key]) };\n }\n return next;\n}\n\nexport const copyContext = (context?: YourRoadContext): YourRoadContext => mergeContext({}, context ?? {});\n","import type { YourRoadContext } from '../context/types';\n\nexport const BRIDGE_VERSION = 1 as const;\n\nexport type BridgeMessage<T = unknown> = {\n source: 'yourroad.sdk' | 'yourroad.embed';\n version: typeof BRIDGE_VERSION;\n type: string;\n requestId?: string;\n payload?: T;\n};\n\nexport type SdkBridgeMessage =\n | BridgeMessage & { source: 'yourroad.sdk'; type: 'ack' }\n | BridgeMessage<YourRoadContext> & { source: 'yourroad.sdk'; type: 'context' | 'context_updated'; payload: YourRoadContext }\n | BridgeMessage<{ sessionId: string }> & { source: 'yourroad.sdk'; type: 'journey_session'; payload: { sessionId: string } };\n","import { copyContext } from '../context/mergeContext';\nimport type { YourRoadContext } from '../context/types';\nimport { BRIDGE_VERSION, type SdkBridgeMessage } from './protocol';\n\nexport function runtimeOriginFromIframeUrl(iframeUrl: string): string {\n const url = new URL(iframeUrl);\n if (url.protocol !== 'https:' && url.protocol !== 'http:') throw new TypeError('The iframe URL must use HTTP(S).');\n return url.origin;\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst isReadyMessage = (value: unknown): boolean => {\n if (!isPlainObject(value)) return false;\n return value.source === 'yourroad.embed'\n && value.version === BRIDGE_VERSION\n && value.type === 'ready'\n && value.payload === undefined\n && (value.requestId === undefined || typeof value.requestId === 'string');\n};\n\nconst isRestartMessage = (value: unknown): boolean => isPlainObject(value)\n && Object.keys(value).length === 3\n && value.source === 'yourroad.embed'\n && value.version === BRIDGE_VERSION\n && value.type === 'journey_session_restart';\n\nexport class BridgeController {\n private ready = false;\n private started = false;\n\n constructor(\n private readonly iframe: HTMLIFrameElement,\n private readonly trustedRuntimeOrigin: string,\n private readonly getCurrentContext: () => YourRoadContext,\n private readonly getJourneySessionId: () => string,\n private readonly onJourneySessionRestart: () => void,\n ) {}\n\n start(): void {\n if (this.started) return;\n window.addEventListener('message', this.handleMessage);\n this.started = true;\n }\n\n contextUpdated(currentContext: YourRoadContext): void {\n if (!this.ready) return;\n this.post({\n source: 'yourroad.sdk',\n version: BRIDGE_VERSION,\n type: 'context_updated',\n payload: copyContext(currentContext),\n });\n }\n\n destroy(): void {\n if (this.started) window.removeEventListener('message', this.handleMessage);\n this.started = false;\n this.ready = false;\n }\n\n private readonly handleMessage = (event: MessageEvent): void => {\n if (event.origin !== this.trustedRuntimeOrigin) return;\n const iframeWindow = this.iframe.contentWindow;\n if (iframeWindow === null || event.source !== iframeWindow) return;\n if (this.ready) {\n if (isRestartMessage(event.data)) this.onJourneySessionRestart();\n return;\n }\n if (!isReadyMessage(event.data)) return;\n this.ready = true;\n this.post({ source: 'yourroad.sdk', version: BRIDGE_VERSION, type: 'ack' });\n this.post({\n source: 'yourroad.sdk',\n version: BRIDGE_VERSION,\n type: 'context',\n payload: copyContext(this.getCurrentContext()),\n });\n this.sendJourneySession(this.getJourneySessionId());\n };\n\n sendJourneySession(sessionId: string): void {\n if (!this.ready) return;\n this.post({ source: 'yourroad.sdk', version: BRIDGE_VERSION, type: 'journey_session', payload: { sessionId } });\n }\n\n private post(message: SdkBridgeMessage): void {\n const iframeWindow = this.iframe.contentWindow;\n if (iframeWindow === null) return;\n try {\n iframeWindow.postMessage(message, this.trustedRuntimeOrigin);\n } catch {\n // The iframe may be removed concurrently; bridge delivery is best-effort.\n }\n }\n}\n","export type YourRoadErrorCode = 'INVALID_INITIALISATION' | 'INVALID_SURFACE' | 'DESTROYED' | 'BOOTSTRAP_FAILED' | 'OVERLAY_CREATION_FAILED' | 'IFRAME_LOAD_FAILED';\n\nexport class YourRoadError extends Error {\n readonly name = 'YourRoadError';\n constructor(public readonly code: YourRoadErrorCode, message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n","export type Handler<T> = (payload: T) => void;\n\nexport class EventEmitter<Events extends object> {\n private listeners = new Map<keyof Events, Set<Handler<never>>>();\n\n on<K extends keyof Events>(event: K, handler: Handler<Events[K]>): () => void {\n const handlers = this.listeners.get(event) ?? new Set();\n handlers.add(handler as Handler<never>);\n this.listeners.set(event, handlers);\n return () => handlers.delete(handler as Handler<never>);\n }\n\n emit<K extends keyof Events>(event: K, payload: Events[K]): void {\n this.listeners.get(event)?.forEach((handler) => handler(payload as never));\n }\n\n clear(): void { this.listeners.clear(); }\n}\n","export class FocusLifecycle {\n private previous: HTMLElement | null = null;\n capture(): void { this.previous = document.activeElement instanceof HTMLElement ? document.activeElement : null; }\n moveTo(element: HTMLElement): void { element.focus(); }\n restore(): void {\n if (this.previous?.isConnected) this.previous.focus();\n this.previous = null;\n }\n}\n","interface SavedStyles { position: string; top: string; left: string; right: string; width: string; overflow: string }\n\nexport class ScrollLock {\n private saved?: SavedStyles;\n private scrollX = 0;\n private scrollY = 0;\n\n lock(): void {\n if (this.saved) return;\n const style = document.body.style;\n this.saved = { position: style.position, top: style.top, left: style.left, right: style.right, width: style.width, overflow: style.overflow };\n this.scrollX = window.scrollX;\n this.scrollY = window.scrollY;\n Object.assign(style, { position: 'fixed', top: `-${this.scrollY}px`, left: `-${this.scrollX}px`, right: '0', width: '100%', overflow: 'hidden' });\n }\n\n unlock(): void {\n if (!this.saved) return;\n Object.assign(document.body.style, this.saved);\n this.saved = undefined;\n window.scrollTo(this.scrollX, this.scrollY);\n }\n}\n","export class IframeController {\n readonly element: HTMLIFrameElement;\n constructor(source: string, onError: () => void) {\n this.element = document.createElement('iframe');\n this.element.dataset.yourroadFrame = '';\n this.element.title = 'YourRoad pre-approval';\n this.element.src = source;\n this.element.addEventListener('error', onError, { once: true });\n }\n destroy(): void { this.element.remove(); }\n}\n","export const SDK_Z_INDEX = 2147483000;\n\nexport const SDK_STYLES = `\n[data-yourroad-overlay-root] { all: initial; position: fixed; inset: 0; z-index: ${SDK_Z_INDEX}; display: block; font-family: system-ui, sans-serif; color: #111; }\n[data-yourroad-scrim] { all: initial; position: absolute; inset: 0; display: block; background: rgba(0, 0, 0, .55); }\n[data-yourroad-panel] { all: initial; box-sizing: border-box; position: absolute; inset-block: 0; inset-inline-end: 0; display: flex; flex-direction: column; width: min(520px, 92vw); height: 100vh; height: 100dvh; padding-block-start: calc(max(12px, env(safe-area-inset-top)) + 56px); overflow: hidden; border-radius: 24px 0 0 24px; background: #fff; box-shadow: -8px 0 30px rgba(0,0,0,.2); }\n[data-yourroad-close] { all: unset; box-sizing: border-box; position: absolute; z-index: 1; inset-block-start: max(12px, env(safe-area-inset-top)); inset-inline-end: max(12px, env(safe-area-inset-right)); width: 44px; height: 44px; display: grid; place-items: center; border-radius: 999px; background: #fff; color: #111; box-shadow: 0 1px 8px rgba(0,0,0,.25); cursor: pointer; font: 28px/1 system-ui, sans-serif; }\n[data-yourroad-close]:focus-visible { outline: 3px solid #1769e0; outline-offset: 2px; }\n[data-yourroad-frame] { all: initial; box-sizing: border-box; display: block; flex: 1 1 auto; min-height: 0; width: 100%; border: 0; background: #fff; }\n@media (max-width: 600px) { [data-yourroad-panel] { inset-block-start: auto; inset-block-end: 0; inset-inline-end: 0; width: 100vw; max-width: none; height: 92vh; height: 92dvh; border-radius: 24px 24px 0 0; box-shadow: 0 -8px 30px rgba(0,0,0,.2); } }\n`;\n\nexport function ensureStyles(): HTMLStyleElement {\n const existing = document.head.querySelector<HTMLStyleElement>('style[data-yourroad-sdk]');\n if (existing) return existing;\n const style = document.createElement('style');\n style.dataset.yourroadSdk = '';\n style.textContent = SDK_STYLES;\n document.head.append(style);\n return style;\n}\n","import { IframeController } from '../iframe/IframeController';\nimport { ensureStyles } from './styles';\n\nexport class OverlayController {\n readonly root: HTMLDivElement;\n readonly closeButton: HTMLButtonElement;\n readonly iframe: IframeController;\n private readonly abort = new AbortController();\n\n constructor(source: string, onClose: () => void, onFrameError: () => void) {\n ensureStyles();\n this.root = document.createElement('div');\n this.root.dataset.yourroadOverlayRoot = '';\n this.root.setAttribute('role', 'dialog');\n this.root.setAttribute('aria-modal', 'true');\n this.root.setAttribute('aria-label', 'YourRoad pre-approval');\n const scrim = document.createElement('div');\n scrim.dataset.yourroadScrim = '';\n const panel = document.createElement('div');\n panel.dataset.yourroadPanel = '';\n this.closeButton = document.createElement('button');\n this.closeButton.type = 'button';\n this.closeButton.dataset.yourroadClose = '';\n this.closeButton.setAttribute('aria-label', 'Close YourRoad');\n const closeIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n closeIcon.setAttribute('viewBox', '0 0 24 24');\n closeIcon.setAttribute('width', '24');\n closeIcon.setAttribute('height', '24');\n closeIcon.setAttribute('fill', 'none');\n closeIcon.setAttribute('stroke', 'currentColor');\n closeIcon.setAttribute('stroke-width', '2');\n closeIcon.setAttribute('stroke-linecap', 'round');\n closeIcon.setAttribute('aria-hidden', 'true');\n const closeIconPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n closeIconPath.setAttribute('d', 'M6 6l12 12M18 6L6 18');\n closeIcon.append(closeIconPath);\n this.closeButton.append(closeIcon);\n this.iframe = new IframeController(source, onFrameError);\n panel.append(this.closeButton, this.iframe.element);\n this.root.append(scrim, panel);\n const signal = this.abort.signal;\n scrim.addEventListener('click', onClose, { signal });\n this.closeButton.addEventListener('click', onClose, { signal });\n document.addEventListener('keydown', (event) => { if (event.key === 'Escape') onClose(); }, { signal });\n }\n\n mount(): void { document.body.append(this.root); }\n destroy(): void {\n this.abort.abort();\n this.iframe.destroy();\n this.root.remove();\n if (!document.querySelector('[data-yourroad-overlay-root]')) {\n document.head.querySelector('style[data-yourroad-sdk]')?.remove();\n }\n }\n}\n","export const JOURNEY_SESSION_MARKER_KEY = 'yr_journey_session_pre_approval_v1';\n\nexport const isUuid = (value: unknown): value is string =>\n typeof value === 'string'\n && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);\n\nexport interface SessionMarker {\n read(): string | undefined;\n write(sessionId: string): void;\n clear(): void;\n}\n\ntype MarkerStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>;\n\nfunction resolveStorage(): MarkerStorage | undefined {\n try { return globalThis.localStorage; } catch { return undefined; }\n}\n\nexport function createSessionMarker(storage: MarkerStorage | undefined = resolveStorage()): SessionMarker {\n const clear = (): void => {\n try { storage?.removeItem(JOURNEY_SESSION_MARKER_KEY); } catch { /* Storage is optional. */ }\n };\n return {\n read() {\n let value: string | null;\n try { value = storage?.getItem(JOURNEY_SESSION_MARKER_KEY) ?? null; } catch { return undefined; }\n if (value === null) return undefined;\n if (!isUuid(value)) { clear(); return undefined; }\n return value;\n },\n write(sessionId) {\n if (!isUuid(sessionId)) return;\n try { storage?.setItem(JOURNEY_SESSION_MARKER_KEY, sessionId); } catch { /* Keep the in-memory session usable. */ }\n },\n clear,\n };\n}\n","import { isUuid } from './sessionMarker';\n\nconst CREATE_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/create-embed-journey-session';\nconst PROBE_ENDPOINT = 'https://tsajlkcfcvjqqjxfigbw.supabase.co/functions/v1/probe-embed-journey-session';\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\nconst isDate = (value: unknown): value is string => typeof value === 'string' && value.trim() !== '' && !Number.isNaN(Date.parse(value));\nconst options = (body: object, signal?: AbortSignal): RequestInit => ({\n method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),\n credentials: 'omit', cache: 'no-store', signal,\n});\n\nexport async function createJourneySession(partnerKey: string, signal?: AbortSignal): Promise<string> {\n const response = await fetch(CREATE_ENDPOINT, options({ partnerKey, surface: 'pre-approval' }, signal));\n if (response.status !== 201) throw new Error('Journey session creation was unsuccessful.');\n const value: unknown = await response.json();\n if (!isPlainObject(value) || !isUuid(value.sessionId) || !isDate(value.expiresAt)) throw new Error('Invalid journey session response.');\n return value.sessionId;\n}\n\nexport type ProbeResult = { status: 'resumable'; sessionId: string } | { status: 'expired' } | { status: 'invalid' };\n\nexport async function probeJourneySession(partnerKey: string, sessionId: string): Promise<ProbeResult> {\n const response = await fetch(PROBE_ENDPOINT, options({ partnerKey, surface: 'pre-approval', sessionId }));\n const value: unknown = await response.json();\n if (!isPlainObject(value)) throw new Error('Invalid journey session probe response.');\n if (response.status === 200 && value.status === 'resumable' && value.sessionId === sessionId && isDate(value.expiresAt)) {\n return { status: 'resumable', sessionId };\n }\n if (response.status === 410 && value.status === 'expired' && value.code === 'SESSION_EXPIRED') return { status: 'expired' };\n if (response.status === 404 && value.status === 'invalid' && value.code === 'SESSION_INVALID') return { status: 'invalid' };\n throw new Error('Journey session probe was unsuccessful.');\n}\n","import { createJourneySession, probeJourneySession } from './sessionClient';\nimport { createSessionMarker, type SessionMarker } from './sessionMarker';\n\ntype State =\n | { kind: 'cold' }\n | { kind: 'probing'; completion: Promise<void> }\n | { kind: 'active'; sessionId: string }\n | { kind: 'expired'; sessionId: string }\n | { kind: 'probe_failed' };\n\nexport class SessionController {\n private state: State = { kind: 'cold' };\n private restart?: Promise<string>;\n\n constructor(private readonly partnerKey: string, private readonly marker: SessionMarker = createSessionMarker()) {\n const sessionId = marker.read();\n if (!sessionId) return;\n const completion = this.probe(sessionId);\n this.state = { kind: 'probing', completion };\n }\n\n async resolveForOpen(signal: AbortSignal): Promise<string> {\n if (this.state.kind === 'probing') await this.state.completion;\n if (this.state.kind === 'probe_failed') throw new Error('Journey session validity could not be established.');\n if (this.state.kind === 'active' || this.state.kind === 'expired') return this.state.sessionId;\n const sessionId = await createJourneySession(this.partnerKey, signal);\n this.marker.write(sessionId);\n this.state = { kind: 'active', sessionId };\n return sessionId;\n }\n\n restartExpired(signal: AbortSignal): Promise<string> | undefined {\n if (this.state.kind !== 'expired') return undefined;\n if (this.restart) return this.restart;\n const operation = createJourneySession(this.partnerKey, signal).then((sessionId) => {\n this.marker.write(sessionId);\n this.state = { kind: 'active', sessionId };\n return sessionId;\n }).finally(() => { if (this.restart === operation) this.restart = undefined; });\n this.restart = operation;\n return operation;\n }\n\n private async probe(sessionId: string): Promise<void> {\n try {\n const result = await probeJourneySession(this.partnerKey, sessionId);\n if (result.status === 'resumable') this.state = { kind: 'active', sessionId };\n else if (result.status === 'expired') { this.marker.clear(); this.state = { kind: 'expired', sessionId }; }\n else { this.marker.clear(); this.state = { kind: 'cold' }; }\n } catch { this.state = { kind: 'probe_failed' }; }\n }\n}\n","import type { YourRoadInitConfig, YourRoadSurface } from '../config/types';\nimport { requestBootstrap } from '../bootstrap/bootstrapClient';\nimport { BridgeController, runtimeOriginFromIframeUrl } from '../bridge/BridgeController';\nimport { copyContext, mergeContext } from '../context/mergeContext';\nimport type { YourRoadContext, YourRoadContextUpdate } from '../context/types';\nimport { YourRoadError } from '../errors/YourRoadError';\nimport { EventEmitter } from '../events/EventEmitter';\nimport { FocusLifecycle } from '../lifecycle/focus';\nimport { ScrollLock } from '../lifecycle/scrollLock';\nimport { OverlayController } from '../overlay/OverlayController';\nimport { SessionController } from '../session/SessionController';\n\nexport interface OpenOptions { surface: YourRoadSurface; context?: YourRoadContext }\nexport interface YourRoadEvents { opened: undefined; closed: undefined; error: YourRoadError }\n\nexport interface YourRoadClient {\n open(options: OpenOptions): Promise<void>;\n updateContext(update: YourRoadContextUpdate): void;\n close(): void;\n on<K extends keyof YourRoadEvents>(event: K, handler: (payload: YourRoadEvents[K]) => void): () => void;\n destroy(): void;\n}\n\nclass YourRoadClientImpl implements YourRoadClient {\n private readonly events = new EventEmitter<YourRoadEvents>();\n private readonly scroll = new ScrollLock();\n private readonly focus = new FocusLifecycle();\n private overlay?: OverlayController;\n private bridge?: BridgeController;\n private context: YourRoadContext = {};\n private destroyed = false;\n private opening?: Promise<void>;\n private bootstrapAbort?: AbortController;\n private restartAbort?: AbortController;\n private readonly session: SessionController;\n\n constructor(private readonly config: Readonly<YourRoadInitConfig>) {\n this.session = new SessionController(config.partnerKey);\n }\n\n async open(options: OpenOptions): Promise<void> {\n this.assertUsable();\n if (!options || options.surface !== 'pre-approval') throw this.fail('INVALID_SURFACE', 'The only supported surface is \"pre-approval\".');\n if (this.overlay) return;\n if (this.opening) return this.opening;\n this.context = copyContext(options.context);\n const abort = new AbortController();\n this.bootstrapAbort = abort;\n const operation = this.performOpen(options.surface, abort);\n this.opening = operation;\n return operation;\n }\n\n updateContext(update: YourRoadContextUpdate): void {\n this.assertUsable();\n this.context = mergeContext(this.context, update);\n this.bridge?.contextUpdated(this.context);\n }\n\n close(): void {\n this.assertUsable();\n if (this.bootstrapAbort) {\n this.bootstrapAbort.abort();\n this.bootstrapAbort = undefined;\n this.opening = undefined;\n }\n this.restartAbort?.abort();\n this.restartAbort = undefined;\n if (!this.overlay) return;\n this.bridge?.destroy();\n this.bridge = undefined;\n this.overlay.destroy();\n this.overlay = undefined;\n this.scroll.unlock();\n this.focus.restore();\n this.events.emit('closed', undefined);\n }\n\n on<K extends keyof YourRoadEvents>(event: K, handler: (payload: YourRoadEvents[K]) => void): () => void {\n this.assertUsable();\n return this.events.on(event, handler);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.close();\n this.events.clear();\n this.context = {};\n this.destroyed = true;\n }\n\n private async performOpen(surface: YourRoadSurface, abort: AbortController): Promise<void> {\n try {\n const [bootstrap, sessionId] = await Promise.all([\n requestBootstrap({ partnerKey: this.config.partnerKey, surface }, abort.signal),\n this.session.resolveForOpen(abort.signal),\n ]);\n const { iframeUrl } = bootstrap;\n if (abort.signal.aborted || this.destroyed || this.bootstrapAbort !== abort) return;\n this.focus.capture();\n try {\n this.overlay = new OverlayController(iframeUrl, () => this.close(), () => this.fail('IFRAME_LOAD_FAILED', 'The embedded experience failed to load.'));\n this.bridge = new BridgeController(\n this.overlay.iframe.element,\n runtimeOriginFromIframeUrl(iframeUrl),\n () => copyContext(this.context),\n () => sessionId,\n () => this.restartExpiredSession(this.bridge),\n );\n this.bridge.start();\n this.overlay.mount();\n this.scroll.lock();\n this.focus.moveTo(this.overlay.closeButton);\n this.events.emit('opened', undefined);\n } catch (cause) {\n this.bridge?.destroy();\n this.bridge = undefined;\n this.overlay?.destroy();\n this.overlay = undefined;\n this.scroll.unlock();\n this.focus.restore();\n throw this.fail('OVERLAY_CREATION_FAILED', 'The YourRoad overlay could not be created.', cause);\n }\n } catch (cause) {\n if (abort.signal.aborted) return;\n if (cause instanceof YourRoadError) throw cause;\n throw this.fail('BOOTSTRAP_FAILED', 'The YourRoad experience could not be started securely.', cause);\n } finally {\n if (this.bootstrapAbort === abort) {\n this.bootstrapAbort = undefined;\n this.opening = undefined;\n }\n }\n }\n\n private restartExpiredSession(bridge: BridgeController | undefined): void {\n if (this.destroyed || bridge === undefined || bridge !== this.bridge || this.restartAbort) return;\n const restartAbort = new AbortController();\n this.restartAbort = restartAbort;\n const operation = this.session.restartExpired(restartAbort.signal);\n if (!operation) { this.restartAbort = undefined; return; }\n void operation.then((sessionId) => {\n if (!this.destroyed && !restartAbort.signal.aborted && this.bridge === bridge) bridge.sendJourneySession(sessionId);\n }).catch(() => { /* The runtime may offer a later explicit retry. */ }).finally(() => {\n if (this.restartAbort === restartAbort) this.restartAbort = undefined;\n });\n }\n\n private assertUsable(): void { if (this.destroyed) throw new YourRoadError('DESTROYED', 'This YourRoad SDK instance has been destroyed.'); }\n private fail(code: ConstructorParameters<typeof YourRoadError>[0], message: string, cause?: unknown): YourRoadError {\n const error = new YourRoadError(code, message, cause === undefined ? undefined : { cause });\n this.events.emit('error', error);\n return error;\n }\n}\n\nexport function createYourRoadClient(config: Readonly<YourRoadInitConfig>): YourRoadClient {\n return new YourRoadClientImpl(config);\n}\n","import { createYourRoadClient, type YourRoadClient } from './client/YourRoadClient';\nimport type { YourRoadInitConfig } from './config/types';\nimport { YourRoadError } from './errors/YourRoadError';\n\nexport type { OpenOptions, YourRoadClient, YourRoadEvents } from './client/YourRoadClient';\nexport type { YourRoadInitConfig, YourRoadSurface } from './config/types';\nexport type { DealerContext, PageContext, VehicleContext, YourRoadContext, YourRoadContextUpdate } from './context/types';\nexport { YourRoadError };\n\nexport class YourRoad {\n static init(config: YourRoadInitConfig): YourRoadClient {\n if (!config || typeof config.partnerKey !== 'string' || config.partnerKey.trim() === '') {\n throw new YourRoadError('INVALID_INITIALISATION', 'partnerKey must be a non-empty string.');\n }\n return createYourRoadClient({ partnerKey: config.partnerKey });\n }\n}\n"],"names":["BOOTSTRAP_ENDPOINT","validateResponse","value","iframeUrl","expiresAt","parsedUrl","requestBootstrap","request","signal","response","defined","item","mergeContext","current","update","next","key","copyContext","context","BRIDGE_VERSION","runtimeOriginFromIframeUrl","url","isPlainObject","prototype","isReadyMessage","isRestartMessage","BridgeController","iframe","trustedRuntimeOrigin","getCurrentContext","getJourneySessionId","onJourneySessionRestart","__publicField","event","iframeWindow","currentContext","sessionId","message","YourRoadError","code","options","EventEmitter","handler","handlers","payload","_a","FocusLifecycle","element","ScrollLock","style","IframeController","source","onError","SDK_Z_INDEX","SDK_STYLES","ensureStyles","existing","OverlayController","onClose","onFrameError","scrim","panel","closeIcon","closeIconPath","JOURNEY_SESSION_MARKER_KEY","isUuid","resolveStorage","createSessionMarker","storage","clear","CREATE_ENDPOINT","PROBE_ENDPOINT","isDate","body","createJourneySession","partnerKey","probeJourneySession","SessionController","marker","completion","operation","result","YourRoadClientImpl","config","abort","_b","surface","bootstrap","cause","bridge","restartAbort","error","createYourRoadClient","YourRoad"],"mappings":"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"}
|