@fanfare-io/fanfare-sdk-core 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/auth.module.d.ts +9 -1
- package/dist/auth/auth.module.js +1 -1
- package/dist/core/client.js +2 -2
- package/dist/storefront.d.ts +0 -36
- package/dist/storefront.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -40,6 +40,10 @@ export declare class AuthenticationModule implements AuthModule {
|
|
|
40
40
|
* Logout current session
|
|
41
41
|
*/
|
|
42
42
|
logout(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Clear all local auth state: store, access-token header, and beacon-token header.
|
|
45
|
+
*/
|
|
46
|
+
private clearAuthState;
|
|
43
47
|
/**
|
|
44
48
|
* Get current session
|
|
45
49
|
*/
|
|
@@ -57,7 +61,11 @@ export declare class AuthenticationModule implements AuthModule {
|
|
|
57
61
|
*/
|
|
58
62
|
private handleUnauthorized;
|
|
59
63
|
/**
|
|
60
|
-
* Schedule token refresh
|
|
64
|
+
* Schedule a proactive token refresh ahead of expiry so an active session
|
|
65
|
+
* rotates before a request hits a 401. Scheduled only while a refresh token is
|
|
66
|
+
* held in memory: after a reload the in-memory token is gone, so there is
|
|
67
|
+
* nothing to present and refresh is driven reactively (a 401 drives
|
|
68
|
+
* re-authentication) rather than by a timer that could only clear auth state.
|
|
61
69
|
*/
|
|
62
70
|
private scheduleTokenRefresh;
|
|
63
71
|
/**
|
package/dist/auth/auth.module.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getLogger as e}from"../core/logger.js";import{getEventBus as t}from"../state/events.js";import{getSDKStore as s}from"../state/store.js";class r{constructor(r,o){this.logger=e(),this.store=s(),this.events=t(),this.http=r,this.beaconHttp=o,this.http.updateConfig({...this.http.getConfig(),onUnauthorized:async()=>{await this.handleUnauthorized()}});const i=this.store.beaconToken;i&&this.beaconHttp.updateConfig({...this.beaconHttp.getConfig(),headers:{...this.beaconHttp.getConfig().headers,"X-Beacon-Token":i}})}check(){const e=this.store.session;return e?{isAuthenticated:!0,session:e,isGuest:"guest"===e.type}:{isAuthenticated:!1}}async guest(){try{this.logger.info("Creating guest session");const{session:e,accessToken:t,refreshToken:s,beaconToken:r}=await this.http.post("/auth/guest");return this.store.setSession(e),this.store.setRefreshToken(s??null),this.store.setBeaconToken(r),this.http.updateConfig({...this.http.getConfig(),headers:{...this.http.getConfig().headers,Authorization:`Bearer ${t}`}}),this.beaconHttp.updateConfig({...this.beaconHttp.getConfig(),headers:{...this.beaconHttp.getConfig().headers,"X-Beacon-Token":r}}),this.scheduleTokenRefresh(e.expiresAt),this.events.emit("auth:authenticated",{session:e,isNew:!0}),e}catch(e){const t=e instanceof Error?e:new Error(String(e));throw this.logger.error("Failed to create guest session",t),this.events.emit("auth:error",{error:t,context:"guest"}),t}}async requestOtp(e){try{this.logger.info("Requesting OTP");const t="string"==typeof e?{email:e}:e;await this.http.post("/auth/otp/request",t)}catch(t){const e=t instanceof Error?t:new Error(String(t));throw this.logger.error("Failed to request OTP",e),this.events.emit("auth:error",{error:e,context:"requestOtp"}),e}}async verifyOtp(e){try{const t=e;this.logger.info("Verifying OTP",{email:t.email,phone:t.phone});const{session:s,accessToken:r,refreshToken:o,beaconToken:i}=await this.http.post("/auth/otp/verify",t);return this.store.setSession(s),this.store.setRefreshToken(o??null),this.store.setBeaconToken(i),this.http.updateConfig({...this.http.getConfig(),headers:{...this.http.getConfig().headers,Authorization:`Bearer ${r}`}}),this.beaconHttp.updateConfig({...this.beaconHttp.getConfig(),headers:{...this.beaconHttp.getConfig().headers,"X-Beacon-Token":i}}),this.scheduleTokenRefresh(s.expiresAt),this.events.emit("auth:authenticated",{session:s,isNew:!0}),s}catch(t){const e=t instanceof Error?t:new Error(String(t));throw this.logger.error("Failed to verify OTP",e),this.events.emit("auth:error",{error:e,context:"verifyOtp"}),e}}async exchangeExternal(e){try{const t="string"==typeof e?{exchangeCode:e}:e;this.logger.info("Exchanging external auth code");const{session:s,accessToken:r,refreshToken:o,beaconToken:i}=await this.http.post("/auth/external/exchange",t);return this.store.setSession(s),this.store.setRefreshToken(o??null),this.store.setBeaconToken(i),this.http.updateConfig({...this.http.getConfig(),headers:{...this.http.getConfig().headers,Authorization:`Bearer ${r}`}}),this.beaconHttp.updateConfig({...this.beaconHttp.getConfig(),headers:{...this.beaconHttp.getConfig().headers,"X-Beacon-Token":i}}),this.scheduleTokenRefresh(s.expiresAt),this.events.emit("auth:authenticated",{session:s,isNew:!0}),s}catch(t){const e=t instanceof Error?t:new Error(String(t));throw this.logger.error("Failed to exchange external auth code",e),this.events.emit("auth:error",{error:e,context:"exchangeExternal"}),e}}async login(e){await this.requestOtp({email:e.email})}async logout(){try{if(!this.store.session)return;this.
|
|
1
|
+
import{getLogger as e}from"../core/logger.js";import{getEventBus as t}from"../state/events.js";import{getSDKStore as s}from"../state/store.js";class r{constructor(r,o){this.logger=e(),this.store=s(),this.events=t(),this.http=r,this.beaconHttp=o,this.http.updateConfig({...this.http.getConfig(),onUnauthorized:async()=>{await this.handleUnauthorized()}});const i=this.store.beaconToken;i&&this.beaconHttp.updateConfig({...this.beaconHttp.getConfig(),headers:{...this.beaconHttp.getConfig().headers,"X-Beacon-Token":i}})}check(){const e=this.store.session;return e?{isAuthenticated:!0,session:e,isGuest:"guest"===e.type}:{isAuthenticated:!1}}async guest(){try{this.logger.info("Creating guest session");const{session:e,accessToken:t,refreshToken:s,beaconToken:r}=await this.http.post("/auth/guest");return this.store.setSession(e),this.store.setRefreshToken(s??null),this.store.setBeaconToken(r),this.http.updateConfig({...this.http.getConfig(),headers:{...this.http.getConfig().headers,Authorization:`Bearer ${t}`}}),this.beaconHttp.updateConfig({...this.beaconHttp.getConfig(),headers:{...this.beaconHttp.getConfig().headers,"X-Beacon-Token":r}}),this.scheduleTokenRefresh(e.expiresAt),this.events.emit("auth:authenticated",{session:e,isNew:!0}),e}catch(e){const t=e instanceof Error?e:new Error(String(e));throw this.logger.error("Failed to create guest session",t),this.events.emit("auth:error",{error:t,context:"guest"}),t}}async requestOtp(e){try{this.logger.info("Requesting OTP");const t="string"==typeof e?{email:e}:e;await this.http.post("/auth/otp/request",t)}catch(t){const e=t instanceof Error?t:new Error(String(t));throw this.logger.error("Failed to request OTP",e),this.events.emit("auth:error",{error:e,context:"requestOtp"}),e}}async verifyOtp(e){try{const t=e;this.logger.info("Verifying OTP",{email:t.email,phone:t.phone});const{session:s,accessToken:r,refreshToken:o,beaconToken:i}=await this.http.post("/auth/otp/verify",t);return this.store.setSession(s),this.store.setRefreshToken(o??null),this.store.setBeaconToken(i),this.http.updateConfig({...this.http.getConfig(),headers:{...this.http.getConfig().headers,Authorization:`Bearer ${r}`}}),this.beaconHttp.updateConfig({...this.beaconHttp.getConfig(),headers:{...this.beaconHttp.getConfig().headers,"X-Beacon-Token":i}}),this.scheduleTokenRefresh(s.expiresAt),this.events.emit("auth:authenticated",{session:s,isNew:!0}),s}catch(t){const e=t instanceof Error?t:new Error(String(t));throw this.logger.error("Failed to verify OTP",e),this.events.emit("auth:error",{error:e,context:"verifyOtp"}),e}}async exchangeExternal(e){try{const t="string"==typeof e?{exchangeCode:e}:e;this.logger.info("Exchanging external auth code");const{session:s,accessToken:r,refreshToken:o,beaconToken:i}=await this.http.post("/auth/external/exchange",t);return this.store.setSession(s),this.store.setRefreshToken(o??null),this.store.setBeaconToken(i),this.http.updateConfig({...this.http.getConfig(),headers:{...this.http.getConfig().headers,Authorization:`Bearer ${r}`}}),this.beaconHttp.updateConfig({...this.beaconHttp.getConfig(),headers:{...this.beaconHttp.getConfig().headers,"X-Beacon-Token":i}}),this.scheduleTokenRefresh(s.expiresAt),this.events.emit("auth:authenticated",{session:s,isNew:!0}),s}catch(t){const e=t instanceof Error?t:new Error(String(t));throw this.logger.error("Failed to exchange external auth code",e),this.events.emit("auth:error",{error:e,context:"exchangeExternal"}),e}}async login(e){await this.requestOtp({email:e.email})}async logout(){try{if(!this.store.session)return;const e=this.store.refreshToken;await this.http.post("/auth/logout",e?{refreshToken:e}:{},{skipUnauthorizedHandler:!0}).catch(()=>{}),this.clearAuthState(),this.events.emit("auth:logout",{reason:"user"})}catch(e){const t=e instanceof Error?e:new Error(String(e));throw this.logger.error("Error during logout",t),this.store.clearAll(),t}}clearAuthState(){this.cancelTokenRefresh(),this.store.clearAll();const e=this.http.getConfig(),{Authorization:t,...s}=e.headers||{};this.http.updateConfig({...e,headers:s});const r=this.beaconHttp.getConfig(),{"X-Beacon-Token":o,...i}=r.headers||{};this.beaconHttp.updateConfig({...r,headers:i})}getSession(){return this.store.session}async refresh(){return this.refreshPromise?(this.logger.debug("Refresh already in progress, returning existing promise"),this.refreshPromise):(this.refreshPromise=this._doRefresh().finally(()=>{this.refreshPromise=void 0}),this.refreshPromise)}async _doRefresh(){const e=this.store.refreshToken;if(!e)throw this.logger.info("No refresh token available; clearing auth state"),this.clearAuthState(),this.events.emit("auth:logout",{reason:"expired"}),new Error("No refresh token available");try{this.logger.info("Refreshing access token");const{accessToken:t,refreshToken:s,beaconToken:r}=await this.http.post("/auth/refresh",{refreshToken:e});this.store.setRefreshToken(s??null),this.store.setBeaconToken(r),this.http.updateConfig({...this.http.getConfig(),headers:{...this.http.getConfig().headers,Authorization:`Bearer ${t}`}}),this.beaconHttp.updateConfig({...this.beaconHttp.getConfig(),headers:{...this.beaconHttp.getConfig().headers,"X-Beacon-Token":r}});const o=this.store.session;o&&o.expiresAt&&this.scheduleTokenRefresh(o.expiresAt),this.store.session&&this.events.emit("auth:refreshed",{session:this.store.session})}catch(t){const e=t instanceof Error?t:new Error(String(t));throw this.logger.error("Failed to refresh token",e),await this.logout(),e}}async handleUnauthorized(){this.logger.warn("Received 401, attempting to refresh token");try{await this.refresh()}catch(e){const t=e instanceof Error?e:new Error(String(e));this.logger.error("Failed to handle 401",t),this.events.emit("auth:error",{error:new Error("Session expired"),context:"unauthorized"})}}scheduleTokenRefresh(e){if(this.cancelTokenRefresh(),!this.store.refreshToken)return;const t=Date.now(),s=new Date(e).getTime()-3e5,r=s-t;r<=0?this.refresh().catch(e=>{this.logger.error("Failed to refresh expired token",e)}):(this.logger.debug("Scheduling token refresh",{expiresAt:new Date(e).toISOString(),refreshAt:new Date(s).toISOString(),delayMs:r}),this.refreshTimer=setTimeout(()=>{this.refresh().catch(e=>{this.logger.error("Scheduled token refresh failed",e)})},r))}cancelTokenRefresh(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=void 0,this.logger.debug("Cancelled token refresh timer"))}destroy(){this.cancelTokenRefresh(),this.refreshPromise=void 0}}export{r as AuthenticationModule};
|
package/dist/core/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{AppointmentManagementModule as e}from"../appointments/appointment.module.js";import{AuctionManagementModule as t}from"../auctions/auction.module.js";import{AuthenticationModule as r}from"../auth/auth.module.js";import{BeaconTrackingModule as n}from"../beacon/beacon.module.js";import{ChallengeManagementModule as i}from"../challenges/challenge.module.js";import{Config as o}from"../config/index.js";import{DrawManagementModule as s}from"../draws/draw.module.js";import{ExperienceManagementModule as a}from"../experiences/experience.module.js";import{ExperienceJourney as d}from"../experiences/journey.js";import{QueueManagementModule as l}from"../queues/queue.module.js";import{resolveCapabilityOptions as
|
|
2
|
-
/* @__PURE__ */new Set([...N.keys(),...$.keys(),...Object.keys(J.activeJourneys)])),resumeAll:e=>(async e=>{const t=/* @__PURE__ */new Set;for(const r of Object.keys(J.activeJourneys))L(r),t.add(r);if(!e&&!E.getSession())return[...t];for(const r of await G(e))t.add(r);return[...t]})(e)},Z={track:e=>P.track(e),trackBatch:e=>P.trackBatch(e),flush:()=>P.flush()},Q=(e,t)=>{if(V.has(e.id))A.warn("CDP adapter already registered, skipping",{adapterId:e.id});else{try{e.init(T,t)}catch(r){return void A.error("CDP adapter failed to initialize",{adapterId:e.id,error:r})}V.set(e.id,e),A.info("CDP adapter registered",{adapterId:e.id})}},W=(e,t)=>T.on(e,t),ee=async()=>{A.info("Destroying SDK instance");for(const t of V.values())try{t.destroy()}catch(e){A.error("CDP adapter failed to destroy",{adapterId:t.id,error:e})}V.clear();for(const t of Array.from(N.values()))try{t.destroy()}catch(e){A.error("Journey handle failed to destroy",{error:e})}$.clear(),N.clear(),"destroy"in E&&"function"==typeof E.destroy&&E.destroy(),C.destroy(),R.destroy(),z.destroy(),
|
|
1
|
+
import{AppointmentManagementModule as e}from"../appointments/appointment.module.js";import{AuctionManagementModule as t}from"../auctions/auction.module.js";import{AuthenticationModule as r}from"../auth/auth.module.js";import{BeaconTrackingModule as n}from"../beacon/beacon.module.js";import{ChallengeManagementModule as i}from"../challenges/challenge.module.js";import{Config as o}from"../config/index.js";import{DrawManagementModule as s}from"../draws/draw.module.js";import{ExperienceManagementModule as a}from"../experiences/experience.module.js";import{ExperienceJourney as d}from"../experiences/journey.js";import{QueueManagementModule as l}from"../queues/queue.module.js";import{resolveCapabilityOptions as u}from"../state/capability-token-registry.js";import{getEventBus as c}from"../state/events.js";import{getSDKStore as g}from"../state/store.js";import{CrossTabCoordinator as y}from"../sync/cross-tab-coordinator.js";import{TimedReleaseManagementModule as p}from"../timed-releases/timed-release.module.js";import{version as f}from"../version.js";import{WaitlistManagementModule as m}from"../waitlists/waitlist.module.js";import{FanfareError as b,ErrorCodes as w}from"./errors.js";import{createHttpClient as v}from"./http.js";import{createLogger as M}from"./logger.js";let h=null;async function I(I){const S=new o(I),j=S.get(),A=M({enabled:j.debug||!1,level:j.debug?"debug":"warn",prefix:"Fanfare"});if(A.info("Initializing Fanfare SDK",{organizationId:I.organizationId,environment:j.environment}),h)throw new b("Fanfare SDK is already initialized. The SDK uses a shared event bus and store; multiple concurrent instances will corrupt state and analytics. Call destroy() on the existing instance before initializing a new one.",w.ALREADY_INITIALIZED);const k=/* @__PURE__ */Symbol("fanfare-sdk"),x=v({baseUrl:S.apiUrl,credentials:j.credentials,headers:{"X-Organization-Id":I.organizationId,"X-Publishable-Key":I.publishableKey,"X-Fanfare-API-Version":"2025-01-15","X-Fanfare-SDK-Version":f,"X-Fanfare-Client-Type":"browser"},timeout:3e4,retryConfig:{maxRetries:3,delayTimer:1e3,retryOnNetworkError:!0}},j),D=v({baseUrl:S.beaconUrl,credentials:"omit",headers:{"X-Organization-Id":I.organizationId,"X-Publishable-Key":I.publishableKey,"X-Fanfare-API-Version":"2025-01-15","X-Fanfare-SDK-Version":f,"X-Fanfare-Client-Type":"browser"},timeout:3e4,retryConfig:{maxRetries:3,delayTimer:1e3,retryOnNetworkError:!0}},j),E=new r(x,D),q=new i(x),C=new l(x),R=new s(x),z=new t(x),O=new e(x),F=new m(x),K=new p(x),X=new a(x,C,R,z,F,K),P=new n(D,j.beacon||{}),T=c(),J=g(),$=/* @__PURE__ */new Map,N=/* @__PURE__ */new Map,V=/* @__PURE__ */new Map;let B,U;const L=e=>{const t=N.get(e);if(t)return A.debug("Returning existing journey handle",{experienceId:e}),t;A.info("Creating new journey",{experienceId:e});const r=new d(e,B);$.set(e,r),U?.registerJourney(r);const n={view$:r.view$,events$:r.events$,latestEvent$:r.latestEvent$,snapshot$:r.state,ackEvent:e=>r.ackEvent(e),ackAllEvents:()=>r.ackAllEvents(),destroy:()=>{r.destroy(),U?.unregisterJourney(e),$.delete(e),N.delete(e)}};return N.set(e,n),n},G=async e=>{const t=e??await X.getMe(),r=/* @__PURE__ */new Set,n=new Set(t.active.journeys.map(e=>e.experienceId));for(const i of n)L(i);for(const i of n){const e=$.get(i);e&&await e.resumeFromMe(t)&&r.add(i)}return[...r]},H={check:()=>E.check(),guest:()=>E.guest(),requestOtp:e=>E.requestOtp(e),verifyOtp:e=>E.verifyOtp(e),exchangeExternal:e=>E.exchangeExternal(e),login:e=>E.login(e),logout:()=>E.logout(),getSession:()=>E.getSession(),refresh:()=>E.refresh()},_={initiate:e=>q.initiate(e),verify:e=>q.verify(e)},Y={get:e=>L(e),list:()=>Array.from(
|
|
2
|
+
/* @__PURE__ */new Set([...N.keys(),...$.keys(),...Object.keys(J.activeJourneys)])),resumeAll:e=>(async e=>{const t=/* @__PURE__ */new Set;for(const r of Object.keys(J.activeJourneys))L(r),t.add(r);if(!e&&!E.getSession())return[...t];for(const r of await G(e))t.add(r);return[...t]})(e)},Z={track:e=>P.track(e),trackBatch:e=>P.trackBatch(e),flush:()=>P.flush()},Q=(e,t)=>{if(V.has(e.id))A.warn("CDP adapter already registered, skipping",{adapterId:e.id});else{try{e.init(T,t)}catch(r){return void A.error("CDP adapter failed to initialize",{adapterId:e.id,error:r})}V.set(e.id,e),A.info("CDP adapter registered",{adapterId:e.id})}},W=(e,t)=>T.on(e,t),ee=async()=>{A.info("Destroying SDK instance");for(const t of V.values())try{t.destroy()}catch(e){A.error("CDP adapter failed to destroy",{adapterId:t.id,error:e})}V.clear();for(const t of Array.from(N.values()))try{t.destroy()}catch(e){A.error("Journey handle failed to destroy",{error:e})}$.clear(),N.clear(),"destroy"in E&&"function"==typeof E.destroy&&E.destroy(),C.destroy(),R.destroy(),z.destroy(),O.destroy(),F.destroy(),K.destroy(),X.destroy(),P.destroy(),U?.close(),T.off(),h===k&&(h=null)};B={auth:H,challenges:_,journeys:Y,queues:{get:e=>C.get(e),enter:(e,t,r)=>C.enter(e,t,u({distributionId:e},r)),leave:(e,t)=>C.leave(e,u({distributionId:e},t)),status:e=>C.status(e),startMonitoring:(e,t,r)=>C.startMonitoring(e,t,r),stopMonitoring:e=>C.stopMonitoring(e),isMonitoring:e=>C.isMonitoring(e)},draws:{get:e=>R.get(e),enter:(e,t,r)=>R.enter(e,t,u({distributionId:e},r)),leave:(e,t)=>R.leave(e,u({distributionId:e},t)),status:e=>R.status(e),startMonitoring:(e,t,r)=>R.startMonitoring(e,t,r),stopMonitoring:e=>R.stopMonitoring(e),isMonitoring:e=>R.isMonitoring(e)},auctions:{get:e=>z.get(e),bid:(e,t,r)=>z.bid(e,t,u({distributionId:e},r)),enter:(e,t,r)=>z.enter(e,t,u({distributionId:e},r)),leave:(e,t)=>z.leave(e,u({distributionId:e},t)),status:e=>z.status(e),getBidHistory:e=>z.getBidHistory(e),enableAutoRebid:(e,t,r)=>z.enableAutoRebid(e,t,r),disableAutoRebid:e=>z.disableAutoRebid(e),getAutoRebidConfig:e=>z.getAutoRebidConfig(e),startMonitoring:(e,t,r)=>z.startMonitoring(e,t,r),stopMonitoring:e=>z.stopMonitoring(e),isMonitoring:e=>z.isMonitoring(e),destroy:()=>z.destroy()},experiences:{get:e=>X.get(e),enter:e=>X.enter(e),leave:e=>X.leave(e),getMe:()=>X.getMe(),findSequence:(e,t)=>X.findSequence(e,t),validateSequenceAccess:(e,t)=>X.validateSequenceAccess(e,t),selectSequence:e=>X.selectSequence(e),getCurrentDistributions:e=>X.getCurrentDistributions(e),enterDistribution:e=>{if(!e)throw new b("Distribution is required",w.VALIDATION_ERROR);return X.enterDistribution(e)},getActiveSession:()=>X.getActiveSession(),isInExperience:e=>X.isInExperience(e),getSelectedSequence:()=>X.getSelectedSequence(),createJourney:e=>L(e),resumeJourneysFromMe:e=>G(e),destroy:()=>X.destroy()},waitlists:{enter:(e,t)=>F.enter(e,u({distributionId:e},t)),leave:(e,t)=>F.leave(e,u({distributionId:e},t)),getStatus:e=>F.getStatus(e),destroy:()=>F.destroy()},timedReleases:{get:e=>K.get(e),enter:(e,t,r)=>K.enter(e,t,u({distributionId:e},r)),leave:(e,t)=>K.leave(e,u({distributionId:e},t)),complete:e=>K.complete(e),status:e=>K.status(e),startMonitoring:(e,t,r)=>K.startMonitoring(e,t,r),stopMonitoring:e=>K.stopMonitoring(e),isMonitoring:e=>K.isMonitoring(e)},appointments:{get:e=>O.get(e),getSlots:(e,t)=>O.getSlots(e,t),getMe:e=>O.getMe(e),book:(e,t,r)=>O.book(e,t,r),cancel:(e,t,r,n)=>O.cancel(e,t,r,n),reschedule:(e,t,r)=>O.reschedule(e,t,r),startMonitoring:(e,t,r)=>O.startMonitoring(e,t,r),stopMonitoring:e=>O.stopMonitoring(e),isMonitoring:e=>O.isMonitoring(e),bumpMonitorGeneration:e=>O.bumpMonitorGeneration(e),destroy:()=>O.destroy()},beacon:Z,use:Q,on:W,destroy:ee};const te=!1!==I.sync&&"object"==typeof I.sync?I.sync:{};U=new y({enabled:!1!==I.sync&&!1!==te.enabled,channelName:te.channelName}),A.info("Inter-tab sync initialized",{tabId:U.getTabId(),enabled:U.isEnabled()});const re={auth:H,challenges:_,journeys:Y,beacon:Z,appointments:B.appointments,use:Q,on:W,destroy:ee};return h=k,A.info("SDK initialized successfully"),re}export{I as init};
|
package/dist/storefront.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { JourneySnapshot } from './experiences/journey.types';
|
|
2
|
-
import { AdmissionProofHeaders } from './security/admission-proof';
|
|
3
|
-
export type { AdmissionProofHeaders } from './security/admission-proof';
|
|
4
2
|
/** Static key map backing AccessStatus. Order is stable; drives exhaustiveness tests. */
|
|
5
3
|
export declare const ACCESS_STATUSES: readonly ["unconfigured", "loading", "blocked", "available", "granted", "ended"];
|
|
6
4
|
/**
|
|
@@ -35,26 +33,6 @@ export interface ExperienceResolver {
|
|
|
35
33
|
handle: string;
|
|
36
34
|
}): string | null | Promise<string | null>;
|
|
37
35
|
}
|
|
38
|
-
export interface CheckoutProofParams {
|
|
39
|
-
/** The PUBLIC checkout URL the storefront is about to POST to — the proof binds to exactly this URL. */
|
|
40
|
-
checkoutUrl: string;
|
|
41
|
-
/** Defaults to "POST". */
|
|
42
|
-
method?: string;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Mints the binding-proof headers for one checkout request: a DPoP JWS signed
|
|
46
|
-
* by this browser's persistent admission key over the GATE's public checkout
|
|
47
|
-
* URL, plus the key-thumbprint header. FRESH per call (new jti + iat) — call it
|
|
48
|
-
* again for every request, including retries the storefront issues itself; never
|
|
49
|
-
* reuse a previous result.
|
|
50
|
-
*
|
|
51
|
-
* Spread the returned headers into the `POST <checkoutUrl>` request alongside
|
|
52
|
-
* the claimed grant's token. Resolves `null` where persistent browser crypto is
|
|
53
|
-
* unavailable (SSR, no IndexedDB): post without proof headers — an unbound
|
|
54
|
-
* credential needs none, and a key-bound credential will be refused by the
|
|
55
|
-
* authority rather than the storefront guessing.
|
|
56
|
-
*/
|
|
57
|
-
export declare function buildCheckoutProofHeaders(params: CheckoutProofParams): Promise<AdmissionProofHeaders | null>;
|
|
58
36
|
export interface GrantRecord {
|
|
59
37
|
/**
|
|
60
38
|
* The client-visible grant value the adapter records when the shopper clears
|
|
@@ -71,20 +49,6 @@ export interface GrantRecord {
|
|
|
71
49
|
experienceId: string;
|
|
72
50
|
/** ms timestamp; absent = no client-side expiry known. */
|
|
73
51
|
expiresAt?: number;
|
|
74
|
-
/**
|
|
75
|
-
* @deprecated Reserved. Handoff tokens bridge active sessions (mint from the
|
|
76
|
-
* sequence capability grant, redeem single-use) and are not part of the
|
|
77
|
-
* admission/checkout verification contract, which is driven by the admission
|
|
78
|
-
* credential. Kept because the field is pinned by the published surface; do
|
|
79
|
-
* not wire new behavior to it.
|
|
80
|
-
*/
|
|
81
|
-
capabilityGrant?: string;
|
|
82
|
-
/**
|
|
83
|
-
* @deprecated Reserved. See `capabilityGrant` — checkout admission is enforced
|
|
84
|
-
* through the platform verifier/proxy using the admission credential, not via
|
|
85
|
-
* a handoff token. Do not wire new behavior to it.
|
|
86
|
-
*/
|
|
87
|
-
handoffToken?: boolean;
|
|
88
52
|
}
|
|
89
53
|
export interface VerificationResult {
|
|
90
54
|
ok: boolean;
|
package/dist/storefront.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const e=["unconfigured","loading","blocked","available","granted","ended"];function a(e){if(null===e)return"loading";switch(e.journeyStage){case"ready":case"routing":return"loading";case"gated":return"blocked";case"routed":switch(e.sequence.phase){case"enterable":return"available";case"scheduled":default:return"blocked";case"granted":return"granted";case"ended":case"unavailable":return"ended"}}}export{e as ACCESS_STATUSES,a as snapshotToAccessStatus};
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const o="0.
|
|
1
|
+
const o="0.5.0";export{o as version};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fanfare-io/fanfare-sdk-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Official Fanfare Browser SDK for queue, draw, auction, and appointment experiences",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"uuid": "^14.0.0",
|
|
123
123
|
"wretch": "^2.11.0",
|
|
124
124
|
"zustand": "^5.0.6",
|
|
125
|
-
"@fanfare-io/fanfare-sdk-contracts": "0.
|
|
125
|
+
"@fanfare-io/fanfare-sdk-contracts": "0.5.0"
|
|
126
126
|
},
|
|
127
127
|
"peerDependencies": {
|
|
128
128
|
"valibot": "^1.1.0",
|
|
@@ -160,12 +160,12 @@
|
|
|
160
160
|
"terser": "^5.46.1",
|
|
161
161
|
"typescript": "^5.9.2",
|
|
162
162
|
"valibot": "^1.1.0",
|
|
163
|
-
"vite": "^7.3.
|
|
163
|
+
"vite": "^7.3.5",
|
|
164
164
|
"vite-bundle-visualizer": "^1.0.0",
|
|
165
165
|
"vite-plugin-dts": "^4.5.4",
|
|
166
166
|
"vite-tsconfig-paths": "^5.1.4",
|
|
167
167
|
"vitest": "^3.2.4",
|
|
168
|
-
"@fanfare-io/shared-models": "0.
|
|
168
|
+
"@fanfare-io/shared-models": "0.5.0"
|
|
169
169
|
},
|
|
170
170
|
"sideEffects": false,
|
|
171
171
|
"keywords": [
|