@fanfare-io/fanfare-sdk-core 0.17.0 → 0.19.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/auctions/auction.driver.js +1 -1
- package/dist/auctions/auction.sequence.d.ts +15 -1
- package/dist/core/error-display.js +1 -1
- package/dist/draws/draw.driver.js +1 -1
- package/dist/draws/draw.sequence.d.ts +18 -1
- package/dist/experiences/journey.js +1 -1
- package/dist/experiences/sequence-driver.js +1 -1
- package/dist/queues/queue.driver.js +1 -1
- package/dist/queues/queue.sequence.d.ts +16 -1
- package/dist/timed-releases/timed-release.driver.js +1 -1
- package/dist/timed-releases/timed-release.sequence.d.ts +12 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AuctionDistributionResults as t}from"@fanfare-io/fanfare-sdk-contracts";import{createError as i}from"../core/errors.js";import{buildGrantPaymentAffordance as
|
|
1
|
+
import{AuctionDistributionResults as t}from"@fanfare-io/fanfare-sdk-contracts";import{createError as i}from"../core/errors.js";import{selectionModeFields as e,buildGrantPaymentAffordance as n}from"../experiences/sequence-driver.js";import{isGrantPendingWin as s}from"./auction-status.js";import{isUnresolvedAuctionConsumer as o}from"./auction.sequence.js";function a(t){return!t||("lost"===t.type||"closed"===t.type)&&!t.reason}function r(t){return new d(t)}function c(n){const s=function(e){const{distribution:n,consumer:s,grant:r,settlement:c,selection:u,outcome:d}=e;if(!n)return{phase:"unavailable"};const l=function(t){if("auction"!==t.type)throw i.validationError("Auction driver received a non-auction distribution");return t}(n),h=s&&"auction"===s.mechanism?function(t){const{mechanism:i,...e}=t;return e}(s):p(n);if(r)return"completed"===d?.type?m(l,h,d):r.expiresAt&&Date.now()>new Date(r.expiresAt).getTime()?"open"===l.lifecycle?{phase:"enterable",mechanism:"auction",distribution:l,consumer:p(l)}:m(l,h,{type:"expired"}):c&&u?{phase:"granted",mechanism:"auction",distribution:l,consumer:h,grant:r,settlement:c,selection:u}:{phase:"unavailable"};if("closed"===l.lifecycle){if("not_bid"===h.status&&l.result===t.FLOOR_UNSOLD&&a(d))return m(l,h,{type:"lost",reason:t.FLOOR_UNSOLD});if("auction"===s?.mechanism&&!d)return m(l,h,{type:"lost"})}const b=d??function(t){return"lost"===t.status?{type:"lost"}:void 0}(h);if(b)return m(l,h,b);if("settling"===l.lifecycle)return{phase:"settling",mechanism:"auction",distribution:l,consumer:h};if(o(h))return{phase:"participating",mechanism:"auction",distribution:l,consumer:h};if("scheduled"===l.lifecycle)return{phase:"scheduled",mechanism:"auction",distribution:l};if("open"===l.lifecycle)return{phase:"enterable",mechanism:"auction",distribution:l,consumer:h};return m(l,h,{type:"closed"})}(n);return"unavailable"===s.phase?s:{...s,...e(n)}}function u(t,i,e){return t&&"auction"===t.mechanism&&i?"won"===i.type?{...t,status:"won"}:!e?.finalize&&"not_bid"===t.status&&a(i)?t:{...t,status:"lost"}:t}class d{constructor(t){this.deps=t,this.mechanism="auction"}project(t){return c(t)}buildView(t,s){if("unavailable"===t.phase)return{phase:"unavailable",reason:t.reason};const o=function(t){if(!("mechanism"in t)||"auction"!==t.mechanism)throw i.validationError("Auction driver received a non-auction sequence");return t}(t);switch(o.phase){case"scheduled":return{phase:"scheduled",mechanism:"auction",...e(o),distribution:o.distribution,startsAt:o.distribution.startsAt??o.distribution.opensAt};case"enterable":return{phase:"enterable",mechanism:"auction",...e(o),distribution:o.distribution,consumer:o.consumer,display$:s.displayAtom,loadSelectionOptions:s.loadSelectionOptions,bid:t=>this.bid(t)};case"participating":return{phase:"participating",mechanism:"auction",...e(o),consumer:o.consumer,display$:s.displayAtom,loadSelectionOptions:s.loadSelectionOptions,bid:t=>this.bid(t)};case"settling":return{phase:"settling",mechanism:"auction",...e(o),distribution:o.distribution,consumer:o.consumer};case"granted":{const t={phase:"granted",mechanism:"auction",...e(o),distribution:o.distribution,consumer:o.consumer,grant:o.grant},{settlement:i}=o,a=o.selection;if("awaiting_assignment"===a.status)return{...t,settlement:i,selection:a};if("required"===a.status)return{...t,settlement:i,selection:a,select:s.select,loadSelectionOptions:s.loadSelectionOptions};if("internal"===i.processor&&"at_end"===i.mode){const e=n(i,o.pendingAction,s);return e?{...t,settlement:i,selection:a,loadSelectionOptions:s.loadSelectionOptions,select:s.select,claim:()=>s.claim(),payment:e}:{...t,settlement:i,selection:a,loadSelectionOptions:s.loadSelectionOptions,select:s.select,claim:()=>s.claim()}}return"external"===i.processor?{...t,settlement:i,selection:a,loadSelectionOptions:s.loadSelectionOptions,select:s.select,claim:()=>s.claim()}:{phase:"unavailable",reason:"checkout_misconfigured"}}case"ended":return{phase:"ended",mechanism:"auction",...e(o),consumer:o.consumer,outcome:o.outcome}}}startMonitoring(t){this.activeMonitorId=t.participation.id,this.deps.auctions.startMonitoring(t.participation.id,{displayAtom:t.displayAtom},t.onUpdate,t.onDegradedChange)}stopMonitoring(){this.activeMonitorId&&(this.deps.auctions.stopMonitoring(this.activeMonitorId),this.activeMonitorId=void 0)}async bid(t){await this.deps.runSerializedOperation(async()=>{const i=this.currentAuctionSequenceForBid(),e=i.consumer.distributionId??i.consumer.id??i.distribution.id,n=i.consumer.selection,o="auction"===i.distribution.details?.type?i.distribution.details:void 0;l(t,o?.auctionType);const a=await this.deps.auctions.bid(e,t),r=this.deps.getCurrentSequence(),u=r&&("enterable"===r.phase||"participating"===r.phase||"settling"===r.phase)&&"mechanism"in r&&"auction"===r.mechanism&&r.distribution.id===e;if("won"===a.status||"lost"===a.status)return void(u&&("won"===a.status&&a.admissionGrant?this.deps.applyMonitorUpdate({type:"granted",token:a.admissionGrant}):"lost"===a.status?this.deps.applyMonitorUpdate({type:"ended",outcome:{type:"lost"}}):s(a)||this.deps.applyMonitorUpdate({type:"resync"})));if(!u)return;const d=function(t){switch(t){case"not_bid":case"winning":case"outbid":return t;case"won":case"lost":return}}(a.status);void 0!==d&&this.deps.commit(c({distribution:i.distribution,consumer:{..."participating"===i.phase?i.consumer:{},mechanism:"auction",status:d,id:e,distributionId:e,...n?{selection:n}:{},currentBid:a.amount,highestBid:a.highestBid}}))})}currentAuctionSequenceForBid(){const t=this.deps.getCurrentSequence();if(!t||"enterable"!==t.phase&&"participating"!==t.phase||!("mechanism"in t)||"auction"!==t.mechanism)throw i.validationError("No auction is available to bid on");return t}}function l(t,e){if("dutch"!==e){if(void 0===t.amount)throw i.validationError("A bid amount is required for an English auction")}else if(void 0!==t.amount)throw i.validationError("A Dutch auction clinches at the current price; omit the bid amount")}function p(t){return{status:"not_bid",distributionId:t.id}}function m(t,i,e){return{phase:"ended",mechanism:"auction",distribution:t,consumer:i,outcome:{...e,distributionType:e.distributionType??t.type,distributionId:e.distributionId??t.id,at:e.at??/* @__PURE__ */(new Date).toISOString()}}}export{l as assertBidInputMatchesMechanism,r as createAuctionDriver,a as isUpgradeableGenericLoss,c as projectAuctionSequence,u as withAuctionTerminalConsumer};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AdmissionGrant, AuctionConsumerStatus, GrantedSettlement, SequenceOutcome } from '@fanfare-io/fanfare-sdk-contracts/consumer-me';
|
|
2
|
-
import { GrantedSelection } from '@fanfare-io/fanfare-sdk-contracts/selection';
|
|
2
|
+
import { GrantedSelection, SelectionMode } from '@fanfare-io/fanfare-sdk-contracts/selection';
|
|
3
3
|
import { ReadableAtom } from 'nanostores';
|
|
4
4
|
import { AuctionDisplayState } from '../experiences/distribution-monitor.types';
|
|
5
5
|
import { DistributionSummary } from '../experiences/journey.types';
|
|
@@ -52,6 +52,7 @@ export type AuctionSequence = AuctionScheduled | AuctionEnterable | AuctionParti
|
|
|
52
52
|
export interface AuctionScheduled {
|
|
53
53
|
/** Mechanism discriminator for auction narrowing. */
|
|
54
54
|
mechanism: "auction";
|
|
55
|
+
selectionMode?: SelectionMode;
|
|
55
56
|
/** Phase discriminator; scheduled auctions cannot be bid on yet. */
|
|
56
57
|
phase: "scheduled";
|
|
57
58
|
/** Auction distribution facts from the journey projector. */
|
|
@@ -65,6 +66,7 @@ export interface AuctionScheduled {
|
|
|
65
66
|
export interface AuctionEnterable {
|
|
66
67
|
/** Mechanism discriminator for auction narrowing. */
|
|
67
68
|
mechanism: "auction";
|
|
69
|
+
selectionMode?: SelectionMode;
|
|
68
70
|
/** Phase discriminator; `bid()` is legal on the matching view. */
|
|
69
71
|
phase: "enterable";
|
|
70
72
|
/** Open auction distribution facts from the journey projector. */
|
|
@@ -80,6 +82,7 @@ export interface AuctionEnterable {
|
|
|
80
82
|
export interface AuctionParticipating {
|
|
81
83
|
/** Mechanism discriminator for auction narrowing. */
|
|
82
84
|
mechanism: "auction";
|
|
85
|
+
selectionMode?: SelectionMode;
|
|
83
86
|
/** Phase discriminator; auction display and bidding are live. */
|
|
84
87
|
phase: "participating";
|
|
85
88
|
/** Auction distribution facts from the journey projector. */
|
|
@@ -95,6 +98,7 @@ export interface AuctionParticipating {
|
|
|
95
98
|
export interface AuctionSettling {
|
|
96
99
|
/** Mechanism discriminator for auction narrowing. */
|
|
97
100
|
mechanism: "auction";
|
|
101
|
+
selectionMode?: SelectionMode;
|
|
98
102
|
/** Phase discriminator; no consumer action is legal while settling. */
|
|
99
103
|
phase: "settling";
|
|
100
104
|
/** Settling auction distribution facts from the journey projector. */
|
|
@@ -110,6 +114,7 @@ export interface AuctionSettling {
|
|
|
110
114
|
export interface AuctionGranted {
|
|
111
115
|
/** Mechanism discriminator for auction narrowing. */
|
|
112
116
|
mechanism: "auction";
|
|
117
|
+
selectionMode?: SelectionMode;
|
|
113
118
|
/** Phase discriminator; `claim()` is legal on the matching view. */
|
|
114
119
|
phase: "granted";
|
|
115
120
|
/** Auction distribution facts from the journey projector. */
|
|
@@ -135,6 +140,7 @@ export interface AuctionGranted {
|
|
|
135
140
|
export interface AuctionEnded {
|
|
136
141
|
/** Mechanism discriminator for auction narrowing. */
|
|
137
142
|
mechanism: "auction";
|
|
143
|
+
selectionMode?: SelectionMode;
|
|
138
144
|
/** Phase discriminator; no auction actions are legal after this phase. */
|
|
139
145
|
phase: "ended";
|
|
140
146
|
/** Auction distribution facts from the journey projector. */
|
|
@@ -162,6 +168,7 @@ export interface AuctionScheduledView {
|
|
|
162
168
|
phase: "scheduled";
|
|
163
169
|
/** Mechanism discriminator for auction rendering. */
|
|
164
170
|
mechanism: "auction";
|
|
171
|
+
selectionMode?: SelectionMode;
|
|
165
172
|
/** Auction distribution facts from the journey projector. */
|
|
166
173
|
distribution: DistributionSummary & {
|
|
167
174
|
type: "auction";
|
|
@@ -177,6 +184,7 @@ export interface AuctionEnterableView {
|
|
|
177
184
|
phase: "enterable";
|
|
178
185
|
/** Mechanism discriminator for auction rendering. */
|
|
179
186
|
mechanism: "auction";
|
|
187
|
+
selectionMode?: SelectionMode;
|
|
180
188
|
/** Open auction distribution facts from the journey projector. */
|
|
181
189
|
distribution: DistributionSummary & {
|
|
182
190
|
type: "auction";
|
|
@@ -208,6 +216,7 @@ export interface AuctionParticipatingView {
|
|
|
208
216
|
phase: "participating";
|
|
209
217
|
/** Mechanism discriminator for auction rendering. */
|
|
210
218
|
mechanism: "auction";
|
|
219
|
+
selectionMode?: SelectionMode;
|
|
211
220
|
/** Consumer auction participation facts. */
|
|
212
221
|
consumer: AuctionSequenceConsumerState;
|
|
213
222
|
/** Live auction display facts: the price model, currency, and close time. */
|
|
@@ -234,6 +243,7 @@ export interface AuctionSettlingView {
|
|
|
234
243
|
phase: "settling";
|
|
235
244
|
/** Mechanism discriminator for auction rendering. */
|
|
236
245
|
mechanism: "auction";
|
|
246
|
+
selectionMode?: SelectionMode;
|
|
237
247
|
/** Settling auction distribution facts from the journey projector. */
|
|
238
248
|
distribution: DistributionSummary & {
|
|
239
249
|
type: "auction";
|
|
@@ -249,6 +259,7 @@ interface AuctionGrantedViewBase {
|
|
|
249
259
|
phase: "granted";
|
|
250
260
|
/** Mechanism discriminator for auction rendering. */
|
|
251
261
|
mechanism: "auction";
|
|
262
|
+
selectionMode?: SelectionMode;
|
|
252
263
|
/** Auction distribution facts from the journey projector. */
|
|
253
264
|
distribution: DistributionSummary & {
|
|
254
265
|
type: "auction";
|
|
@@ -317,6 +328,7 @@ export interface AuctionEndedView {
|
|
|
317
328
|
phase: "ended";
|
|
318
329
|
/** Mechanism discriminator for auction rendering. */
|
|
319
330
|
mechanism: "auction";
|
|
331
|
+
selectionMode?: SelectionMode;
|
|
320
332
|
/** Consumer auction facts at the terminal outcome. */
|
|
321
333
|
consumer: AuctionSequenceConsumerState;
|
|
322
334
|
/** Server-derived terminal outcome for the auction participation. */
|
|
@@ -328,6 +340,7 @@ export interface AuctionGrantedAwaitingAssignmentView {
|
|
|
328
340
|
phase: "granted";
|
|
329
341
|
/** Mechanism discriminator. */
|
|
330
342
|
mechanism: "auction";
|
|
343
|
+
selectionMode?: SelectionMode;
|
|
331
344
|
/** Distribution associated with this grant. */
|
|
332
345
|
distribution: DistributionSummary & {
|
|
333
346
|
type: "auction";
|
|
@@ -349,6 +362,7 @@ export interface AuctionGrantedSelectionRequiredView {
|
|
|
349
362
|
phase: "granted";
|
|
350
363
|
/** Mechanism discriminator. */
|
|
351
364
|
mechanism: "auction";
|
|
365
|
+
selectionMode?: SelectionMode;
|
|
352
366
|
/** Distribution associated with this grant. */
|
|
353
367
|
distribution: DistributionSummary & {
|
|
354
368
|
type: "auction";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{classify as
|
|
1
|
+
import{classify as e}from"./error-disposition.js";import{FanfareError as r,ErrorCodes as o}from"./errors.js";const t={[o.OTP_INVALID]:"auth.invalidCode",[o.OTP_EXPIRED]:"auth.codeExpired",[o.INVALID_SESSION]:"common.sessionExpired",[o.INVALID_REFRESH_TOKEN]:"common.sessionExpired",[o.SERVICE_UNAVAILABLE]:"error.overloadedGeneric",[o.TIMEOUT]:"error.overloadedGeneric",[o.NETWORK_ERROR]:"error.overloadedGeneric",[o.FEATURE_DISABLED]:"error.featureDisabled",[o.NO_ACCESS]:"widget.noAccess.message",[o.FORBIDDEN]:"error.forbidden",[o.DISTRIBUTION_NOT_OPEN]:"error.notOpen",[o.DISTRIBUTION_DEACTIVATED]:"error.deactivated",[o.ALREADY_BOOKED]:"appointment.error.alreadyBooked",[o.ACTIVE_BOOKING_EXISTS]:"appointment.error.activeBookingExists",[o.SLOT_NOT_AVAILABLE]:"appointment.error.slotNotAvailable",[o.SLOT_EXPIRED]:"appointment.error.slotExpired",[o.SLOT_OUT_OF_WINDOW]:"appointment.error.slotOutOfWindow",[o.CANNOT_CANCEL_ONGOING_OR_PAST]:"appointment.error.cannotCancel",[o.NEW_SLOT_FULL]:"appointment.error.newSlotFull",[o.BOOKING_COMPLETED]:"appointment.error.bookingCompleted",[o.NO_EXISTING_BOOKING]:"appointment.error.noExistingBooking",[o.INVALID_SLOT]:"appointment.error.invalidSlot",[o.SELECTION_REQUIRED]:"selection.error.required",[o.SELECTION_INVALID_CHOICE]:"selection.error.invalidChoice",[o.SELECTION_NOT_REQUIRED]:"selection.error.notRequired",[o.SELECTION_LOCKED]:"selection.locked.final",[o.SELECTION_MISMATCH]:"selection.error.mismatch",[o.SELECTION_UNAVAILABLE]:"selection.error.unavailable",[o.SELECTION_LIMIT_REACHED]:"selection.error.limitReached",[o.SELECTION_ASSIGNMENT_PENDING]:"selection.error.assignmentPending",[o.ADMISSION_SELECTION_UNRESOLVED]:"selection.error.admissionUnresolved",[o.SOLD_OUT]:"selection.error.soldOut",[o.STOCK_UNSEEDED]:"selection.error.unseeded"},i=/* @__PURE__ */new Set([o.DISTRIBUTION_DEACTIVATED,o.DISTRIBUTION_CLOSED,o.DISTRIBUTION_ORDER_LIMIT,o.SOLD_OUT,o.CHECKOUT_MISCONFIGURED]);function n(e){return"INLINE"===e||"STEP_RESET"===e?"error.inlineGeneric":"error.description"}function E(r,E){const{disposition:s}=e(r.code,r.status,r.action),I="number"==typeof r.retryAfter&&Number.isFinite(r.retryAfter)?r.retryAfter:void 0,O=function(e,r,i){return e===o.RATE_LIMITED?i?"error.rateLimited":"error.rateLimitedGeneric":e===o.OVERLOADED?i?"error.overloaded":"error.overloadedGeneric":t[e]??n(r)}(r.code,s,void 0!==I);let d=E(O,void 0!==I?{values:{seconds:I}}:void 0);d.includes("{{")&&(d=E(n(s)));const T="PANEL"===s?E("error.title"):void 0;return{code:r.code,title:T,description:d,disposition:s,retryAfter:r.retryAfter,support:r.support,allowRetry:!i.has(r.code)}}function s(e){if(e instanceof r)return e;const t=e instanceof Error?e.message:String(e);return new r(t,o.INTERNAL_ERROR)}function I(e){return{code:e.code,status:e.status,requestId:e.requestId,correlationId:e.correlationId,details:e.details,issues:e.issues}}export{s as ensureFanfareError,I as toDebug,E as toDisplay};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DrawConsumerStatuses as e}from"@fanfare-io/fanfare-sdk-contracts/consumer-me";import{createError as t}from"../core/errors.js";import{buildGrantPaymentAffordance as
|
|
1
|
+
import{DrawConsumerStatuses as e}from"@fanfare-io/fanfare-sdk-contracts/consumer-me";import{createError as t}from"../core/errors.js";import{selectionModeFields as i,buildGrantPaymentAffordance as n}from"../experiences/sequence-driver.js";import{resolveCheckoutContract as s,checkoutViewFields as r,isEntryActionRequired as o,canReenter as a,isPreAuthMisconfigured as d}from"../payment/checkout-contract.js";import{isClaimableSettlement as c}from"../payment/settlement.js";import{isUnresolvedDrawConsumer as u}from"./draw.sequence.js";import{drawSelectionFromResponse as p}from"./types.js";function l(e){return d(s(e.details))}function m(e){return a(e.distribution.lifecycle,s(e.distribution.details))}function h(e){return new y(e)}const w=new Set(e);function f(e){const n=function(e){const{distribution:i,consumer:n,grant:s,checkout:r,settlement:o,selection:a,outcome:d}=e;if(!i)return{phase:"unavailable"};const c=function(e){if("draw"!==e.type)throw t.validationError("Draw driver received a non-draw distribution");return e}(i),p=n&&"draw"===n.mechanism?function(e){const{mechanism:t,...i}=e;return i}(n):v(i);if(s)return"completed"===d?.type?g(c,p,d,r):s.expiresAt&&Date.now()>new Date(s.expiresAt).getTime()?"open"===c.lifecycle?l(c)?{phase:"unavailable",reason:"checkout_misconfigured"}:{phase:"enterable",mechanism:"draw",distribution:c,consumer:v(c)}:g(c,p,{type:"expired"}):o&&a?{phase:"granted",mechanism:"draw",distribution:c,consumer:p,grant:s,settlement:o,selection:a}:{phase:"unavailable"};if(!function(e){return w.has(e.status)}(p))return{phase:"unavailable",reason:"unrecognized_standing"};if(!d&&"draw"===n?.mechanism&&"closed"===c.lifecycle)return g(c,p,{type:"lost"});const m=d??function(e){return"completed"===e.status?{type:"completed"}:"denied"===e.status?{type:"denied",reason:e.deniedReason}:void 0}(p);if(m)return g(c,p,m,r);if("settling"===c.lifecycle)return{phase:"settling",mechanism:"draw",distribution:c,consumer:p};if(u(p))return{phase:"participating",mechanism:"draw",distribution:c,consumer:p};if("scheduled"===c.lifecycle)return{phase:"scheduled",mechanism:"draw",distribution:c};if("open"===c.lifecycle)return l(c)?{phase:"unavailable",reason:"checkout_misconfigured"}:{phase:"enterable",mechanism:"draw",distribution:c,consumer:p};return g(c,p,{type:"closed"})}(e);return"unavailable"===n.phase?n:{...n,...i(e)}}function b(e,t){return e&&"draw"===e.mechanism&&t?"left"===t.type?{...e,status:"left"}:"denied"===t.type?{...e,status:"denied",deniedReason:t.reason}:"completed"===t.type?{...e,status:"completed"}:"won"===t.type?{...e,status:"won"}:{...e,status:"not_entered"}:e}class y{constructor(e){this.deps=e,this.mechanism="draw",this.settlementCanStartWhileActive=!0}project(e){return f(e)}buildView(e,s){if("unavailable"===e.phase)return{phase:"unavailable",reason:e.reason};const r=function(e){if(!("mechanism"in e)||"draw"!==e.mechanism)throw t.validationError("Draw driver received a non-draw sequence");return e}(e);switch(r.phase){case"scheduled":return{phase:"scheduled",mechanism:"draw",...i(r),distribution:r.distribution,startsAt:r.distribution.startsAt??r.distribution.opensAt};case"enterable":return this.buildEnterableView(r,s);case"participating":return{phase:"participating",mechanism:"draw",...i(r),consumer:r.consumer,display$:s.displayAtom,loadSelectionOptions:s.loadSelectionOptions,select:s.select,leave:()=>this.leave()};case"settling":return{phase:"settling",mechanism:"draw",...i(r),distribution:r.distribution,consumer:r.consumer};case"granted":{const e={phase:"granted",mechanism:"draw",...i(r),distribution:r.distribution,consumer:r.consumer,grant:r.grant},{settlement:t}=r,o=r.selection;if("awaiting_assignment"===o.status)return{...e,settlement:t,selection:o};if("required"===o.status)return{...e,settlement:t,selection:o,select:s.select,loadSelectionOptions:s.loadSelectionOptions};if("internal"===t.processor&&"at_end"===t.mode){const i=n(t,r.pendingAction,s);return i?{...e,settlement:t,selection:o,loadSelectionOptions:s.loadSelectionOptions,select:s.select,claim:()=>s.claim(),payment:i}:{...e,settlement:t,selection:o,loadSelectionOptions:s.loadSelectionOptions,select:s.select,claim:()=>s.claim()}}return c(t)?{...e,settlement:t,selection:o,loadSelectionOptions:s.loadSelectionOptions,select:s.select,claim:()=>s.claim()}:{...e,settlement:t,selection:o}}case"ended":return this.buildEndedView(r)}}buildEnterableView(e,t){const n=s(e.distribution.details),o=r(n);return"pre_auth"===o.checkoutMode?{phase:"enterable",mechanism:"draw",...i(e),...o,distribution:e.distribution,consumer:e.consumer,...e.pendingAction?{pendingAction:e.pendingAction}:{},...e.paymentProvider?{paymentProvider:e.paymentProvider}:{},loadSelectionOptions:t.loadSelectionOptions,enter:(e,t)=>this.enter({paymentInput:e,selection:t})}:{phase:"enterable",mechanism:"draw",...i(e),...o,distribution:e.distribution,consumer:e.consumer,loadSelectionOptions:t.loadSelectionOptions,enter:e=>this.enter({selection:e})}}buildEndedView(e){const t={phase:"ended",mechanism:"draw",...i(e),consumer:e.consumer,outcome:e.outcome,...e.checkout?{checkout:e.checkout}:{}};if(!m(e))return t;const n=s(e.distribution.details),o=r(n);return"pre_auth"===o.checkoutMode?{...t,...o,reenter:(e,t)=>this.enter({paymentInput:e,selection:t})}:{...t,...o,reenter:e=>this.enter({selection:e})}}startMonitoring(e){this.activeMonitorId=e.participation.id;const t=this.deps.getCurrentSequence(),i=t&&("participating"===t.phase||"settling"===t.phase)&&"mechanism"in t&&"draw"===t.mechanism&&"draw"===t.distribution.details?.type?t.distribution.details.drawTime:void 0;this.deps.draws.startMonitoring(e.participation.id,{displayAtom:e.displayAtom,drawTime:i,phase:"settling"===t?.phase?"settling":"participating"},e.onUpdate)}stopMonitoring(){this.activeMonitorId&&(this.deps.draws.stopMonitoring(this.activeMonitorId),this.activeMonitorId=void 0)}async enter(e){await this.deps.runSerializedOperation(async()=>{await this.enterWithinOperation(e)})}async enterWithinOperation(e){const i=this.currentDrawSequence("enterable","No open draw to enter"),n=i.distribution,r=s(n.details),a=e?.paymentInput;if("pre_auth"===r.mode&&!a)throw t.validationError("Payment input is required for pre-auth distributions");const d=e?.selection?await this.deps.draws.enter(n.id,void 0,void 0,a,e.selection):a?await this.deps.draws.enter(n.id,void 0,void 0,a):await this.deps.draws.enter(n.id,void 0);if(o(d))return this.deps.commit({...i,pendingAction:d.nextAction}),void this.deps.emitEvent("sequence_change","info","user","Entry awaiting verification",{distributionId:n.id,processor:d.nextAction.processor});const c=function(e){if("ENTERED"===e.status)return null;if("COMPLETED"===e.status)return{type:"ended",outcome:{type:"completed"}};if("WON"===e.status)return"admissionGrant"in e?{type:"granted",token:e.admissionGrant,expiresAt:e.expiresAt?new Date(e.expiresAt).getTime():void 0}:null;if("LEFT"===e.status)return{type:"ended",outcome:{type:"left"}};return{type:"ended",outcome:{type:"DENIED"===e.status?"denied":"lost",reason:"reason"in e?e.reason:void 0}}}(d);if(c)return void this.deps.applyMonitorUpdate(c);const u=p(d),l={...(m=n.id,{mechanism:"draw",status:"entered",id:m,distributionId:m}),...u?{selection:u}:{}};var m;this.deps.ensureDisplayAtom({id:n.id,type:"draw"}),this.deps.commit(f({distribution:n,consumer:l})),this.deps.emitEvent("sequence_change","success","user","Entered draw",{distributionId:n.id})}async leave(){await this.deps.runSerializedOperation(async()=>{await this.leaveWithinOperation()})}async leaveWithinOperation(){const e=this.currentDrawSequence("participating"),t=e.consumer.distributionId??e.consumer.id??e.distribution.id;await this.deps.draws.leave(t),this.deps.stopRuntimeMonitoring(!0),this.deps.applyMonitorUpdate({type:"ended",outcome:{type:"left"}}),this.deps.emitEvent("sequence_change","info","user","Left participation",{type:"draw"})}currentDrawSequence(e,i="Not participating in a draw"){const n=this.deps.getCurrentSequence();if(!n||!("mechanism"in n)||"draw"!==n.mechanism)throw t.validationError(i);if("enterable"===e&&"ended"===n.phase&&m(n))return{phase:"enterable",mechanism:"draw",distribution:n.distribution,consumer:v(n.distribution)};if(n.phase!==e)throw t.validationError(i);return n}}function v(e){return{status:"not_entered",distributionId:e.id}}function g(e,t,i,n){return{phase:"ended",mechanism:"draw",distribution:e,consumer:t,outcome:{...i,distributionType:i.distributionType??e.type,distributionId:i.distributionId??e.id,at:i.at??/* @__PURE__ */(new Date).toISOString()},...n?{checkout:n}:{}}}export{h as createDrawDriver,f as projectDrawSequence,b as withDrawTerminalConsumer};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AdmissionGrant, DrawConsumerStatus, GrantedSettlement, SequenceOutcome } from '@fanfare-io/fanfare-sdk-contracts/consumer-me';
|
|
2
|
-
import { GrantedSelection } from '@fanfare-io/fanfare-sdk-contracts/selection';
|
|
2
|
+
import { GrantedSelection, SelectionMode } from '@fanfare-io/fanfare-sdk-contracts/selection';
|
|
3
3
|
import { ReadableAtom } from 'nanostores';
|
|
4
4
|
import { DrawDisplayState } from '../experiences/distribution-monitor.types';
|
|
5
5
|
import { DistributionSummary } from '../experiences/journey.types';
|
|
@@ -48,6 +48,7 @@ export type DrawSequence = DrawScheduled | DrawEnterable | DrawParticipating | D
|
|
|
48
48
|
export interface DrawScheduled {
|
|
49
49
|
/** Mechanism discriminator for draw narrowing. */
|
|
50
50
|
mechanism: "draw";
|
|
51
|
+
selectionMode?: SelectionMode;
|
|
51
52
|
/** Phase discriminator; scheduled draws cannot be entered yet. */
|
|
52
53
|
phase: "scheduled";
|
|
53
54
|
/** Draw distribution facts from the journey projector. */
|
|
@@ -61,6 +62,7 @@ export interface DrawScheduled {
|
|
|
61
62
|
export interface DrawEnterable {
|
|
62
63
|
/** Mechanism discriminator for draw narrowing. */
|
|
63
64
|
mechanism: "draw";
|
|
65
|
+
selectionMode?: SelectionMode;
|
|
64
66
|
/** Phase discriminator; `enter()` is legal on the matching view. */
|
|
65
67
|
phase: "enterable";
|
|
66
68
|
/** Open draw distribution facts from the journey projector. */
|
|
@@ -87,6 +89,7 @@ export interface DrawEnterable {
|
|
|
87
89
|
export interface DrawParticipating {
|
|
88
90
|
/** Mechanism discriminator for draw narrowing. */
|
|
89
91
|
mechanism: "draw";
|
|
92
|
+
selectionMode?: SelectionMode;
|
|
90
93
|
/** Phase discriminator; the draw display is live while participating. */
|
|
91
94
|
phase: "participating";
|
|
92
95
|
/** Draw distribution facts from the journey projector. */
|
|
@@ -102,6 +105,7 @@ export interface DrawParticipating {
|
|
|
102
105
|
export interface DrawSettling {
|
|
103
106
|
/** Mechanism discriminator for draw narrowing. */
|
|
104
107
|
mechanism: "draw";
|
|
108
|
+
selectionMode?: SelectionMode;
|
|
105
109
|
/** Phase discriminator; no consumer action is legal while settling. */
|
|
106
110
|
phase: "settling";
|
|
107
111
|
/** Settling draw distribution facts from the journey projector. */
|
|
@@ -117,6 +121,7 @@ export interface DrawSettling {
|
|
|
117
121
|
export interface DrawGranted {
|
|
118
122
|
/** Mechanism discriminator for draw narrowing. */
|
|
119
123
|
mechanism: "draw";
|
|
124
|
+
selectionMode?: SelectionMode;
|
|
120
125
|
/** Phase discriminator; `claim()` is legal on the matching view. */
|
|
121
126
|
phase: "granted";
|
|
122
127
|
/** Draw distribution facts from the journey projector. */
|
|
@@ -143,6 +148,7 @@ export interface DrawGranted {
|
|
|
143
148
|
export interface DrawEnded {
|
|
144
149
|
/** Mechanism discriminator for draw narrowing. */
|
|
145
150
|
mechanism: "draw";
|
|
151
|
+
selectionMode?: SelectionMode;
|
|
146
152
|
/** Phase discriminator; no draw actions are legal after this phase. */
|
|
147
153
|
phase: "ended";
|
|
148
154
|
/** Draw distribution facts from the journey projector. */
|
|
@@ -172,6 +178,7 @@ export interface DrawScheduledView {
|
|
|
172
178
|
phase: "scheduled";
|
|
173
179
|
/** Mechanism discriminator for draw rendering. */
|
|
174
180
|
mechanism: "draw";
|
|
181
|
+
selectionMode?: SelectionMode;
|
|
175
182
|
/** Draw distribution facts from the journey projector. */
|
|
176
183
|
distribution: DistributionSummary & {
|
|
177
184
|
type: "draw";
|
|
@@ -193,6 +200,7 @@ export type DrawEnterableView = {
|
|
|
193
200
|
phase: "enterable";
|
|
194
201
|
/** Mechanism discriminator for draw rendering. */
|
|
195
202
|
mechanism: "draw";
|
|
203
|
+
selectionMode?: SelectionMode;
|
|
196
204
|
/** Money moves after the win; entry places no hold. */
|
|
197
205
|
checkoutMode: "at_end";
|
|
198
206
|
/** Open draw distribution facts from the journey projector. */
|
|
@@ -216,6 +224,7 @@ export type DrawEnterableView = {
|
|
|
216
224
|
phase: "enterable";
|
|
217
225
|
/** Mechanism discriminator for draw rendering. */
|
|
218
226
|
mechanism: "draw";
|
|
227
|
+
selectionMode?: SelectionMode;
|
|
219
228
|
/** Fanfare places a payment authorization hold at entry and captures it on win. */
|
|
220
229
|
checkoutMode: "pre_auth";
|
|
221
230
|
/** Open draw distribution facts from the journey projector. */
|
|
@@ -258,6 +267,7 @@ export interface DrawParticipatingView {
|
|
|
258
267
|
phase: "participating";
|
|
259
268
|
/** Mechanism discriminator for draw rendering. */
|
|
260
269
|
mechanism: "draw";
|
|
270
|
+
selectionMode?: SelectionMode;
|
|
261
271
|
/** Consumer draw participation facts. */
|
|
262
272
|
consumer: DrawSequenceConsumerState;
|
|
263
273
|
/** Live draw display facts, such as participant counts and draw timing. */
|
|
@@ -282,6 +292,7 @@ export interface DrawSettlingView {
|
|
|
282
292
|
phase: "settling";
|
|
283
293
|
/** Mechanism discriminator for draw rendering. */
|
|
284
294
|
mechanism: "draw";
|
|
295
|
+
selectionMode?: SelectionMode;
|
|
285
296
|
/** Settling draw distribution facts from the journey projector. */
|
|
286
297
|
distribution: DistributionSummary & {
|
|
287
298
|
type: "draw";
|
|
@@ -295,6 +306,7 @@ interface DrawGrantedViewBase {
|
|
|
295
306
|
phase: "granted";
|
|
296
307
|
/** Mechanism discriminator for draw rendering. */
|
|
297
308
|
mechanism: "draw";
|
|
309
|
+
selectionMode?: SelectionMode;
|
|
298
310
|
/** Draw distribution facts from the journey projector. */
|
|
299
311
|
distribution: DistributionSummary & {
|
|
300
312
|
type: "draw";
|
|
@@ -375,6 +387,7 @@ export type DrawEndedView = {
|
|
|
375
387
|
phase: "ended";
|
|
376
388
|
/** Mechanism discriminator for draw rendering. */
|
|
377
389
|
mechanism: "draw";
|
|
390
|
+
selectionMode?: SelectionMode;
|
|
378
391
|
/** Consumer draw facts at the terminal outcome. */
|
|
379
392
|
consumer: DrawSequenceConsumerState;
|
|
380
393
|
/** Server-derived terminal outcome for the draw participation. */
|
|
@@ -390,6 +403,7 @@ export type DrawEndedView = {
|
|
|
390
403
|
phase: "ended";
|
|
391
404
|
/** Mechanism discriminator for draw rendering. */
|
|
392
405
|
mechanism: "draw";
|
|
406
|
+
selectionMode?: SelectionMode;
|
|
393
407
|
/** Consumer draw facts at the terminal outcome. */
|
|
394
408
|
consumer: DrawSequenceConsumerState;
|
|
395
409
|
/** Server-derived terminal outcome for the draw participation. */
|
|
@@ -411,6 +425,7 @@ export type DrawEndedView = {
|
|
|
411
425
|
phase: "ended";
|
|
412
426
|
/** Mechanism discriminator for draw rendering. */
|
|
413
427
|
mechanism: "draw";
|
|
428
|
+
selectionMode?: SelectionMode;
|
|
414
429
|
/** Consumer draw facts at the terminal outcome. */
|
|
415
430
|
consumer: DrawSequenceConsumerState;
|
|
416
431
|
/** Server-derived terminal outcome for the draw participation. */
|
|
@@ -445,6 +460,7 @@ export interface DrawGrantedAwaitingAssignmentView {
|
|
|
445
460
|
phase: "granted";
|
|
446
461
|
/** Mechanism discriminator. */
|
|
447
462
|
mechanism: "draw";
|
|
463
|
+
selectionMode?: SelectionMode;
|
|
448
464
|
/** Distribution associated with this grant. */
|
|
449
465
|
distribution: DistributionSummary & {
|
|
450
466
|
type: "draw";
|
|
@@ -466,6 +482,7 @@ export interface DrawGrantedSelectionRequiredView {
|
|
|
466
482
|
phase: "granted";
|
|
467
483
|
/** Mechanism discriminator. */
|
|
468
484
|
mechanism: "draw";
|
|
485
|
+
selectionMode?: SelectionMode;
|
|
469
486
|
/** Distribution associated with this grant. */
|
|
470
487
|
distribution: DistributionSummary & {
|
|
471
488
|
type: "draw";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AuthenticationRoutingGateV1Schema as e,AccessCodeRoutingGateV1Schema as t,BotCheckRoutingGateV1Schema as i}from"@fanfare-io/fanfare-sdk-contracts/routing";import{GrantedSelectionSchema as s,SelectionChoiceSchema as r}from"@fanfare-io/fanfare-sdk-contracts/selection";import{atom as n,computed as o}from"nanostores";import*as a from"valibot";import{createAppointmentDriver as c,withAppointmentTerminalConsumer as d}from"../appointments/appointment.driver.js";import{createAuctionDriver as u,isUpgradeableGenericLoss as h,withAuctionTerminalConsumer as l}from"../auctions/auction.driver.js";import{createError as p,isFanfareError as m,ErrorCodes as g}from"../core/errors.js";import{createLogger as y}from"../core/logger.js";import{generateId as f}from"../core/utils.js";import{createDrawDriver as b,withDrawTerminalConsumer as S}from"../draws/draw.driver.js";import{createQueueDriver as I,withQueueTerminalConsumer as v}from"../queues/queue.driver.js";import{clearExperienceContext as A,clearSequenceContext as q,resolveCapabilityOptions as w,bindDistributionContext as k,bindWaitlist as C,upsertSequenceToken as x,peekSequenceToken as j,getSequenceTokenExpiryMs as T}from"../state/capability-token-registry.js";import{getEventBus as D}from"../state/events.js";import{getSDKStore as E}from"../state/store.js";import{createTimedReleaseDriver as R,withTimedReleaseTerminalConsumer as O}from"../timed-releases/timed-release.driver.js";import{NoSequenceAvailableError as M}from"./experience.module.js";import{buildJourneyView as G}from"./journey-view.js";import{createInitialSnapshot as F,getSequencePhase as _,normalizeSequenceState as P,buildSnapshot as H,getSequenceId as N,getConsumer as z,getWaitlistAttachment as U,getDistribution as B,getOutcome as L,getGrant as J,getSequenceState as W,getCheckout as Q,isPreEntryJourney as V,getGates as $,isRoutedState as K,getAdmissionGrantExpiresAt as X,getParticipation as Y,validateSequenceState as Z}from"./journey.machine.js";import{isUnresolvedSettlementConsumer as ee}from"./settlement.js";const te="Cannot commit a stale sequence transition",ie="Cannot commit a sequence transition before routing",se=3e4,re=/* @__PURE__ */new Set([g.RATE_LIMITED,g.OVERLOADED,g.SERVICE_UNAVAILABLE,g.TIMEOUT,g.NETWORK_ERROR]),ne=[2e3,5e3,1e4],oe=3*ne.length,ae=[2e3,5e3,1e4];function ce(e,t){if("scheduled"!==e?.lifecycle||!e.opensAt)return!1;const i=Date.parse(e.opensAt);return Number.isFinite(i)&&i<=t}function de(e){const t=Y(e);if(t)return t;if(!K(e))return;const i=e.sequence;return"enterable"===i.phase&&"mechanism"in i&&"auction"===i.mechanism?{id:i.distribution.id,type:"auction"}:void 0}function ue(e,t){return"routing"!==e.journeyStage&&("routed"!==e.journeyStage||e.sequenceId!==t||"granted"===e.sequence.phase&&"awaiting_assignment"!==e.sequence.selection.status||"ended"===e.sequence.phase)}class he{constructor(e,t){this.experienceId=e,this.sdk=t,this.store=E(),this.routingSession=this.store.session,this.logger=y(),this.activeMonitor=null,this.selfCheckStartedAtMs=0,this.selfCheckAttempts=0,this.selfCheckTotalAttempts=0,this.consecutiveRefreshFailures=0,this.checkoutStarted=!1,this.displayAtom=null,this.destroyed=!1,this.operationQueue=Promise.resolve(),this.lastClearedSequenceId=null,this.restoredSnapshotNeedsPersist=!1,this.EVENT_BUFFER_LIMIT=20;const i=this.restoreFromStore(),s=i??F(this.experienceId),r=i?de(i):void 0,a=_(s);!r||"participating"!==a&&"enterable"!==a||this.ensureDisplayAtom(r),this.stateAtom=n(s),this.state=this.stateAtom,this.sequenceDrivers=this.createSequenceDrivers(),this.view$=o(this.stateAtom,e=>this.buildView(e)),this.events$=o(this.stateAtom,e=>e.events),this.latestEvent$=o(this.stateAtom,e=>{if(!e.events.length)return null;const t=e.lastSeenEventId??"",i=e.events.filter(e=>e.id>t);return i.length?i[i.length-1]:null}),i?(this.restoredSnapshotNeedsPersist&&this.persist(),this.rearmTimersIfNeeded()):this.persist()}getExperienceId(){return this.experienceId}async start(e){await this.runSerializedOperation(async()=>{e?.reset&&(this.clearRoutedRuntimeState(),this.setSnapshot(F(this.experienceId))),"accessCode"in(e??{})&&this.patchJourneyBase({accessCode:e?.accessCode??null}),await this.routeAndLoadDistribution(this.stateAtom.get().accessCode)})}async reroute(e={}){await this.runSerializedOperation(async()=>{"accessCode"in e&&this.patchJourneyBase({accessCode:e.accessCode??null}),await this.routeAndLoadDistribution(e.accessCode??this.stateAtom.get().accessCode)})}async submitAccessCode(e){return await this.runSerializedOperation(async()=>{const t=this.stateAtom.get();if("routed"!==t.journeyStage){await this.routeAndLoadDistribution(e,{transient:!0});const t=this.stateAtom.get();return"routed"!==t.journeyStage?"gated"===t.journeyStage?{outcome:"gated"}:{outcome:"unchanged"}:(this.patchJourneyBase({accessCode:e}),{outcome:"advanced",sequenceId:t.sequenceId})}const i=t.sequenceId,s=t.accessCode,r=new Set(t.offers.map(e=>e.sequence.id));await this.routeAndLoadDistribution(e,{transient:!0});let n=this.stateAtom.get();return"routed"===n.journeyStage&&n.sequenceId===i?{outcome:"unchanged"}:"routed"===n.journeyStage&&r.has(n.sequenceId)?(this.patchJourneyBase({accessCode:e}),{outcome:"advanced",sequenceId:n.sequenceId}):("string"==typeof s&&s!==e&&(await this.routeAndLoadDistribution(s,{carryFrom:t,transient:!0}),n=this.stateAtom.get()),"gated"===n.journeyStage?{outcome:"gated"}:{outcome:"unchanged"})})}async retry(){await this.runSerializedOperation(()=>this.routeAndLoadDistribution(this.stateAtom.get().accessCode))}destroy(){this.destroyed||(this.destroyed=!0,this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearGrantHydration(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),this.stopPolling(),A(this.experienceId),this.store.removeJourney(this.experienceId),this.stateAtom.set(F(this.experienceId)))}async resumeFromMe(e){const t=e.active.journeys.find(e=>e.experienceId===this.experienceId&&"routed"===e.journeyStage);if(!t||"routed"!==t.journeyStage)return!1;const i=this.stateAtom.get(),s=P({sequence:Ue(t.sequence)}),r="granted"===s.phase&&!("routed"===i.journeyStage&&i.sequenceId===t.sequenceId&&"granted"===i.sequence.phase),n=H({base:this.baseFromSnapshot(i),journeyStage:"routed",sequenceId:t.sequenceId,offers:this.normalizeOffers(t.offers),sequence:s,waitlist:this.buildWaitlistAttachmentFromMe(e,t.sequenceId)});this.setSnapshot(n),"routed"===i.journeyStage&&i.sequenceId!==t.sequenceId&&q(this.experienceId,i.sequenceId);try{await this.reroute()}catch{}return"granted"!==s.phase&&"ended"!==s.phase||(this.stopRuntimeMonitoring(!0),this.resetDistributionSelfCheck()),r&&"granted"===s.phase&&(this.clearGrantExpiryTimer(),this.checkoutStarted=!1),this.rearmTimersIfNeeded(),r&&"granted"===s.phase&&"granted"===_(this.stateAtom.get())&&(this.emitEvent("sequence_change","success","user","Grant issued",{grant:s.grant.token}),D().emit("journey:granted",{experienceId:this.experienceId,sequenceId:t.sequenceId,grant:s.grant.token,distributionType:s.grant.distributionType})),!0}async refreshDistribution(){await this.runSerializedOperation(async()=>{const e=this.stateAtom.get();try{const t=N(e);if(!t)throw p.validationError("Cannot refresh distribution before routing to a sequence");const i=await this.sdk.experiences.getCurrentDistributions(t,w({experienceId:this.experienceId,sequenceId:t})),s=this.stateAtom.get();if(N(s)!==t)return;const r=z(s),n=this.buildDistributionSummary(i,t,{consumer:r,settlingDistributionId:"routed"===s.journeyStage&&"settling"===s.sequence.phase?s.sequence.distribution.id:void 0}),o=this.buildWaitlistAttachmentFromContext(i,U(s)),a=B(s);n&&k({experienceId:this.experienceId,sequenceId:t,distributionContext:n}),o&&C({waitlistId:o.waitlistId,experienceId:this.experienceId,sequenceId:t});const c=this.deriveTerminalOutcomeForClosedDistribution(r,n,L(s)),d=this.withTerminalConsumer(r,c),u=!n&&"routed"===s.journeyStage&&("granted"===s.sequence.phase||"ended"===s.sequence.phase)?s.sequence:this.projectSequenceState({distribution:n,consumer:d,grant:J(s),settlement:Le(s),selection:Je(s),checkout:Be(s),outcome:c});this.commit(u,{waitlist:o,lastSyncedAt:Date.now(),degraded:!1}),this.emitIfDistributionChanged(a,n),"granted"===u.phase||"ended"===u.phase?this.resetDistributionSelfCheck():this.evaluateDistributionSelfCheck(n)}catch(t){const i=this.stateAtom.get();if(N(i)===N(e)&&"routed"===i.journeyStage&&this.isQuietableDegradationError(t))throw this.markDegraded(),this.markErrorQuietable(t);throw t}})}async joinWaitlistAttachment(){await this.runSerializedOperation(async()=>{const e=this.stateAtom.get(),t=W(e),i=B(e),s=U(e)?.waitlistId;if("scheduled"!==t?.phase||!i||!s)throw p.validationError("Waitlist is not available for this sequence");const r=await this.sdk.waitlists.enter(s);this.commit(t,{waitlist:{waitlistId:s,status:"waitlisted",entryId:r.id}}),this.emitEvent("sequence_change","info","user","Entered waitlist",{waitlistId:s})})}async exitWaitlistAttachment(){await this.runSerializedOperation(async()=>{const e=this.stateAtom.get(),t=W(e),i=B(e),s=U(e)?.waitlistId;"scheduled"===t?.phase&&i&&s&&(await this.sdk.waitlists.leave(s),this.commit(t,{waitlist:{waitlistId:s,status:"not_waitlisted"}}),this.emitEvent("sequence_change","info","user","Left waitlist",{waitlistId:s}))})}async loadSelectionOptions(){const e=N(this.stateAtom.get());if(!e)throw p.validationError("No sequence is available to load selection options");return this.sdk.selections.loadOptions(e,w({experienceId:this.experienceId,sequenceId:e}))}async select(e){await this.runSerializedOperation(async()=>{const t=this.stateAtom.get();if("routed"!==t.journeyStage)throw p.validationError("No sequence is available to select against");const i=t.sequence;if(!("participating"===i.phase&&"draw"===i.mechanism||"granted"===i.phase&&"timed_release"!==i.mechanism))throw p.validationError("Selection is not available in the current phase");const s=t.sequenceId,r=await this.sdk.selections.select(s,e,w({experienceId:this.experienceId,sequenceId:s})),n=this.stateAtom.get();if("routed"!==n.journeyStage||n.sequenceId!==s)return;const o=n.sequence;if("participating"===i.phase){if("participating"!==o.phase||"draw"!==o.mechanism||o.distribution.id!==i.distribution.id||o.consumer.id!==i.consumer.id)return;if("recorded"!==r.status)return;this.commit({...o,consumer:{...o.consumer,selection:{productId:r.productId,variantId:r.variantId}}});const e=this.displayAtom?.get();"draw"===e?.type&&this.displayAtom?.set({...e,selectionAvailability:void 0})}else{if("granted"!==o.phase||o.mechanism!==i.mechanism||o.grant.token!==i.grant.token)return;if("recorded"===r.status)return;this.commit({...o,selection:r})}})}claim(){const e=this.stateAtom.get();if("routed"===e.journeyStage&&"granted"===e.sequence.phase&&"resolved"!==e.sequence.selection.status)throw p.validationError("Selection must be resolved before claiming the grant");const t=J(e);if(!t)throw p.validationError("No grant is available to claim");return this.checkoutStarted=!0,this.clearGrantExpiryTimer(),this.clearCapabilityRefreshTimer(),this.emitEvent("sequence_change","success","user","Grant claimed",{distributionType:t.distributionType,distributionId:t.distributionId,sequenceId:t.sequenceId}),D().emit("journey:grant-claimed",{experienceId:this.experienceId,sequenceId:t.sequenceId,grant:t.token}),t}async confirmCheckout(e){await this.runCheckoutOperation(()=>this.submitCheckout(e))}async resumeCheckout(){await this.runCheckoutOperation(async()=>{const e=this.pendingCheckoutPaymentInput;if(!e)throw p.validationError("No paused checkout to resume");await this.submitCheckout(e)})}async runCheckoutOperation(e){try{await this.runSerializedOperation(e)}catch(t){if(await this.reconcileMissingCheckoutAdmission(t))return void(this.pendingCheckoutPaymentInput=void 0);throw t}}async reconcileMissingCheckoutAdmission(e){if(!m(e)||e.code!==g.ADMISSION_NOT_FOUND)return!1;const t=N(this.stateAtom.get());try{const e=await this.sdk.experiences.getMe();if(this.destroyed||N(this.stateAtom.get())!==t)return!1;const i=await this.resumeFromMe(e),s=this.stateAtom.get();return i&&N(s)===t&&"ended"===_(s)&&void 0!==Q(s)}catch{return!1}}async submitCheckout(e){const t=this.stateAtom.get(),i=W(t);if("granted"!==i?.phase||"internal"!==i.settlement.processor||"at_end"!==i.settlement.mode||"resolved"!==i.selection.status||this.checkoutStarted)throw p.validationError("No grant awaiting embedded checkout");const s=N(t),r=i.grant.token;this.clearGrantExpiryTimer();try{let t;try{t=await this.sdk.experiences.confirmCheckout(r,i.grant.distributionId,e)}catch(n){throw m(n)&&n.code===g.ADMISSION_EXPIRED&&this.transitionToEnded({type:"expired"}),n}const o=this.stateAtom.get(),a=W(o);if(N(o)!==s||"granted"!==a?.phase||a.grant.token!==r)throw p.validationError("Grant changed before checkout could be confirmed");if("requires_action"===t.outcome)return this.pendingCheckoutPaymentInput=e,this.commit({...a,pendingAction:t.nextAction}),void this.emitEvent("sequence_change","info","user","Checkout awaiting verification",{processor:t.nextAction.processor});this.pendingCheckoutPaymentInput=void 0,this.transitionToEnded({checkout:t.checkout})}finally{const e=W(this.stateAtom.get());"granted"!==e?.phase||e.pendingAction||this.rearmTimersIfNeeded()}}ackEvent(e){this.stateAtom.get().events.some(t=>t.id===e)&&this.patchJourneyBase({lastSeenEventId:e})}ackAllEvents(){const e=this.stateAtom.get();if(!e.events.length)return;const t=e.events[e.events.length-1];this.patchJourneyBase({lastSeenEventId:t.id})}async routeAndLoadDistribution(e,t){let i=t?.carryFrom??this.stateAtom.get();const s=this.store.session;(s?.consumerId!==this.routingSession?.consumerId||s?.type!==this.routingSession?.type)&&"routed"===i.journeyStage&&V(i)&&(this.clearRoutedRuntimeState(),q(this.experienceId,i.sequenceId),i=H({base:this.baseFromSnapshot(i),journeyStage:"ready"}),this.setSnapshot(i)),this.routingSession=s;const r=i,n=N(r);let o,a=!1;try{const i=await this.resolveRouting(e,{transient:t?.transient});if(!i||this.destroyed)return;if(o=this.stateAtom.get().revision,a=n===i.sequenceId,await this.enterExperienceIfReady(),this.destroyed)return;const s=await this.sdk.experiences.getCurrentDistributions(i.sequenceId,w({experienceId:this.experienceId,sequenceId:i.sequenceId}));if(this.destroyed)return;const c=a?z(r):void 0,d=this.buildDistributionSummary(s,i.sequenceId,{consumer:c,settlingDistributionId:a&&"routed"===r.journeyStage&&"settling"===r.sequence.phase?r.sequence.distribution.id:void 0}),u=this.buildWaitlistAttachmentFromContext(s,a?U(r):void 0);d&&k({experienceId:this.experienceId,sequenceId:i.sequenceId,distributionContext:d}),u&&C({waitlistId:u.waitlistId,experienceId:this.experienceId,sequenceId:i.sequenceId});const h=a?J(r):void 0,l=a?Be(r):void 0,p=a?Le(r):void 0,m=a?this.deriveTerminalOutcomeForClosedDistribution(c,d,L(r)):void 0,g=this.withTerminalConsumer(c,m),y=!d&&a&&"routed"===r.journeyStage&&("granted"===r.sequence.phase||"ended"===r.sequence.phase)?r.sequence:this.projectSequenceState({distribution:d,consumer:g,grant:h,settlement:p,selection:a?Je(r):void 0,checkout:l,outcome:m});a||(this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearGrantHydration(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck());const f=this.stateAtom.get(),b=H({base:this.baseFromSnapshot(f,{lastSyncedAt:Date.now(),degraded:!1}),journeyStage:"routed",sequenceId:i.sequenceId,offers:i.offers,sequence:y,waitlist:u,sequenceRef:i.selectedSequence});this.setSnapshot(b),this.resumeDeferredGrantHydration(),this.consecutiveRefreshFailures=0,this.rearmTimersIfNeeded();const S=a?B(r):void 0;this.emitIfDistributionChanged(S,d),this.evaluateDistributionSelfCheck(d)}catch(c){if("routed"===r.journeyStage&&a&&this.isQuietableDegradationError(c))throw this.restoreQuietSnapshot(r),this.markErrorQuietable(c);if("routing"===this.stateAtom.get().journeyStage)if(this.lastClearedSequenceId===n&&this.restoreClearedSequenceContext(r,n),void 0!==o&&this.stateAtom.get().revision===o)this.setSnapshot(r);else{const e=this.stateAtom.get();"routed"===r.journeyStage?this.setSnapshot(H({base:this.baseFromSnapshot(e),journeyStage:"routed",sequenceId:r.sequenceId,offers:r.offers,sequence:r.sequence,waitlist:r.waitlist,sequenceRef:r.sequenceRef})):this.setSnapshot(H({base:this.baseFromSnapshot(e),journeyStage:"ready"}))}throw c}}restoreClearedSequenceContext(e,t){const i=B(e);i&&k({experienceId:this.experienceId,sequenceId:t,distributionContext:i});const s=U(e);s&&C({waitlistId:s.waitlistId,experienceId:this.experienceId,sequenceId:t}),this.lastClearedSequenceToken&&x({experienceId:this.experienceId,sequenceId:t,token:this.lastClearedSequenceToken.token,expiresAt:this.lastClearedSequenceToken.expiresAt}),this.lastClearedSequenceId=null,this.lastClearedSequenceToken=void 0}async resolveRouting(e,t){const i=this.stateAtom.get(),s=N(i);let r;this.transitionToRouting();try{r=await this.sdk.experiences.findSequence(this.experienceId,e)}catch(o){throw this.setSnapshot(i),"routed"===i.journeyStage&&this.armCapabilityRefreshTimer(),this.emitEvent("error","error","user","Failed to route experience"),o}if(this.destroyed)return null;if("gated"===r.outcome&&r.selected){const e=r.selected.gates;return"routed"===i.journeyStage&&this.clearRoutedRuntimeState(),this.transitionToGated({gates:e,selected:{sequence:r.selected.sequence,status:"gated"}}),this.emitEvent("requirement","info","user","Gates required",{gates:e}),null}if("no_access"===r.outcome||!r.selected)throw this.setSnapshot(i),this.emitEvent("error","error","user","No access available for this experience"),new M("No access available for this experience");const n=r.selected.sequence.id;if(s&&s!==n&&(this.lastClearedSequenceId=s,this.lastClearedSequenceToken=j(this.experienceId,s),q(this.experienceId,s)),r.selected.capabilityGrant&&x({experienceId:this.experienceId,sequenceId:n,token:r.selected.capabilityGrant,expiresAt:r.selected.capabilityGrantExpiresAt}),s!==n){const e="routed"===i.journeyStage?i.sequenceRef?.priority:void 0,o=r.selected.sequence.priority,a=function(e,t){return void 0===e?"unknown":t>e?"upgrade":t<e?"downgrade":"lateral"}(e,o);this.emitEvent("reroute","downgrade"===a?"warning":"info",t?.transient?"system":"user","downgrade"===a?"Sequence downgraded":"Sequence changed",{previousSequenceId:s,sequenceId:n,...void 0===e?{}:{previousPriority:e},priority:o,direction:a})}return{sequenceId:n,selectedSequence:r.selected.sequence,offers:r.offers}}async enterExperienceIfReady(){const e=this.stateAtom.get();if($(e).length>0)return;if(e.experience)return;const t=await this.sdk.experiences.enter(this.experienceId);this.destroyed||this.patchJourneyBase({experience:t})}createSequenceDrivers(){return{appointment:c({appointments:this.sdk.appointments,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>W(this.stateAtom.get()),getDisplayState:()=>this.displayAtom?.get()??null,commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e),ensureDisplayAtom:e=>this.ensureDisplayAtom(e),stopRuntimeMonitoring:e=>this.stopRuntimeMonitoring(e),emitEvent:(e,t,i,s,r)=>this.emitEvent(e,t,i,s,r)}),auction:u({auctions:this.sdk.auctions,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>W(this.stateAtom.get()),commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e)}),queue:I({queues:this.sdk.queues,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>W(this.stateAtom.get()),commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e),ensureDisplayAtom:e=>{this.ensureDisplayAtom(e)},stopRuntimeMonitoring:e=>this.stopRuntimeMonitoring(e),emitEvent:(e,t,i,s,r)=>this.emitEvent(e,t,i,s,r)}),timed_release:R({timedReleases:this.sdk.timedReleases,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>W(this.stateAtom.get()),commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e),ensureDisplayAtom:e=>{this.ensureDisplayAtom(e)},stopRuntimeMonitoring:e=>this.stopRuntimeMonitoring(e),emitEvent:(e,t,i,s,r)=>this.emitEvent(e,t,i,s,r)}),draw:b({draws:this.sdk.draws,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>W(this.stateAtom.get()),commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e),ensureDisplayAtom:e=>{this.ensureDisplayAtom(e)},stopRuntimeMonitoring:e=>this.stopRuntimeMonitoring(e),emitEvent:(e,t,i,s,r)=>this.emitEvent(e,t,i,s,r)})}}buildView(e){return G(e,{start:e=>this.start(e),reroute:e=>this.reroute(e),submitAccessCode:e=>this.submitAccessCode(e),retry:()=>this.retry(),joinWaitlist:()=>this.joinWaitlistAttachment(),exitWaitlist:()=>this.exitWaitlistAttachment(),claim:()=>this.claim(),select:e=>this.select(e),loadSelectionOptions:()=>this.loadSelectionOptions(),canConfirmCheckout:()=>!this.checkoutStarted,confirmCheckout:e=>this.confirmCheckout(e),resumeCheckout:()=>this.resumeCheckout()},this.displayAtom,this.sequenceDrivers)}projectSequenceState(e){if(!e.distribution)return{phase:"unavailable"};const t=this.sequenceDrivers[e.distribution.type];if(!t)throw new Error(`${e.distribution.type} sequence driver is required`);return t.project(e)}patchJourneyBase(e){if(this.destroyed)return;const t=this.stateAtom.get(),i=this.baseFromSnapshot(t,e);switch(t.journeyStage){case"ready":return void this.setSnapshot(H({base:i,journeyStage:"ready"}));case"routing":return void this.setSnapshot(H({base:i,journeyStage:"routing"}));case"gated":return void this.setSnapshot(H({base:i,journeyStage:"gated",gates:t.gates,selected:t.selected}));case"routed":return void this.setSnapshot(H({base:i,journeyStage:"routed",sequenceId:t.sequenceId,offers:t.offers,sequence:t.sequence,waitlist:t.waitlist,sequenceRef:t.sequenceRef}))}}transitionToRouting(){if(this.destroyed)return;const e=this.stateAtom.get();this.setSnapshot(H({base:this.baseFromSnapshot(e),journeyStage:"routing"}))}transitionToGated(e){if(this.destroyed)return;const t=this.stateAtom.get();this.setSnapshot(H({base:this.baseFromSnapshot(t),journeyStage:"gated",gates:e.gates,selected:e.selected}))}baseFromSnapshot(e,t={}){const i=Object.prototype.hasOwnProperty.call(t,"accessCode")?t.accessCode??void 0:e.accessCode,s=Object.prototype.hasOwnProperty.call(t,"degraded")?t.degraded||void 0:e.degraded,r=Object.prototype.hasOwnProperty.call(t,"lastSyncedAt")?t.lastSyncedAt:e.lastSyncedAt;return{revision:e.revision,updatedAt:e.updatedAt,experienceId:e.experienceId,accessCode:i,experience:t.experience??e.experience,events:t.events??e.events,lastSeenEventId:t.lastSeenEventId??e.lastSeenEventId,degraded:s,lastSyncedAt:r}}commit(e,t={}){if(this.destroyed)throw p.notInitialized("Journey has been destroyed");const i=this.stateAtom.get();if("routed"!==i.journeyStage)throw p.validationError(ie);if(!function(e,t){if("distribution"in e&&e.distribution.sequenceId&&e.distribution.sequenceId!==t)return!1;return!0}(e,i.sequenceId))throw p.validationError(te);const s=Object.prototype.hasOwnProperty.call(t,"waitlist")?t.waitlist??void 0:i.waitlist,r={};Object.prototype.hasOwnProperty.call(t,"lastSyncedAt")&&(r.lastSyncedAt=t.lastSyncedAt),Object.prototype.hasOwnProperty.call(t,"degraded")&&(r.degraded=t.degraded);const n=H({base:this.baseFromSnapshot(i,{...r,events:t.events??i.events}),journeyStage:"routed",sequenceId:i.sequenceId,offers:i.offers,sequence:e,waitlist:s,sequenceRef:i.sequenceRef});this.setSnapshot(n)}markDegraded(){if(this.destroyed)return;const e=this.stateAtom.get();e.degraded||this.setSnapshot(this.rebuildSnapshot(e,{degraded:!0}))}clearDegraded(){if(this.destroyed)return;const e=this.stateAtom.get();e.degraded&&this.setSnapshot(this.rebuildSnapshot(e,{degraded:!1}))}restoreQuietSnapshot(e){this.setSnapshot(this.rebuildSnapshot(e,{degraded:!0}))}isQuietableDegradationError(e){return m(e)&&(e.retryable||re.has(e.code))}markErrorQuietable(e){return e&&"object"==typeof e&&(e.quietable=!0),e}rebuildSnapshot(e,t={}){const i=this.baseFromSnapshot(e,t);switch(e.journeyStage){case"ready":return H({base:i,journeyStage:"ready"});case"routing":return H({base:i,journeyStage:"routing"});case"gated":return H({base:i,journeyStage:"gated",gates:e.gates,selected:e.selected});case"routed":return H({base:i,journeyStage:"routed",sequenceId:e.sequenceId,offers:e.offers,sequence:e.sequence,waitlist:e.waitlist,sequenceRef:e.sequenceRef})}}emitEvent(e,t,i,s,r){const n=this.stateAtom.get(),o={id:f(),ts:Date.now(),kind:e,severity:t,audience:i,message:s,detail:r},a=[...n.events,o],c=a.length>this.EVENT_BUFFER_LIMIT?a.slice(a.length-this.EVENT_BUFFER_LIMIT):a;this.patchJourneyBase({events:c})}emitIfDistributionChanged(e,t){e?.id===t?.id&&e?.lifecycle===t?.lifecycle||this.emitEvent("distribution_change","info","user","Distribution context changed",{previous:e,next:t})}buildDistributionSummary(e,t,i){if(e.active){const s=this.sequenceDrivers[e.active.type],r=!0===s?.settlementCanStartWhileActive&&i?.settlingDistributionId===e.active.id?"settling":"open";return{type:e.active.type,id:e.active.id,sequenceId:t,lifecycle:r,details:e.active.details,opensAt:e.active.details.openAt,closesAt:e.active.details.closeAt,updatedAt:Date.now()}}if(e.upcoming)return{type:e.upcoming.type,id:e.upcoming.id,sequenceId:t,lifecycle:"scheduled",startsAt:e.upcoming.startsAt,opensAt:e.upcoming.startsAt,updatedAt:Date.now()};if(e.recentPast){const s=i?.settlingDistributionId===e.recentPast.id||ee(i?.consumer,e.recentPast.type,e.recentPast.id)?"settling":"closed";return{type:e.recentPast.type,id:e.recentPast.id,sequenceId:t,lifecycle:s,result:e.recentPast.result,closesAt:e.recentPast.endedAt,updatedAt:Date.now()}}}buildWaitlistAttachmentFromContext(e,t){const i=e.waitlist?.id;if(i)return t?.waitlistId===i?t:{waitlistId:i,status:"not_waitlisted"}}buildWaitlistAttachmentFromMe(e,t){const i=e.waitlists?.find(e=>e.experienceId===this.experienceId&&e.sequenceId===t);if(i)return{waitlistId:i.waitlistId,status:"waitlisted"}}normalizeOffers(e){return Array.isArray(e)?e.filter(Boolean):[]}restoreFromStore(){const e=this.store.activeJourneys;if(!e||!e[this.experienceId])return null;const t=ze(e[this.experienceId]);return t?"routing"===t.journeyStage||"routed"===t.journeyStage&&V(t)?("routed"===t.journeyStage&&q(this.experienceId,t.sequenceId),this.restoredSnapshotNeedsPersist=!0,H({base:this.baseFromSnapshot(t),journeyStage:"ready"})):t:(this.store.removeJourney(this.experienceId),null)}persist(){this.store.setJourneyState(this.experienceId,this.stateAtom.get())}setSnapshot(e,t={}){if(this.destroyed)return;const i=this.stateAtom.get(),s=de(e);"auction"===s?.type&&"auction"!==this.displayAtom?.get().type&&(this.resetDisplayAtom("auction"),this.displayParticipationId=s.id),this.stateAtom.set(e),!1!==t.persist&&this.persist(),this.emitPhaseChanged(i,e)}emitPhaseChanged(e,t){const i=e.journeyStage,s="routed"===i?_(e):void 0,r=t.journeyStage,n="routed"===r?_(t):void 0;i===r&&s===n||D().emit("journey:phase-changed",{experienceId:this.experienceId,journeyStage:r,sequencePhase:n})}runSerializedOperation(e){const t=this.operationQueue.then(async()=>{if(this.destroyed)throw p.notInitialized("Journey has been destroyed");return e()});return this.operationQueue=t.then(()=>{},()=>{}),t}transitionToEnded(e,t={}){if(this.destroyed)return;const i=this.stateAtom.get(),s=N(i);if(!s)throw p.validationError(ie);const r=B(i),n="checkout"in e?e.checkout:void 0,o="checkout"in e?{type:"completed"}:e,a=this.reinterpretLapsedGrantOutcome(i,o),c={...a,distributionType:a.distributionType??r?.type,distributionId:a.distributionId??r?.id,at:a.at??/* @__PURE__ */(new Date).toISOString()},d=this.withTerminalConsumer(z(i),c,{finalize:!0}),u=this.projectSequenceState({distribution:r,consumer:d,checkout:n,outcome:c});this.commit(u,t),this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearGrantHydration(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),this.emitEvent("sequence_change","expired"===c.type?"warning":"info","user","Sequence ended",{outcome:c}),D().emit("journey:ended",{experienceId:this.experienceId,sequenceId:s,outcome:c})}reinterpretLapsedGrantOutcome(e,t){if("granted"!==_(e))return t;return"closed"===t.type&&("not_queued"===t.reason||"not_entered"===t.reason)?{type:"expired",at:t.at,distributionType:t.distributionType,distributionId:t.distributionId}:t}applyMonitorUpdate(e){if(!this.destroyed){if("settling"===e.type){const t=this.stateAtom.get();if(!K(t)||"participating"!==t.sequence.phase)return;const i={...t.sequence.distribution,lifecycle:"settling",settlesAt:e.at},s=this.projectSequenceState({distribution:i,consumer:z(t)});if("settling"!==s.phase)return;return void this.commit(s,{lastSyncedAt:Date.now(),degraded:!1})}"granted"!==e.type?"resync"!==e.type?this.transitionToEnded(e.outcome,{lastSyncedAt:Date.now(),degraded:!1}):this.beginGrantHydration():this.beginGrantHydration(e.token,e.expiresAt)}}beginGrantHydration(e,t){const i=this.stateAtom.get();"routing"!==i.journeyStage?"routed"===i.journeyStage&&(ue(i,i.sequenceId)||this.pendingGrantHydration?.sequenceId!==i.sequenceId&&(this.clearGrantHydration(),this.pendingGrantHydration={sequenceId:i.sequenceId,token:e,expiresAt:t,attempt:0},this.hydrateGrantFromMe(e,t))):this.pendingGrantObservation={token:e,expiresAt:t}}resumeDeferredGrantHydration(){const e=this.pendingGrantObservation;e&&(this.pendingGrantObservation=void 0,this.beginGrantHydration(e.token,e.expiresAt))}async hydrateGrantFromMe(e,t){if(this.destroyed)return;const i=this.pendingGrantHydration,s=this.stateAtom.get();if(i)if("routing"!==s.journeyStage)if(ue(s,i.sequenceId))this.clearGrantHydration();else if(void 0!==t&&Date.now()>=t)this.transitionToEnded({type:"expired"},{lastSyncedAt:Date.now(),degraded:!1});else{try{const e=await this.sdk.experiences.getMe();if(this.destroyed)return;await this.resumeFromMe(e)}catch(r){this.emitEvent("error","warning","system","Could not resolve an observed grant from /me",{grant:e,error:r instanceof Error?r.message:String(r)})}this.scheduleGrantHydrationRetry()}else this.scheduleGrantHydrationRetry()}scheduleGrantHydrationRetry(){const e=this.pendingGrantHydration;if(!e||this.destroyed)return;if(ue(this.stateAtom.get(),e.sequenceId))return void this.clearGrantHydration();const t=ae[e.attempt]??1e4;e.attempt+=1,e.timer=setTimeout(()=>{this.pendingGrantHydration===e&&(e.timer=void 0,this.hydrateGrantFromMe(e.token,e.expiresAt))},t)}clearGrantHydration(){const e=this.pendingGrantHydration;e?.timer&&clearTimeout(e.timer),this.pendingGrantHydration=void 0,this.pendingGrantObservation=void 0}applyMonitorUpdateFromCallback(e){try{this.applyMonitorUpdate(e)}catch(t){if(this.dropStaleCallbackCommit(t,"monitor"))return;throw t}}startMonitorForParticipation(e){const t=this.ensureDisplayAtom(e),i=e=>this.applyMonitorUpdateFromCallback(e),s=e=>{e?this.markDegraded():this.clearDegraded()},r=this.sequenceDrivers[e.type];if(r?.startMonitoring)return r.startMonitoring({participation:e,displayAtom:t,onUpdate:i,onDegradedChange:s}),void(this.activeMonitor={type:e.type,id:e.id,stop:()=>r.stopMonitoring?.()});throw new Error(`Unknown distribution type: ${e.type}`)}stopRuntimeMonitoring(e=!1){this.activeMonitor&&(this.activeMonitor.stop(),this.activeMonitor=null),e&&this.clearRuntimeDisplayState()}clearGrantExpiryTimer(){this.grantExpiryTimer&&(clearTimeout(this.grantExpiryTimer),this.grantExpiryTimer=void 0)}clearCapabilityRefreshTimer(){this.capabilityRefreshTimer&&(clearTimeout(this.capabilityRefreshTimer),this.capabilityRefreshTimer=void 0)}clearDistributionSelfCheck(){this.selfCheckTimer&&(clearTimeout(this.selfCheckTimer),this.selfCheckTimer=void 0),this.selfCheckKey=void 0,this.selfCheckStartedAtMs=0,this.selfCheckAttempts=0}resetDistributionSelfCheck(){this.clearDistributionSelfCheck(),this.selfCheckTotalAttempts=0}evaluateDistributionSelfCheck(e){if(this.destroyed)return;const t=Date.now();if(!ce(e,t))return void this.clearDistributionSelfCheck();const i=`${e?.sequenceId??""}:${e?.id??""}:${e?.opensAt??""}`;if(this.selfCheckKey!==i&&(this.clearDistributionSelfCheck(),this.selfCheckKey=i,this.selfCheckStartedAtMs=t),this.selfCheckTimer)return;if(this.selfCheckAttempts>=ne.length)return;if(this.selfCheckTotalAttempts>=oe)return;const s=this.selfCheckStartedAtMs+ne[this.selfCheckAttempts];this.selfCheckAttempts+=1,this.selfCheckTotalAttempts+=1,this.selfCheckTimer=setTimeout(()=>{this.selfCheckFromTimer()},Math.max(0,s-t))}async selfCheckFromTimer(){if(this.selfCheckTimer=void 0,!this.destroyed)try{await this.refreshDistribution()}catch(e){if(this.destroyed||"routed"!==this.stateAtom.get().journeyStage)return;this.emitEvent("error","warning","system","Distribution self-check failed",{error:e instanceof Error?e.message:String(e)})}}armCapabilityRefreshTimer(){if(this.clearCapabilityRefreshTimer(),this.destroyed||this.checkoutStarted)return;const e=this.stateAtom.get();if("routed"!==e.journeyStage)return;const t=T(this.experienceId,e.sequenceId);if(void 0===t)return;const i=Math.max(t-Date.now()-6e4,5e3);this.scheduleCapabilityRefresh(i)}scheduleCapabilityRefresh(e){if(this.clearCapabilityRefreshTimer(),this.destroyed||this.checkoutStarted)return;"routed"===this.stateAtom.get().journeyStage&&(this.capabilityRefreshTimer=setTimeout(()=>this.refreshCapabilityFromTimer(),e))}rearmTimersIfNeeded(){if(this.destroyed||this.checkoutStarted)return;const e=this.stateAtom.get();"routed"===e.journeyStage&&this.armCapabilityRefreshTimer(),this.pendingGrantHydration&&ue(e,this.pendingGrantHydration.sequenceId)&&this.scheduleGrantHydrationRetry(),"routed"===e.journeyStage&&"granted"===e.sequence.phase&&"awaiting_assignment"===e.sequence.selection.status&&this.pendingGrantHydration?.sequenceId!==e.sequenceId&&(this.clearGrantHydration(),this.pendingGrantHydration={sequenceId:e.sequenceId,token:e.sequence.grant.token,expiresAt:X(e),attempt:0},this.scheduleGrantHydrationRetry());const t=W(e);if("granted"===t?.phase&&(t.pendingAction||"internal"===t.settlement.processor&&"at_end"===t.settlement.mode&&"in_progress"===t.settlement.state))this.clearGrantExpiryTimer();else if("granted"===t?.phase&&!this.grantExpiryTimer){const t=X(e);if(t){const e=t-Date.now();e<=0?this.transitionToEnded({type:"expired"}):this.grantExpiryTimer=setTimeout(()=>this.expireGrantFromTimer(),e)}}}async refreshCapabilityFromTimer(){this.capabilityRefreshTimer=void 0;try{if("routed"!==this.stateAtom.get().journeyStage)return void this.clearCapabilityRefreshTimer();if(this.checkoutStarted)return;const e=Date.now();if(void 0!==this.lastCapabilityRefreshAtMs&&e-this.lastCapabilityRefreshAtMs<se)return void this.scheduleCapabilityRefresh(se);this.lastCapabilityRefreshAtMs=e,await this.retry(),this.consecutiveRefreshFailures=0}catch(e){if(this.dropStaleCallbackCommit(e,"capability refresh timer"))return;const t=Math.min(se*2**this.consecutiveRefreshFailures,6e5);this.consecutiveRefreshFailures+=1,this.emitEvent("error","warning","system","Capability grant refresh failed",{error:e instanceof Error?e.message:String(e),consecutiveFailures:this.consecutiveRefreshFailures}),this.scheduleCapabilityRefresh(t)}}expireGrantFromTimer(){try{this.transitionToEnded({type:"expired"})}catch(e){if(this.dropStaleCallbackCommit(e,"grant-expiry timer"))return;throw e}}dropStaleCallbackCommit(e,t){return!(!m(e)||e.code!==g.VALIDATION_ERROR||e.message!==te&&e.message!==ie)&&(this.logger.debug("Dropped stale journey callback",{experienceId:this.experienceId,source:t,message:e.message}),!0)}getRuntimeBinding(){const e=this.stateAtom.get(),t=de(e),i=N(e);return t&&i?{experienceId:this.experienceId,sequenceId:i,participationId:t.id,participationType:t.type}:null}startRuntimeMonitoring(){const e=this.getRuntimeBinding();if(!e)return;const t=this.activeMonitor;t&&t.id===e.participationId&&t.type===e.participationType&&this.displayAtom||(this.stopRuntimeMonitoring(!1),this.startMonitorForParticipation({id:e.participationId,type:e.participationType}))}getRuntimeDisplayAtom(){return this.displayAtom}applyRuntimeState(e){if(!e)return void this.clearRuntimeDisplayState();const t=this.getRuntimeBinding();if(!t)return;this.ensureDisplayAtom({id:t.participationId,type:t.participationType}).set(e)}reconcileSyncedSnapshot(e){if(this.destroyed)return;if(!e)return this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearGrantHydration(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),void this.setSnapshot(F(this.experienceId),{persist:!1});const t=ze(e);if(!t)return;const i="routing"===t.journeyStage?H({base:this.baseFromSnapshot(t),journeyStage:"ready"}):t,s=this.stateAtom.get();if(s.revision===i.revision&&s.updatedAt===i.updatedAt)return;const r=de(i);r||(this.displayAtom=null,this.displayParticipationId=void 0),this.setSnapshot(i,{persist:!1}),r?this.ensureDisplayAtom(r):this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),this.rearmTimersIfNeeded()}ensureDisplayAtom(e){const t=this.displayAtom;if(t?.get().type===e.type&&this.displayParticipationId===e.id)return t;const i=this.resetDisplayAtom(e.type);return this.displayParticipationId=e.id,i}resetDisplayAtom(e){const t=this.displayAtom;if(!t||t.get().type!==e){const t=n({type:e});return this.displayAtom=t,t}return t.set({type:e}),t}clearRuntimeDisplayState(){const e=this.getRuntimeBinding();if(!e)return this.displayAtom=null,void(this.displayParticipationId=void 0);this.displayParticipationId=void 0,this.resetDisplayAtom(e.participationType)}clearRoutedRuntimeState(){this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),this.checkoutStarted=!1}deriveTerminalOutcomeForClosedDistribution(e,t,i){if(i&&!h(i))return i;if(!t||"closed"!==t.lifecycle||!e)return i;const s=this.projectSequenceState({distribution:t,consumer:e});return"ended"===s.phase&&"lost"===s.outcome.type?s.outcome:i??{type:"closed",distributionType:t.type,distributionId:t.id}}withTerminalConsumer(e,t,i){switch(e?.mechanism){case"appointment":return d(e,t);case"auction":return l(e,t,i);case"draw":return S(e,t);case"queue":return v(e,t);case"timed_release":return O(e,t);default:return e}}stopPolling(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0)}}const le=a.picklist(["queue","draw","auction","timed_release","appointment"]),pe=le,me=a.picklist(["queue","draw","auction","timed_release"]),ge=a.picklist(["draw","auction"]),ye=a.strictObject({id:a.string(),ts:a.number(),kind:a.picklist(["reroute","sequence_change","distribution_change","requirement","error","info"]),severity:a.picklist(["info","success","warning","error"]),audience:a.picklist(["user","system","analytics"]),message:a.string(),detail:a.optional(a.record(a.string(),a.unknown()))}),fe=a.strictObject({id:a.string(),name:a.string(),experienceId:a.string(),priority:a.number(),color:a.string()}),be=a.strictObject({type:le,id:a.string(),sequenceId:a.optional(a.string()),lifecycle:a.string(),startsAt:a.optional(a.string()),opensAt:a.optional(a.string()),closesAt:a.optional(a.string()),settlesAt:a.optional(a.string()),result:a.optional(a.string()),details:a.optional(a.unknown()),updatedAt:a.optional(a.number())}),Se=a.strictObject({status:a.string(),selection:a.optional(r),id:a.optional(a.string()),distributionId:a.optional(a.string()),waitlistId:a.optional(a.string()),enteredAt:a.optional(a.string()),admissionGrant:a.optional(a.string()),grantedAt:a.optional(a.string()),deniedReason:a.optional(a.string()),position:a.optional(a.number()),highestBid:a.optional(a.string()),currentBid:a.optional(a.string()),slotId:a.optional(a.string()),locationId:a.optional(a.string()),bookedAt:a.optional(a.string()),checkedInAt:a.optional(a.string()),completedAt:a.optional(a.string()),cancelledAt:a.optional(a.string()),noShowAt:a.optional(a.string())}),Ie=a.strictObject({token:a.string(),distributionType:me,distributionId:a.string(),sequenceId:a.string(),experienceId:a.string(),issuedAt:a.optional(a.string()),expiresAt:a.optional(a.string())}),ve=a.strictObject({orderId:a.string(),amount:a.string(),currencyCode:a.string(),paymentMethodLast4:a.optional(a.string()),paymentMethodBrand:a.optional(a.string())}),Ae=a.strictObject({publishableKey:a.string(),stripeAccount:a.optional(a.string())}),qe=a.strictObject({type:a.string(),reason:a.optional(a.string()),at:a.optional(a.string()),distributionType:a.optional(le),distributionId:a.optional(a.string())}),we=a.strictObject({phase:a.literal("unavailable"),reason:a.optional(a.string())}),ke=a.strictObject({waitlistId:a.string(),status:a.picklist(["not_waitlisted","waitlisted"]),entryId:a.optional(a.string())}),Ce=a.strictObject({phase:a.literal("scheduled"),mechanism:pe,distribution:be}),xe=a.strictObject({phase:a.literal("enterable"),mechanism:pe,distribution:be,consumer:Se,paymentProvider:a.optional(Ae)}),je=a.strictObject({phase:a.literal("participating"),mechanism:pe,distribution:be,consumer:Se}),Te=a.strictObject({phase:a.literal("settling"),mechanism:ge,distribution:be,consumer:Se}),De=a.variant("processor",[a.strictObject({processor:a.literal("external")}),a.strictObject({processor:a.literal("internal"),mode:a.literal("at_end"),state:a.picklist(["awaiting","in_progress"]),paymentProvider:a.optional(Ae)}),a.strictObject({processor:a.literal("internal"),mode:a.literal("pre_auth")})]),Ee=a.strictObject({phase:a.literal("granted"),mechanism:me,distribution:be,consumer:Se,grant:Ie,settlement:De,selection:s}),Re=a.strictObject({phase:a.literal("ended"),mechanism:pe,distribution:be,consumer:Se,outcome:qe,checkout:a.optional(ve)}),Oe=a.union([we,Ce,xe,je,Te,Ee,Re]),Me={schemaVersion:a.literal(5),revision:a.number(),updatedAt:a.number(),experienceId:a.string(),accessCode:a.optional(a.string()),experience:a.optional(a.unknown()),events:a.array(ye),lastSeenEventId:a.optional(a.string()),lastSyncedAt:a.optional(a.number())},Ge=a.strictObject({...Me,journeyStage:a.literal("ready")}),Fe=a.strictObject({...Me,journeyStage:a.literal("routing")}),_e=a.variant("type",[a.object({...a.omit(e,["reason"]).entries,requirement:a.optional(a.picklist(["session","authenticated"]),"authenticated")}),a.omit(t,["reason"]),a.omit(i,["reason"])]),Pe=a.strictObject({...Me,journeyStage:a.literal("gated"),gates:a.array(_e),selected:a.optional(a.strictObject({sequence:a.unknown(),status:a.literal("gated")}))}),He=a.strictObject({...Me,journeyStage:a.literal("routed"),sequenceId:a.string(),offers:a.array(a.object({sequence:a.unknown(),status:a.literal("gated"),gates:a.array(_e)})),sequence:Oe,waitlist:a.optional(ke),sequenceRef:a.optional(fe)}),Ne=a.union([Ge,Fe,Pe,He]);function ze(e){const t=a.safeParse(Ne,e);if(!t.success)return null;const{schemaVersion:i,...s}=t.output;if("routed"===s.journeyStage)try{Z(s.sequence)}catch{return null}return s}function Ue(e){if("participating"!==e.phase&&"settling"!==e.phase)return e;if(!("selection"in e))return e;const{selection:t,...i}=e;return void 0===t?i:{...i,consumer:{...i.consumer,selection:t}}}function Be(e){return"routed"!==e.journeyStage||"granted"!==e.sequence.phase&&"ended"!==e.sequence.phase||!("checkout"in e.sequence)?Q(e):e.sequence.checkout}function Le(e){if("routed"===e.journeyStage&&"granted"===e.sequence.phase)return e.sequence.settlement}function Je(e){if("routed"===e.journeyStage&&"granted"===e.sequence.phase)return e.sequence.selection}export{he as ExperienceJourney,ce as isSelfContradictingDistribution};
|
|
1
|
+
import{AuthenticationRoutingGateV1Schema as e,AccessCodeRoutingGateV1Schema as t,BotCheckRoutingGateV1Schema as i}from"@fanfare-io/fanfare-sdk-contracts/routing";import{SelectionModes as s,GrantedSelectionSchema as r,SelectionPinRequestSchema as n}from"@fanfare-io/fanfare-sdk-contracts/selection";import{atom as o,computed as a}from"nanostores";import*as c from"valibot";import{createAppointmentDriver as d,withAppointmentTerminalConsumer as u}from"../appointments/appointment.driver.js";import{createAuctionDriver as h,isUpgradeableGenericLoss as l,withAuctionTerminalConsumer as p}from"../auctions/auction.driver.js";import{createError as m,isFanfareError as g,ErrorCodes as y}from"../core/errors.js";import{createLogger as f}from"../core/logger.js";import{generateId as b}from"../core/utils.js";import{createDrawDriver as S,withDrawTerminalConsumer as I}from"../draws/draw.driver.js";import{createQueueDriver as v,withQueueTerminalConsumer as q}from"../queues/queue.driver.js";import{clearExperienceContext as A,clearSequenceContext as w,resolveCapabilityOptions as k,bindDistributionContext as C,bindWaitlist as j,upsertSequenceToken as x,peekSequenceToken as T,getSequenceTokenExpiryMs as R}from"../state/capability-token-registry.js";import{getEventBus as E}from"../state/events.js";import{getSDKStore as D}from"../state/store.js";import{createTimedReleaseDriver as M,withTimedReleaseTerminalConsumer as O}from"../timed-releases/timed-release.driver.js";import{NoSequenceAvailableError as G}from"./experience.module.js";import{buildJourneyView as F}from"./journey-view.js";import{createInitialSnapshot as _,getSequencePhase as P,normalizeSequenceState as H,buildSnapshot as N,getSequenceId as z,getConsumer as U,getWaitlistAttachment as B,getDistribution as L,getOutcome as J,getGrant as W,getSequenceState as Q,getCheckout as V,isPreEntryJourney as $,getGates as K,isRoutedState as X,getAdmissionGrantExpiresAt as Y,getParticipation as Z,validateSequenceState as ee}from"./journey.machine.js";import{isUnresolvedSettlementConsumer as te}from"./settlement.js";const ie="Cannot commit a stale sequence transition",se="Cannot commit a sequence transition before routing",re=3e4,ne=6e5,oe=/* @__PURE__ */new Set([y.RATE_LIMITED,y.OVERLOADED,y.SERVICE_UNAVAILABLE,y.TIMEOUT,y.NETWORK_ERROR]),ae=[2e3,5e3,1e4],ce=3*ae.length,de=[2e3,5e3,1e4];function ue(e,t){if("scheduled"!==e?.lifecycle||!e.opensAt)return!1;const i=Date.parse(e.opensAt);return Number.isFinite(i)&&i<=t}function he(e){const t=Z(e);if(t)return t;if(!X(e))return;const i=e.sequence;return"enterable"===i.phase&&"mechanism"in i&&"auction"===i.mechanism?{id:i.distribution.id,type:"auction"}:void 0}function le(e,t){return"routing"!==e.journeyStage&&("routed"!==e.journeyStage||e.sequenceId!==t||"granted"===e.sequence.phase&&"awaiting_assignment"!==e.sequence.selection.status||"ended"===e.sequence.phase)}class pe{constructor(e,t){this.experienceId=e,this.sdk=t,this.store=D(),this.routingSession=this.store.session,this.logger=f(),this.activeMonitor=null,this.selfCheckStartedAtMs=0,this.selfCheckAttempts=0,this.selfCheckTotalAttempts=0,this.consecutiveRefreshFailures=0,this.consecutiveGatedRestores=0,this.checkoutStarted=!1,this.displayAtom=null,this.destroyed=!1,this.operationQueue=Promise.resolve(),this.lastClearedSequenceId=null,this.restoredSnapshotNeedsPersist=!1,this.EVENT_BUFFER_LIMIT=20;const i=this.restoreFromStore(),s=i??_(this.experienceId),r=i?he(i):void 0,n=P(s);!r||"participating"!==n&&"enterable"!==n||this.ensureDisplayAtom(r),this.stateAtom=o(s),this.state=this.stateAtom,this.sequenceDrivers=this.createSequenceDrivers(),this.view$=a(this.stateAtom,e=>this.buildView(e)),this.events$=a(this.stateAtom,e=>e.events),this.latestEvent$=a(this.stateAtom,e=>{if(!e.events.length)return null;const t=e.lastSeenEventId??"",i=e.events.filter(e=>e.id>t);return i.length?i[i.length-1]:null}),i?(this.restoredSnapshotNeedsPersist&&this.persist(),this.rearmTimersIfNeeded()):this.persist()}getExperienceId(){return this.experienceId}async start(e){await this.runSerializedOperation(async()=>{e?.reset&&(this.clearRoutedRuntimeState(),this.setSnapshot(_(this.experienceId))),"accessCode"in(e??{})&&this.patchJourneyBase({accessCode:e?.accessCode??null}),await this.routeAndLoadDistribution(this.stateAtom.get().accessCode)})}async reroute(e={}){await this.runSerializedOperation(async()=>{"accessCode"in e&&this.patchJourneyBase({accessCode:e.accessCode??null}),await this.routeAndLoadDistribution(e.accessCode??this.stateAtom.get().accessCode)})}async submitAccessCode(e){return await this.runSerializedOperation(async()=>{const t=this.stateAtom.get();if("routed"!==t.journeyStage){await this.routeAndLoadDistribution(e,{transient:!0});const t=this.stateAtom.get();return"routed"!==t.journeyStage?"gated"===t.journeyStage?{outcome:"gated"}:{outcome:"unchanged"}:(this.patchJourneyBase({accessCode:e}),{outcome:"advanced",sequenceId:t.sequenceId})}const i=t.sequenceId,s=t.accessCode,r=new Set(t.offers.map(e=>e.sequence.id));await this.routeAndLoadDistribution(e,{transient:!0});let n=this.stateAtom.get();return"routed"===n.journeyStage&&n.sequenceId===i?{outcome:"unchanged"}:"routed"===n.journeyStage&&r.has(n.sequenceId)?(this.patchJourneyBase({accessCode:e}),{outcome:"advanced",sequenceId:n.sequenceId}):("string"==typeof s&&s!==e&&(await this.routeAndLoadDistribution(s,{carryFrom:t,transient:!0}),n=this.stateAtom.get()),"gated"===n.journeyStage?{outcome:"gated"}:{outcome:"unchanged"})})}async retry(){await this.runSerializedOperation(()=>this.routeAndLoadDistribution(this.stateAtom.get().accessCode))}destroy(){this.destroyed||(this.destroyed=!0,this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearGrantHydration(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),this.stopPolling(),A(this.experienceId),this.store.removeJourney(this.experienceId),this.stateAtom.set(_(this.experienceId)))}async resumeFromMe(e){const t=e.active.journeys.find(e=>e.experienceId===this.experienceId&&"routed"===e.journeyStage);if(!t||"routed"!==t.journeyStage)return!1;const i=this.stateAtom.get(),s=H({sequence:Le(t.sequence)}),r="granted"===s.phase&&!("routed"===i.journeyStage&&i.sequenceId===t.sequenceId&&"granted"===i.sequence.phase),n=N({base:this.baseFromSnapshot(i),journeyStage:"routed",sequenceId:t.sequenceId,offers:this.normalizeOffers(t.offers),sequence:s,waitlist:this.buildWaitlistAttachmentFromMe(e,t.sequenceId)});this.setSnapshot(n),"routed"===i.journeyStage&&i.sequenceId!==t.sequenceId&&w(this.experienceId,i.sequenceId);try{await this.reroute()}catch{}return"granted"!==s.phase&&"ended"!==s.phase||(this.stopRuntimeMonitoring(!0),this.resetDistributionSelfCheck()),r&&"granted"===s.phase&&(this.clearGrantExpiryTimer(),this.checkoutStarted=!1),this.rearmTimersIfNeeded(),r&&"granted"===s.phase&&"granted"===P(this.stateAtom.get())&&(this.emitEvent("sequence_change","success","user","Grant issued",{grant:s.grant.token}),E().emit("journey:granted",{experienceId:this.experienceId,sequenceId:t.sequenceId,grant:s.grant.token,distributionType:s.grant.distributionType})),!0}async refreshDistribution(){await this.runSerializedOperation(async()=>{const e=this.stateAtom.get();try{const t=z(e);if(!t)throw m.validationError("Cannot refresh distribution before routing to a sequence");const i=await this.sdk.experiences.getCurrentDistributions(t,k({experienceId:this.experienceId,sequenceId:t})),s=this.stateAtom.get();if(z(s)!==t)return;const r=U(s),n=this.buildDistributionSummary(i,t,{consumer:r,settlingDistributionId:"routed"===s.journeyStage&&"settling"===s.sequence.phase?s.sequence.distribution.id:void 0}),o=this.buildWaitlistAttachmentFromContext(i,B(s)),a=L(s);n&&C({experienceId:this.experienceId,sequenceId:t,distributionContext:n}),o&&j({waitlistId:o.waitlistId,experienceId:this.experienceId,sequenceId:t});const c=this.deriveTerminalOutcomeForClosedDistribution(r,n,J(s)),d=this.withTerminalConsumer(r,c),u=!n&&"routed"===s.journeyStage&&("granted"===s.sequence.phase||"ended"===s.sequence.phase)?s.sequence:this.projectSequenceState({distribution:n,consumer:d,selectionMode:Ve(s),grant:W(s),settlement:We(s),selection:Qe(s),checkout:Je(s),outcome:c});this.commit(u,{waitlist:o,lastSyncedAt:Date.now(),degraded:!1}),this.emitIfDistributionChanged(a,n),"granted"===u.phase||"ended"===u.phase?this.resetDistributionSelfCheck():this.evaluateDistributionSelfCheck(n)}catch(t){const i=this.stateAtom.get();if(z(i)===z(e)&&"routed"===i.journeyStage&&this.isQuietableDegradationError(t))throw this.markDegraded(),this.markErrorQuietable(t);throw t}})}async joinWaitlistAttachment(){await this.runSerializedOperation(async()=>{const e=this.stateAtom.get(),t=Q(e),i=L(e),s=B(e)?.waitlistId;if("scheduled"!==t?.phase||!i||!s)throw m.validationError("Waitlist is not available for this sequence");const r=await this.sdk.waitlists.enter(s);this.commit(t,{waitlist:{waitlistId:s,status:"waitlisted",entryId:r.id}}),this.emitEvent("sequence_change","info","user","Entered waitlist",{waitlistId:s})})}async exitWaitlistAttachment(){await this.runSerializedOperation(async()=>{const e=this.stateAtom.get(),t=Q(e),i=L(e),s=B(e)?.waitlistId;"scheduled"===t?.phase&&i&&s&&(await this.sdk.waitlists.leave(s),this.commit(t,{waitlist:{waitlistId:s,status:"not_waitlisted"}}),this.emitEvent("sequence_change","info","user","Left waitlist",{waitlistId:s}))})}async loadSelectionOptions(){const e=z(this.stateAtom.get());if(!e)throw m.validationError("No sequence is available to load selection options");return this.sdk.selections.loadOptions(e,k({experienceId:this.experienceId,sequenceId:e}))}async select(e){await this.runSerializedOperation(async()=>{const t=this.stateAtom.get();if("routed"!==t.journeyStage)throw m.validationError("No sequence is available to select against");const i=t.sequence;if(!("participating"===i.phase&&"draw"===i.mechanism||"granted"===i.phase&&"timed_release"!==i.mechanism))throw m.validationError("Selection is not available in the current phase");const s=t.sequenceId,r=await this.sdk.selections.select(s,e,k({experienceId:this.experienceId,sequenceId:s})),n=this.stateAtom.get();if("routed"!==n.journeyStage||n.sequenceId!==s)return;const o=n.sequence;if("participating"===i.phase){if("participating"!==o.phase||"draw"!==o.mechanism||o.distribution.id!==i.distribution.id||o.consumer.id!==i.consumer.id)return;if("recorded"!==r.status)return;this.commit({...o,consumer:{...o.consumer,selection:{productId:r.productId,variantId:r.variantId}}});const e=this.displayAtom?.get();"draw"===e?.type&&this.displayAtom?.set({...e,selectionAvailability:void 0})}else{if("granted"!==o.phase||o.mechanism!==i.mechanism||o.grant.token!==i.grant.token)return;if("recorded"===r.status)return;this.commit({...o,selection:r})}})}claim(){const e=this.stateAtom.get();if("routed"===e.journeyStage&&"granted"===e.sequence.phase&&"resolved"!==e.sequence.selection.status)throw m.validationError("Selection must be resolved before claiming the grant");const t=W(e);if(!t)throw m.validationError("No grant is available to claim");return this.checkoutStarted=!0,this.clearGrantExpiryTimer(),this.clearCapabilityRefreshTimer(),this.emitEvent("sequence_change","success","user","Grant claimed",{distributionType:t.distributionType,distributionId:t.distributionId,sequenceId:t.sequenceId}),E().emit("journey:grant-claimed",{experienceId:this.experienceId,sequenceId:t.sequenceId,grant:t.token}),t}async confirmCheckout(e){await this.runCheckoutOperation(()=>this.submitCheckout(e))}async resumeCheckout(){await this.runCheckoutOperation(async()=>{const e=this.pendingCheckoutPaymentInput;if(!e)throw m.validationError("No paused checkout to resume");await this.submitCheckout(e)})}async runCheckoutOperation(e){try{await this.runSerializedOperation(e)}catch(t){if(await this.reconcileMissingCheckoutAdmission(t))return void(this.pendingCheckoutPaymentInput=void 0);throw t}}async reconcileMissingCheckoutAdmission(e){if(!g(e)||e.code!==y.ADMISSION_NOT_FOUND)return!1;const t=z(this.stateAtom.get());try{const e=await this.sdk.experiences.getMe();if(this.destroyed||z(this.stateAtom.get())!==t)return!1;const i=await this.resumeFromMe(e),s=this.stateAtom.get();return i&&z(s)===t&&"ended"===P(s)&&void 0!==V(s)}catch{return!1}}async submitCheckout(e){const t=this.stateAtom.get(),i=Q(t);if("granted"!==i?.phase||"internal"!==i.settlement.processor||"at_end"!==i.settlement.mode||"resolved"!==i.selection.status||this.checkoutStarted)throw m.validationError("No grant awaiting embedded checkout");const s=z(t),r=i.grant.token;this.clearGrantExpiryTimer();try{let t;try{t=await this.sdk.experiences.confirmCheckout(r,i.grant.distributionId,e)}catch(n){throw g(n)&&n.code===y.ADMISSION_EXPIRED&&this.transitionToEnded({type:"expired"}),n}const o=this.stateAtom.get(),a=Q(o);if(z(o)!==s||"granted"!==a?.phase||a.grant.token!==r)throw m.validationError("Grant changed before checkout could be confirmed");if("requires_action"===t.outcome)return this.pendingCheckoutPaymentInput=e,this.commit({...a,pendingAction:t.nextAction}),void this.emitEvent("sequence_change","info","user","Checkout awaiting verification",{processor:t.nextAction.processor});this.pendingCheckoutPaymentInput=void 0,this.transitionToEnded({checkout:t.checkout})}finally{const e=Q(this.stateAtom.get());"granted"!==e?.phase||e.pendingAction||this.rearmTimersIfNeeded()}}ackEvent(e){this.stateAtom.get().events.some(t=>t.id===e)&&this.patchJourneyBase({lastSeenEventId:e})}ackAllEvents(){const e=this.stateAtom.get();if(!e.events.length)return;const t=e.events[e.events.length-1];this.patchJourneyBase({lastSeenEventId:t.id})}async routeAndLoadDistribution(e,t){let i=t?.carryFrom??this.stateAtom.get();const s=this.store.session;(s?.consumerId!==this.routingSession?.consumerId||s?.type!==this.routingSession?.type)&&"routed"===i.journeyStage&&$(i)&&(this.clearRoutedRuntimeState(),w(this.experienceId,i.sequenceId),i=N({base:this.baseFromSnapshot(i),journeyStage:"ready"}),this.setSnapshot(i)),this.routingSession=s;const r=i,n=z(r);let o,a=!1;try{const i=await this.resolveRouting(e,{transient:t?.transient});if(!i||this.destroyed)return;if(o=this.stateAtom.get().revision,a=n===i.sequenceId,await this.enterExperienceIfReady(),this.destroyed)return;const s=await this.sdk.experiences.getCurrentDistributions(i.sequenceId,k({experienceId:this.experienceId,sequenceId:i.sequenceId}));if(this.destroyed)return;const c=a?U(r):void 0,d=this.buildDistributionSummary(s,i.sequenceId,{consumer:c,settlingDistributionId:a&&"routed"===r.journeyStage&&"settling"===r.sequence.phase?r.sequence.distribution.id:void 0}),u=this.buildWaitlistAttachmentFromContext(s,a?B(r):void 0);d&&C({experienceId:this.experienceId,sequenceId:i.sequenceId,distributionContext:d}),u&&j({waitlistId:u.waitlistId,experienceId:this.experienceId,sequenceId:i.sequenceId});const h=a?W(r):void 0,l=a?Je(r):void 0,p=a?We(r):void 0,m=a?this.deriveTerminalOutcomeForClosedDistribution(c,d,J(r)):void 0,g=this.withTerminalConsumer(c,m),y=!d&&a&&"routed"===r.journeyStage&&("granted"===r.sequence.phase||"ended"===r.sequence.phase)?r.sequence:this.projectSequenceState({distribution:d,consumer:g,selectionMode:a?Ve(r):void 0,grant:h,settlement:p,selection:a?Qe(r):void 0,checkout:l,outcome:m});a||(this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearGrantHydration(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck());const f=this.stateAtom.get(),b=N({base:this.baseFromSnapshot(f,{lastSyncedAt:Date.now(),degraded:!1}),journeyStage:"routed",sequenceId:i.sequenceId,offers:i.offers,sequence:y,waitlist:u,sequenceRef:i.selectedSequence});this.setSnapshot(b),this.resumeDeferredGrantHydration(),this.consecutiveRefreshFailures=0,this.rearmTimersIfNeeded();const S=a?L(r):void 0;this.emitIfDistributionChanged(S,d),this.evaluateDistributionSelfCheck(d)}catch(c){if("routed"===r.journeyStage&&a&&this.isQuietableDegradationError(c))throw this.restoreQuietSnapshot(r),this.markErrorQuietable(c);if("routing"===this.stateAtom.get().journeyStage)if(this.lastClearedSequenceId===n&&this.restoreClearedSequenceContext(r,n),void 0!==o&&this.stateAtom.get().revision===o)this.setSnapshot(r);else{const e=this.stateAtom.get();"routed"===r.journeyStage?this.setSnapshot(N({base:this.baseFromSnapshot(e),journeyStage:"routed",sequenceId:r.sequenceId,offers:r.offers,sequence:r.sequence,waitlist:r.waitlist,sequenceRef:r.sequenceRef})):this.setSnapshot(N({base:this.baseFromSnapshot(e),journeyStage:"ready"}))}throw c}}restoreClearedSequenceContext(e,t){const i=L(e);i&&C({experienceId:this.experienceId,sequenceId:t,distributionContext:i});const s=B(e);s&&j({waitlistId:s.waitlistId,experienceId:this.experienceId,sequenceId:t}),this.lastClearedSequenceToken&&x({experienceId:this.experienceId,sequenceId:t,token:this.lastClearedSequenceToken.token,expiresAt:this.lastClearedSequenceToken.expiresAt}),this.lastClearedSequenceId=null,this.lastClearedSequenceToken=void 0}restoreUndisplacedJourney(e,t){const i=this.stateAtom.get();return i.revision===t?(this.setSnapshot(e),!0):"routing"===i.journeyStage&&(this.setSnapshot(N({base:this.baseFromSnapshot(i),journeyStage:"routed",sequenceId:e.sequenceId,offers:e.offers,sequence:e.sequence,waitlist:e.waitlist,sequenceRef:e.sequenceRef})),!0)}async resolveRouting(e,t){const i=this.stateAtom.get(),s=z(i);this.transitionToRouting();const r=this.stateAtom.get().revision;let n;try{n=await this.sdk.experiences.findSequence(this.experienceId,e)}catch(a){throw this.setSnapshot(i),"routed"===i.journeyStage&&this.armCapabilityRefreshTimer(),this.emitEvent("error","error","user","Failed to route experience"),a}if(this.destroyed)return null;if("gated"===n.outcome&&n.selected){const e=n.selected.gates;return"routed"!==i.journeyStage||$(i)?("routed"===i.journeyStage&&this.clearRoutedRuntimeState(),this.transitionToGated({gates:e,selected:{sequence:n.selected.sequence,status:"gated"}}),this.emitEvent("requirement","info","user","Gates required",{gates:e}),null):(this.restoreUndisplacedJourney(i,r)&&(this.rearmTimersIfNeeded(),"ended"!==P(this.stateAtom.get())&&(this.scheduleGatedCapabilityRefresh(),this.emitEvent("requirement","info","user","Gates required",{gates:e}))),null)}if("no_access"===n.outcome||!n.selected)throw this.setSnapshot(i),this.emitEvent("error","error","user","No access available for this experience"),new G("No access available for this experience");const o=n.selected.sequence.id;if(s&&s!==o&&(this.lastClearedSequenceId=s,this.lastClearedSequenceToken=T(this.experienceId,s),w(this.experienceId,s)),this.consecutiveGatedRestores=0,n.selected.capabilityGrant&&x({experienceId:this.experienceId,sequenceId:o,token:n.selected.capabilityGrant,expiresAt:n.selected.capabilityGrantExpiresAt}),s!==o){const e="routed"===i.journeyStage?i.sequenceRef?.priority:void 0,r=n.selected.sequence.priority,a=function(e,t){return void 0===e?"unknown":t>e?"upgrade":t<e?"downgrade":"lateral"}(e,r);this.emitEvent("reroute","downgrade"===a?"warning":"info",t?.transient?"system":"user","downgrade"===a?"Sequence downgraded":"Sequence changed",{previousSequenceId:s,sequenceId:o,...void 0===e?{}:{previousPriority:e},priority:r,direction:a})}return{sequenceId:o,selectedSequence:n.selected.sequence,offers:n.offers}}async enterExperienceIfReady(){const e=this.stateAtom.get();if(K(e).length>0)return;if(e.experience)return;const t=await this.sdk.experiences.enter(this.experienceId);this.destroyed||this.patchJourneyBase({experience:t})}createSequenceDrivers(){return{appointment:d({appointments:this.sdk.appointments,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>Q(this.stateAtom.get()),getDisplayState:()=>this.displayAtom?.get()??null,commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e),ensureDisplayAtom:e=>this.ensureDisplayAtom(e),stopRuntimeMonitoring:e=>this.stopRuntimeMonitoring(e),emitEvent:(e,t,i,s,r)=>this.emitEvent(e,t,i,s,r)}),auction:h({auctions:this.sdk.auctions,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>Q(this.stateAtom.get()),commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e)}),queue:v({queues:this.sdk.queues,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>Q(this.stateAtom.get()),commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e),ensureDisplayAtom:e=>{this.ensureDisplayAtom(e)},stopRuntimeMonitoring:e=>this.stopRuntimeMonitoring(e),emitEvent:(e,t,i,s,r)=>this.emitEvent(e,t,i,s,r)}),timed_release:M({timedReleases:this.sdk.timedReleases,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>Q(this.stateAtom.get()),commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e),ensureDisplayAtom:e=>{this.ensureDisplayAtom(e)},stopRuntimeMonitoring:e=>this.stopRuntimeMonitoring(e),emitEvent:(e,t,i,s,r)=>this.emitEvent(e,t,i,s,r)}),draw:S({draws:this.sdk.draws,runSerializedOperation:e=>this.runSerializedOperation(e),getCurrentSequence:()=>Q(this.stateAtom.get()),commit:(e,t)=>this.commit(e,t),applyMonitorUpdate:e=>this.applyMonitorUpdate(e),ensureDisplayAtom:e=>{this.ensureDisplayAtom(e)},stopRuntimeMonitoring:e=>this.stopRuntimeMonitoring(e),emitEvent:(e,t,i,s,r)=>this.emitEvent(e,t,i,s,r)})}}buildView(e){return F(e,{start:e=>this.start(e),reroute:e=>this.reroute(e),submitAccessCode:e=>this.submitAccessCode(e),retry:()=>this.retry(),joinWaitlist:()=>this.joinWaitlistAttachment(),exitWaitlist:()=>this.exitWaitlistAttachment(),claim:()=>this.claim(),select:e=>this.select(e),loadSelectionOptions:()=>this.loadSelectionOptions(),canConfirmCheckout:()=>!this.checkoutStarted,confirmCheckout:e=>this.confirmCheckout(e),resumeCheckout:()=>this.resumeCheckout()},this.displayAtom,this.sequenceDrivers)}projectSequenceState(e){if(!e.distribution)return{phase:"unavailable"};const t=this.sequenceDrivers[e.distribution.type];if(!t)throw new Error(`${e.distribution.type} sequence driver is required`);return t.project(e)}patchJourneyBase(e){if(this.destroyed)return;const t=this.stateAtom.get(),i=this.baseFromSnapshot(t,e);switch(t.journeyStage){case"ready":return void this.setSnapshot(N({base:i,journeyStage:"ready"}));case"routing":return void this.setSnapshot(N({base:i,journeyStage:"routing"}));case"gated":return void this.setSnapshot(N({base:i,journeyStage:"gated",gates:t.gates,selected:t.selected}));case"routed":return void this.setSnapshot(N({base:i,journeyStage:"routed",sequenceId:t.sequenceId,offers:t.offers,sequence:t.sequence,waitlist:t.waitlist,sequenceRef:t.sequenceRef}))}}transitionToRouting(){if(this.destroyed)return;const e=this.stateAtom.get();this.setSnapshot(N({base:this.baseFromSnapshot(e),journeyStage:"routing"}))}transitionToGated(e){if(this.destroyed)return;const t=this.stateAtom.get();this.setSnapshot(N({base:this.baseFromSnapshot(t),journeyStage:"gated",gates:e.gates,selected:e.selected}))}baseFromSnapshot(e,t={}){const i=Object.prototype.hasOwnProperty.call(t,"accessCode")?t.accessCode??void 0:e.accessCode,s=Object.prototype.hasOwnProperty.call(t,"degraded")?t.degraded||void 0:e.degraded,r=Object.prototype.hasOwnProperty.call(t,"lastSyncedAt")?t.lastSyncedAt:e.lastSyncedAt;return{revision:e.revision,updatedAt:e.updatedAt,experienceId:e.experienceId,accessCode:i,experience:t.experience??e.experience,events:t.events??e.events,lastSeenEventId:t.lastSeenEventId??e.lastSeenEventId,degraded:s,lastSyncedAt:r}}commit(e,t={}){if(this.destroyed)throw m.notInitialized("Journey has been destroyed");const i=this.stateAtom.get();if("routed"!==i.journeyStage)throw m.validationError(se);if(!function(e,t){if("distribution"in e&&e.distribution.sequenceId&&e.distribution.sequenceId!==t)return!1;return!0}(e,i.sequenceId))throw m.validationError(ie);const s=Object.prototype.hasOwnProperty.call(t,"waitlist")?t.waitlist??void 0:i.waitlist,r={};Object.prototype.hasOwnProperty.call(t,"lastSyncedAt")&&(r.lastSyncedAt=t.lastSyncedAt),Object.prototype.hasOwnProperty.call(t,"degraded")&&(r.degraded=t.degraded);const n=N({base:this.baseFromSnapshot(i,{...r,events:t.events??i.events}),journeyStage:"routed",sequenceId:i.sequenceId,offers:i.offers,sequence:e,waitlist:s,sequenceRef:i.sequenceRef});this.setSnapshot(n)}markDegraded(){if(this.destroyed)return;const e=this.stateAtom.get();e.degraded||this.setSnapshot(this.rebuildSnapshot(e,{degraded:!0}))}clearDegraded(){if(this.destroyed)return;const e=this.stateAtom.get();e.degraded&&this.setSnapshot(this.rebuildSnapshot(e,{degraded:!1}))}restoreQuietSnapshot(e){this.setSnapshot(this.rebuildSnapshot(e,{degraded:!0}))}isQuietableDegradationError(e){return g(e)&&(e.retryable||oe.has(e.code))}markErrorQuietable(e){return e&&"object"==typeof e&&(e.quietable=!0),e}rebuildSnapshot(e,t={}){const i=this.baseFromSnapshot(e,t);switch(e.journeyStage){case"ready":return N({base:i,journeyStage:"ready"});case"routing":return N({base:i,journeyStage:"routing"});case"gated":return N({base:i,journeyStage:"gated",gates:e.gates,selected:e.selected});case"routed":return N({base:i,journeyStage:"routed",sequenceId:e.sequenceId,offers:e.offers,sequence:e.sequence,waitlist:e.waitlist,sequenceRef:e.sequenceRef})}}emitEvent(e,t,i,s,r){const n=this.stateAtom.get(),o={id:b(),ts:Date.now(),kind:e,severity:t,audience:i,message:s,detail:r},a=[...n.events,o],c=a.length>this.EVENT_BUFFER_LIMIT?a.slice(a.length-this.EVENT_BUFFER_LIMIT):a;this.patchJourneyBase({events:c})}emitIfDistributionChanged(e,t){e?.id===t?.id&&e?.lifecycle===t?.lifecycle||this.emitEvent("distribution_change","info","user","Distribution context changed",{previous:e,next:t})}buildDistributionSummary(e,t,i){if(e.active){const s=this.sequenceDrivers[e.active.type],r=!0===s?.settlementCanStartWhileActive&&i?.settlingDistributionId===e.active.id?"settling":"open";return{type:e.active.type,id:e.active.id,sequenceId:t,lifecycle:r,details:e.active.details,opensAt:e.active.details.openAt,closesAt:e.active.details.closeAt,updatedAt:Date.now()}}if(e.upcoming)return{type:e.upcoming.type,id:e.upcoming.id,sequenceId:t,lifecycle:"scheduled",startsAt:e.upcoming.startsAt,opensAt:e.upcoming.startsAt,updatedAt:Date.now()};if(e.recentPast){const s=i?.settlingDistributionId===e.recentPast.id||te(i?.consumer,e.recentPast.type,e.recentPast.id)?"settling":"closed";return{type:e.recentPast.type,id:e.recentPast.id,sequenceId:t,lifecycle:s,result:e.recentPast.result,closesAt:e.recentPast.endedAt,updatedAt:Date.now()}}}buildWaitlistAttachmentFromContext(e,t){const i=e.waitlist?.id;if(i)return t?.waitlistId===i?t:{waitlistId:i,status:"not_waitlisted"}}buildWaitlistAttachmentFromMe(e,t){const i=e.waitlists?.find(e=>e.experienceId===this.experienceId&&e.sequenceId===t);if(i)return{waitlistId:i.waitlistId,status:"waitlisted"}}normalizeOffers(e){return Array.isArray(e)?e.filter(Boolean):[]}restoreFromStore(){const e=this.store.activeJourneys;if(!e||!e[this.experienceId])return null;const t=Be(e[this.experienceId]);return t?"routing"===t.journeyStage||"routed"===t.journeyStage&&$(t)?("routed"===t.journeyStage&&w(this.experienceId,t.sequenceId),this.restoredSnapshotNeedsPersist=!0,N({base:this.baseFromSnapshot(t),journeyStage:"ready"})):t:(this.store.removeJourney(this.experienceId),null)}persist(){this.store.setJourneyState(this.experienceId,this.stateAtom.get())}setSnapshot(e,t={}){if(this.destroyed)return;const i=this.stateAtom.get(),s=he(e);"auction"===s?.type&&"auction"!==this.displayAtom?.get().type&&(this.resetDisplayAtom("auction"),this.displayParticipationId=s.id),this.stateAtom.set(e),!1!==t.persist&&this.persist(),this.emitPhaseChanged(i,e)}emitPhaseChanged(e,t){const i=e.journeyStage,s="routed"===i?P(e):void 0,r=t.journeyStage,n="routed"===r?P(t):void 0;i===r&&s===n||E().emit("journey:phase-changed",{experienceId:this.experienceId,journeyStage:r,sequencePhase:n})}runSerializedOperation(e){const t=this.operationQueue.then(async()=>{if(this.destroyed)throw m.notInitialized("Journey has been destroyed");return e()});return this.operationQueue=t.then(()=>{},()=>{}),t}transitionToEnded(e,t={}){if(this.destroyed)return;const i=this.stateAtom.get(),s=z(i);if(!s)throw m.validationError(se);const r=L(i),n="checkout"in e?e.checkout:void 0,o="checkout"in e?{type:"completed"}:e,a=this.reinterpretLapsedGrantOutcome(i,o),c={...a,distributionType:a.distributionType??r?.type,distributionId:a.distributionId??r?.id,at:a.at??/* @__PURE__ */(new Date).toISOString()},d=this.withTerminalConsumer(U(i),c,{finalize:!0}),u=this.projectSequenceState({distribution:r,consumer:d,selectionMode:Ve(i),checkout:n,outcome:c});this.commit(u,t),this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearGrantHydration(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),this.emitEvent("sequence_change","expired"===c.type?"warning":"info","user","Sequence ended",{outcome:c}),E().emit("journey:ended",{experienceId:this.experienceId,sequenceId:s,outcome:c})}reinterpretLapsedGrantOutcome(e,t){if("granted"!==P(e))return t;return"closed"===t.type&&("not_queued"===t.reason||"not_entered"===t.reason)?{type:"expired",at:t.at,distributionType:t.distributionType,distributionId:t.distributionId}:t}applyMonitorUpdate(e){if(!this.destroyed){if("settling"===e.type){const t=this.stateAtom.get();if(!X(t)||"participating"!==t.sequence.phase)return;const i={...t.sequence.distribution,lifecycle:"settling",settlesAt:e.at},s=this.projectSequenceState({distribution:i,consumer:U(t),selectionMode:Ve(t)});if("settling"!==s.phase)return;return void this.commit(s,{lastSyncedAt:Date.now(),degraded:!1})}"granted"!==e.type?"resync"!==e.type?this.transitionToEnded(e.outcome,{lastSyncedAt:Date.now(),degraded:!1}):this.beginGrantHydration():this.beginGrantHydration(e.token,e.expiresAt)}}beginGrantHydration(e,t){const i=this.stateAtom.get();"routing"!==i.journeyStage?"routed"===i.journeyStage&&(le(i,i.sequenceId)||this.pendingGrantHydration?.sequenceId!==i.sequenceId&&(this.clearGrantHydration(),this.pendingGrantHydration={sequenceId:i.sequenceId,token:e,expiresAt:t,attempt:0},this.hydrateGrantFromMe(e,t))):this.pendingGrantObservation={token:e,expiresAt:t}}resumeDeferredGrantHydration(){const e=this.pendingGrantObservation;e&&(this.pendingGrantObservation=void 0,this.beginGrantHydration(e.token,e.expiresAt))}async hydrateGrantFromMe(e,t){if(this.destroyed)return;const i=this.pendingGrantHydration,s=this.stateAtom.get();if(i)if("routing"!==s.journeyStage)if(le(s,i.sequenceId))this.clearGrantHydration();else if(void 0!==t&&Date.now()>=t)this.transitionToEnded({type:"expired"},{lastSyncedAt:Date.now(),degraded:!1});else{try{const e=await this.sdk.experiences.getMe();if(this.destroyed)return;await this.resumeFromMe(e)}catch(r){this.emitEvent("error","warning","system","Could not resolve an observed grant from /me",{grant:e,error:r instanceof Error?r.message:String(r)})}this.scheduleGrantHydrationRetry()}else this.scheduleGrantHydrationRetry()}scheduleGrantHydrationRetry(){const e=this.pendingGrantHydration;if(!e||this.destroyed)return;if(le(this.stateAtom.get(),e.sequenceId))return void this.clearGrantHydration();const t=de[e.attempt]??1e4;e.attempt+=1,e.timer=setTimeout(()=>{this.pendingGrantHydration===e&&(e.timer=void 0,this.hydrateGrantFromMe(e.token,e.expiresAt))},t)}clearGrantHydration(){const e=this.pendingGrantHydration;e?.timer&&clearTimeout(e.timer),this.pendingGrantHydration=void 0,this.pendingGrantObservation=void 0}applyMonitorUpdateFromCallback(e){try{this.applyMonitorUpdate(e)}catch(t){if(this.dropStaleCallbackCommit(t,"monitor"))return;throw t}}startMonitorForParticipation(e){const t=this.ensureDisplayAtom(e),i=e=>this.applyMonitorUpdateFromCallback(e),s=e=>{e?this.markDegraded():this.clearDegraded()},r=this.sequenceDrivers[e.type];if(r?.startMonitoring)return r.startMonitoring({participation:e,displayAtom:t,onUpdate:i,onDegradedChange:s}),void(this.activeMonitor={type:e.type,id:e.id,stop:()=>r.stopMonitoring?.()});throw new Error(`Unknown distribution type: ${e.type}`)}stopRuntimeMonitoring(e=!1){this.activeMonitor&&(this.activeMonitor.stop(),this.activeMonitor=null),e&&this.clearRuntimeDisplayState()}clearGrantExpiryTimer(){this.grantExpiryTimer&&(clearTimeout(this.grantExpiryTimer),this.grantExpiryTimer=void 0)}clearCapabilityRefreshTimer(){this.capabilityRefreshTimer&&(clearTimeout(this.capabilityRefreshTimer),this.capabilityRefreshTimer=void 0)}clearDistributionSelfCheck(){this.selfCheckTimer&&(clearTimeout(this.selfCheckTimer),this.selfCheckTimer=void 0),this.selfCheckKey=void 0,this.selfCheckStartedAtMs=0,this.selfCheckAttempts=0}resetDistributionSelfCheck(){this.clearDistributionSelfCheck(),this.selfCheckTotalAttempts=0}evaluateDistributionSelfCheck(e){if(this.destroyed)return;const t=Date.now();if(!ue(e,t))return void this.clearDistributionSelfCheck();const i=`${e?.sequenceId??""}:${e?.id??""}:${e?.opensAt??""}`;if(this.selfCheckKey!==i&&(this.clearDistributionSelfCheck(),this.selfCheckKey=i,this.selfCheckStartedAtMs=t),this.selfCheckTimer)return;if(this.selfCheckAttempts>=ae.length)return;if(this.selfCheckTotalAttempts>=ce)return;const s=this.selfCheckStartedAtMs+ae[this.selfCheckAttempts];this.selfCheckAttempts+=1,this.selfCheckTotalAttempts+=1,this.selfCheckTimer=setTimeout(()=>{this.selfCheckFromTimer()},Math.max(0,s-t))}async selfCheckFromTimer(){if(this.selfCheckTimer=void 0,!this.destroyed)try{await this.refreshDistribution()}catch(e){if(this.destroyed||"routed"!==this.stateAtom.get().journeyStage)return;this.emitEvent("error","warning","system","Distribution self-check failed",{error:e instanceof Error?e.message:String(e)})}}armCapabilityRefreshTimer(){if(this.clearCapabilityRefreshTimer(),this.destroyed||this.checkoutStarted)return;const e=this.stateAtom.get();if("routed"!==e.journeyStage)return;const t=R(this.experienceId,e.sequenceId);if(void 0===t)return;const i=Math.max(t-Date.now()-6e4,5e3);this.scheduleCapabilityRefresh(i)}scheduleGatedCapabilityRefresh(){const e=this.stateAtom.get();if("routed"!==e.journeyStage)return;const t=Math.min(re*2**this.consecutiveGatedRestores,ne);this.consecutiveGatedRestores+=1;const i=R(this.experienceId,e.sequenceId),s=void 0===i?t:Math.max(i-Date.now()-6e4,t);this.scheduleCapabilityRefresh(s)}scheduleCapabilityRefresh(e){if(this.clearCapabilityRefreshTimer(),this.destroyed||this.checkoutStarted)return;"routed"===this.stateAtom.get().journeyStage&&(this.capabilityRefreshTimer=setTimeout(()=>this.refreshCapabilityFromTimer(),e))}rearmTimersIfNeeded(){if(this.destroyed||this.checkoutStarted)return;const e=this.stateAtom.get();"routed"===e.journeyStage&&this.armCapabilityRefreshTimer(),this.pendingGrantHydration&&le(e,this.pendingGrantHydration.sequenceId)&&this.scheduleGrantHydrationRetry(),"routed"===e.journeyStage&&"granted"===e.sequence.phase&&"awaiting_assignment"===e.sequence.selection.status&&this.pendingGrantHydration?.sequenceId!==e.sequenceId&&(this.clearGrantHydration(),this.pendingGrantHydration={sequenceId:e.sequenceId,token:e.sequence.grant.token,expiresAt:Y(e),attempt:0},this.scheduleGrantHydrationRetry());const t=Q(e);if("granted"===t?.phase&&(t.pendingAction||"internal"===t.settlement.processor&&"at_end"===t.settlement.mode&&"in_progress"===t.settlement.state))this.clearGrantExpiryTimer();else if("granted"===t?.phase&&!this.grantExpiryTimer){const t=Y(e);if(t){const e=t-Date.now();e<=0?this.transitionToEnded({type:"expired"}):this.grantExpiryTimer=setTimeout(()=>this.expireGrantFromTimer(),e)}}}async refreshCapabilityFromTimer(){this.capabilityRefreshTimer=void 0;try{if("routed"!==this.stateAtom.get().journeyStage)return void this.clearCapabilityRefreshTimer();if(this.checkoutStarted)return;const e=Date.now();if(void 0!==this.lastCapabilityRefreshAtMs&&e-this.lastCapabilityRefreshAtMs<re)return void this.scheduleCapabilityRefresh(re);this.lastCapabilityRefreshAtMs=e,await this.retry(),this.consecutiveRefreshFailures=0}catch(e){if(this.dropStaleCallbackCommit(e,"capability refresh timer"))return;const t=Math.min(re*2**this.consecutiveRefreshFailures,ne);this.consecutiveRefreshFailures+=1,this.emitEvent("error","warning","system","Capability grant refresh failed",{error:e instanceof Error?e.message:String(e),consecutiveFailures:this.consecutiveRefreshFailures}),this.scheduleCapabilityRefresh(t)}}expireGrantFromTimer(){this.grantExpiryTimer=void 0;try{this.transitionToEnded({type:"expired"})}catch(e){if(this.dropStaleCallbackCommit(e,"grant-expiry timer"))return;throw e}}dropStaleCallbackCommit(e,t){return!(!g(e)||e.code!==y.VALIDATION_ERROR||e.message!==ie&&e.message!==se)&&(this.logger.debug("Dropped stale journey callback",{experienceId:this.experienceId,source:t,message:e.message}),!0)}getRuntimeBinding(){const e=this.stateAtom.get(),t=he(e),i=z(e);return t&&i?{experienceId:this.experienceId,sequenceId:i,participationId:t.id,participationType:t.type}:null}startRuntimeMonitoring(){const e=this.getRuntimeBinding();if(!e)return;const t=this.activeMonitor;t&&t.id===e.participationId&&t.type===e.participationType&&this.displayAtom||(this.stopRuntimeMonitoring(!1),this.startMonitorForParticipation({id:e.participationId,type:e.participationType}))}getRuntimeDisplayAtom(){return this.displayAtom}applyRuntimeState(e){if(!e)return void this.clearRuntimeDisplayState();const t=this.getRuntimeBinding();if(!t)return;this.ensureDisplayAtom({id:t.participationId,type:t.participationType}).set(e)}reconcileSyncedSnapshot(e){if(this.destroyed)return;if(!e)return this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearGrantHydration(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),void this.setSnapshot(_(this.experienceId),{persist:!1});const t=Be(e);if(!t)return;const i="routing"===t.journeyStage?N({base:this.baseFromSnapshot(t),journeyStage:"ready"}):t,s=this.stateAtom.get();if(s.revision===i.revision&&s.updatedAt===i.updatedAt)return;const r=he(i);r||(this.displayAtom=null,this.displayParticipationId=void 0),this.setSnapshot(i,{persist:!1}),r?this.ensureDisplayAtom(r):this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),this.rearmTimersIfNeeded()}ensureDisplayAtom(e){const t=this.displayAtom;if(t?.get().type===e.type&&this.displayParticipationId===e.id)return t;const i=this.resetDisplayAtom(e.type);return this.displayParticipationId=e.id,i}resetDisplayAtom(e){const t=this.displayAtom;if(!t||t.get().type!==e){const t=o({type:e});return this.displayAtom=t,t}return t.set({type:e}),t}clearRuntimeDisplayState(){const e=this.getRuntimeBinding();if(!e)return this.displayAtom=null,void(this.displayParticipationId=void 0);this.displayParticipationId=void 0,this.resetDisplayAtom(e.participationType)}clearRoutedRuntimeState(){this.stopRuntimeMonitoring(!0),this.clearGrantExpiryTimer(),this.clearCapabilityRefreshTimer(),this.resetDistributionSelfCheck(),this.checkoutStarted=!1}deriveTerminalOutcomeForClosedDistribution(e,t,i){if(i&&!l(i))return i;if(!t||"closed"!==t.lifecycle||!e)return i;const s=this.projectSequenceState({distribution:t,consumer:e});return"ended"===s.phase&&"lost"===s.outcome.type?s.outcome:i??{type:"closed",distributionType:t.type,distributionId:t.id}}withTerminalConsumer(e,t,i){switch(e?.mechanism){case"appointment":return u(e,t);case"auction":return p(e,t,i);case"draw":return I(e,t);case"queue":return q(e,t);case"timed_release":return O(e,t);default:return e}}stopPolling(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0)}}const me=c.picklist(["queue","draw","auction","timed_release","appointment"]),ge=me,ye=c.picklist(["queue","draw","auction","timed_release"]),fe=c.picklist(["draw","auction"]),be=c.strictObject({id:c.string(),ts:c.number(),kind:c.picklist(["reroute","sequence_change","distribution_change","requirement","error","info"]),severity:c.picklist(["info","success","warning","error"]),audience:c.picklist(["user","system","analytics"]),message:c.string(),detail:c.optional(c.record(c.string(),c.unknown()))}),Se=c.strictObject({id:c.string(),name:c.string(),experienceId:c.string(),priority:c.number(),color:c.string()}),Ie=c.strictObject({type:me,id:c.string(),sequenceId:c.optional(c.string()),lifecycle:c.string(),startsAt:c.optional(c.string()),opensAt:c.optional(c.string()),closesAt:c.optional(c.string()),settlesAt:c.optional(c.string()),result:c.optional(c.string()),details:c.optional(c.unknown()),updatedAt:c.optional(c.number())}),ve=c.strictObject({status:c.string(),selection:c.optional(n),id:c.optional(c.string()),distributionId:c.optional(c.string()),waitlistId:c.optional(c.string()),enteredAt:c.optional(c.string()),admissionGrant:c.optional(c.string()),grantedAt:c.optional(c.string()),deniedReason:c.optional(c.string()),position:c.optional(c.number()),highestBid:c.optional(c.string()),currentBid:c.optional(c.string()),slotId:c.optional(c.string()),locationId:c.optional(c.string()),bookedAt:c.optional(c.string()),checkedInAt:c.optional(c.string()),completedAt:c.optional(c.string()),cancelledAt:c.optional(c.string()),noShowAt:c.optional(c.string())}),qe=c.strictObject({token:c.string(),distributionType:ye,distributionId:c.string(),sequenceId:c.string(),experienceId:c.string(),issuedAt:c.optional(c.string()),expiresAt:c.optional(c.string())}),Ae=c.strictObject({orderId:c.string(),amount:c.string(),currencyCode:c.string(),paymentMethodLast4:c.optional(c.string()),paymentMethodBrand:c.optional(c.string())}),we=c.strictObject({publishableKey:c.string(),stripeAccount:c.optional(c.string())}),ke=c.strictObject({type:c.string(),reason:c.optional(c.string()),at:c.optional(c.string()),distributionType:c.optional(me),distributionId:c.optional(c.string())}),Ce=c.strictObject({phase:c.literal("unavailable"),reason:c.optional(c.string())}),je=c.strictObject({waitlistId:c.string(),status:c.picklist(["not_waitlisted","waitlisted"]),entryId:c.optional(c.string())}),xe=c.strictObject({phase:c.literal("scheduled"),selectionMode:c.optional(c.picklist(s)),mechanism:ge,distribution:Ie}),Te=c.strictObject({phase:c.literal("enterable"),selectionMode:c.optional(c.picklist(s)),mechanism:ge,distribution:Ie,consumer:ve,paymentProvider:c.optional(we)}),Re=c.strictObject({phase:c.literal("participating"),selectionMode:c.optional(c.picklist(s)),mechanism:ge,distribution:Ie,consumer:ve}),Ee=c.strictObject({phase:c.literal("settling"),selectionMode:c.optional(c.picklist(s)),mechanism:fe,distribution:Ie,consumer:ve}),De=c.variant("processor",[c.strictObject({processor:c.literal("external")}),c.strictObject({processor:c.literal("internal"),mode:c.literal("at_end"),state:c.picklist(["awaiting","in_progress"]),paymentProvider:c.optional(we)}),c.strictObject({processor:c.literal("internal"),mode:c.literal("pre_auth")})]),Me=c.strictObject({phase:c.literal("granted"),selectionMode:c.optional(c.picklist(s)),mechanism:ye,distribution:Ie,consumer:ve,grant:qe,settlement:De,selection:r}),Oe=c.strictObject({phase:c.literal("ended"),selectionMode:c.optional(c.picklist(s)),mechanism:ge,distribution:Ie,consumer:ve,outcome:ke,checkout:c.optional(Ae)}),Ge=c.union([Ce,xe,Te,Re,Ee,Me,Oe]),Fe={schemaVersion:c.literal(5),revision:c.number(),updatedAt:c.number(),experienceId:c.string(),accessCode:c.optional(c.string()),experience:c.optional(c.unknown()),events:c.array(be),lastSeenEventId:c.optional(c.string()),lastSyncedAt:c.optional(c.number())},_e=c.strictObject({...Fe,journeyStage:c.literal("ready")}),Pe=c.strictObject({...Fe,journeyStage:c.literal("routing")}),He=c.variant("type",[c.object({...c.omit(e,["reason"]).entries,requirement:c.optional(c.picklist(["session","authenticated"]),"authenticated")}),c.omit(t,["reason"]),c.omit(i,["reason"])]),Ne=c.strictObject({...Fe,journeyStage:c.literal("gated"),gates:c.array(He),selected:c.optional(c.strictObject({sequence:c.unknown(),status:c.literal("gated")}))}),ze=c.strictObject({...Fe,journeyStage:c.literal("routed"),sequenceId:c.string(),offers:c.array(c.object({sequence:c.unknown(),status:c.literal("gated"),gates:c.array(He)})),sequence:Ge,waitlist:c.optional(je),sequenceRef:c.optional(Se)}),Ue=c.union([_e,Pe,Ne,ze]);function Be(e){const t=c.safeParse(Ue,e);if(!t.success)return null;const{schemaVersion:i,...s}=t.output;if("routed"===s.journeyStage)try{ee(s.sequence)}catch{return null}return s}function Le(e){if("participating"!==e.phase&&"settling"!==e.phase)return e;if(!("selection"in e))return e;const{selection:t,...i}=e;return void 0===t?i:{...i,consumer:{...i.consumer,selection:t}}}function Je(e){return"routed"!==e.journeyStage||"granted"!==e.sequence.phase&&"ended"!==e.sequence.phase||!("checkout"in e.sequence)?V(e):e.sequence.checkout}function We(e){if("routed"===e.journeyStage&&"granted"===e.sequence.phase)return e.sequence.settlement}function Qe(e){if("routed"===e.journeyStage&&"granted"===e.sequence.phase)return e.sequence.selection}function Ve(e){if("routed"===e.journeyStage)return"selectionMode"in e.sequence?e.sequence.selectionMode:void 0}export{pe as ExperienceJourney,ue as isSelfContradictingDistribution};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e,o,
|
|
1
|
+
function e(e){return e.selectionMode?{selectionMode:e.selectionMode}:{}}function o(e,o,n){const r=n.confirmCheckout,t=n.resumeCheckout;if(n.canConfirmCheckout&&r&&t)return{processor:"internal",confirmCheckout:e=>r(e),resumeCheckout:()=>t(),...o?{pendingAction:o}:{},...e.paymentProvider?{paymentProvider:e.paymentProvider}:{}}}export{o as buildGrantPaymentAffordance,e as selectionModeFields};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createError as e}from"../core/errors.js";import{buildGrantPaymentAffordance as
|
|
1
|
+
import{createError as e}from"../core/errors.js";import{selectionModeFields as t,buildGrantPaymentAffordance as i}from"../experiences/sequence-driver.js";import{resolveCheckoutContract as n,checkoutViewFields as s,isEntryActionRequired as r,canReenter as o,isPreAuthMisconfigured as u}from"../payment/checkout-contract.js";import{isClaimableSettlement as a}from"../payment/settlement.js";function c(e){return u(n(e.details))}function d(e){return o(e.distribution.lifecycle,n(e.distribution.details))}function p(e){return new h(e)}function l(i){const n=function(t){const{distribution:i,consumer:n,grant:s,checkout:r,settlement:o,selection:u,outcome:a}=t;if(!i)return{phase:"unavailable"};const d=function(t){if("queue"!==t.type)throw e.validationError("Queue driver received a non-queue distribution");return t}(i),p=n&&"queue"===n.mechanism?function(e){const{mechanism:t,...i}=e;return i}(n):b(i);if(s)return"completed"===a?.type?f(d,p,a,r):s.expiresAt&&Date.now()>new Date(s.expiresAt).getTime()?"open"===d.lifecycle?c(d)?{phase:"unavailable",reason:"checkout_misconfigured"}:{phase:"enterable",mechanism:"queue",distribution:d,consumer:b(d)}:f(d,p,{type:"expired"}):o&&u?{phase:"granted",mechanism:"queue",distribution:d,consumer:p,grant:s,settlement:o,selection:u}:{phase:"unavailable"};const l=a??function(e){return"completed"===e.status?{type:"completed"}:"denied"===e.status?{type:"denied",reason:e.deniedReason}:"left"===e.status?{type:"left"}:void 0}(p);if(l)return f(d,p,l,r);if(function(e){return"queued"===e.status}(p))return{phase:"participating",mechanism:"queue",distribution:d,consumer:p};if("scheduled"===d.lifecycle)return{phase:"scheduled",mechanism:"queue",distribution:d};if("open"===d.lifecycle)return c(d)?{phase:"unavailable",reason:"checkout_misconfigured"}:{phase:"enterable",mechanism:"queue",distribution:d,consumer:p};return f(d,p,{type:"closed"})}(i);return"unavailable"===n.phase?n:{...n,...t(i)}}function m(e,t){return e&&"queue"===e.mechanism&&t?"left"===t.type?{...e,status:"left"}:"denied"===t.type?{...e,status:"denied",deniedReason:t.reason}:"completed"===t.type?{...e,status:"completed"}:{...e,status:"not_queued"}:e}class h{constructor(e){this.deps=e,this.mechanism="queue"}project(e){return l(e)}buildView(n,s){if("unavailable"===n.phase)return{phase:"unavailable",reason:n.reason};const r=function(t){if(!("mechanism"in t)||"queue"!==t.mechanism)throw e.validationError("Queue driver received a non-queue sequence");return t}(n);switch(r.phase){case"scheduled":return{phase:"scheduled",mechanism:"queue",...t(r),distribution:r.distribution,startsAt:r.distribution.startsAt??r.distribution.opensAt};case"enterable":return this.buildEnterableView(r);case"participating":return{phase:"participating",mechanism:"queue",...t(r),consumer:r.consumer,display$:s.displayAtom,leave:()=>this.leave()};case"granted":{const e={phase:"granted",mechanism:"queue",...t(r),distribution:r.distribution,consumer:r.consumer,grant:r.grant},{settlement:n}=r,o=r.selection;if("awaiting_assignment"===o.status)return{...e,settlement:n,selection:o};if("required"===o.status)return{...e,settlement:n,selection:o,select:s.select,loadSelectionOptions:s.loadSelectionOptions};if("internal"===n.processor&&"at_end"===n.mode){const t=i(n,r.pendingAction,s);return t?{...e,settlement:n,selection:o,loadSelectionOptions:s.loadSelectionOptions,select:s.select,claim:()=>s.claim(),payment:t}:{...e,settlement:n,selection:o,loadSelectionOptions:s.loadSelectionOptions,select:s.select,claim:()=>s.claim()}}return a(n)?{...e,settlement:n,selection:o,loadSelectionOptions:s.loadSelectionOptions,select:s.select,claim:()=>s.claim()}:{...e,settlement:n,selection:o}}case"ended":return this.buildEndedView(r)}}buildEnterableView(e){const i=n(e.distribution.details),r=s(i);return"pre_auth"===r.checkoutMode?{phase:"enterable",mechanism:"queue",...t(e),...r,distribution:e.distribution,consumer:e.consumer,...e.pendingAction?{pendingAction:e.pendingAction}:{},...e.paymentProvider?{paymentProvider:e.paymentProvider}:{},enter:e=>this.enter({paymentInput:e})}:{phase:"enterable",mechanism:"queue",...t(e),...r,distribution:e.distribution,consumer:e.consumer,enter:()=>this.enter()}}buildEndedView(e){const i={phase:"ended",mechanism:"queue",...t(e),consumer:e.consumer,outcome:e.outcome,...e.checkout?{checkout:e.checkout}:{}};if(!d(e))return i;const r=n(e.distribution.details),o=s(r);return"pre_auth"===o.checkoutMode?{...i,...o,reenter:e=>this.enter({paymentInput:e})}:{...i,...o,reenter:()=>this.enter()}}startMonitoring(e){this.activeMonitorId=e.participation.id,this.deps.queues.startMonitoring(e.participation.id,{displayAtom:e.displayAtom},e.onUpdate,e.onDegradedChange)}stopMonitoring(){this.activeMonitorId&&(this.deps.queues.stopMonitoring(this.activeMonitorId),this.activeMonitorId=void 0)}async enter(e){await this.deps.runSerializedOperation(async()=>{await this.enterWithinOperation(e)})}async enterWithinOperation(t){const i=this.currentQueueSequence("enterable","No open queue to enter"),s=i.distribution,o=n(s.details),u=t?.paymentInput;if("pre_auth"===o.mode&&!u)throw e.validationError("Payment input is required for pre-auth distributions");const a=u?await this.deps.queues.enter(s.id,void 0,void 0,u):await this.deps.queues.enter(s.id,void 0);if(r(a))return this.deps.commit({...i,pendingAction:a.nextAction}),void this.deps.emitEvent("sequence_change","info","user","Entry awaiting verification",{distributionId:s.id,processor:a.nextAction.processor});const c=function(e){if("QUEUED"===e.status)return null;if("COMPLETED"===e.status)return{type:"ended",outcome:{type:"completed"}};if("GRANTED"===e.status)return"admissionGrant"in e?{type:"granted",token:e.admissionGrant,expiresAt:"expiresAt"in e&&e.expiresAt?new Date(e.expiresAt).getTime():void 0}:null;return{type:"ended",outcome:{type:y(e),reason:"reason"in e?e.reason:void 0}}}(a);if(c)return void this.deps.applyMonitorUpdate(c);const d={mechanism:"queue",status:"queued",id:p=s.id,distributionId:p};var p;this.deps.ensureDisplayAtom({id:s.id,type:"queue"}),this.deps.commit(l({distribution:s,consumer:d})),this.deps.emitEvent("sequence_change","success","user","Entered queue",{distributionId:s.id})}async leave(){await this.deps.runSerializedOperation(async()=>{await this.leaveWithinOperation()})}async leaveWithinOperation(){const e=this.currentQueueSequence("participating"),t=e.consumer.distributionId??e.consumer.id??e.distribution.id;this.deps.stopRuntimeMonitoring(!0),await this.deps.queues.leave(t),this.deps.applyMonitorUpdate({type:"ended",outcome:{type:"left"}}),this.deps.emitEvent("sequence_change","info","user","Left participation",{type:"queue"})}currentQueueSequence(t,i="Not participating in a queue"){const n=this.deps.getCurrentSequence();if(!n||!("mechanism"in n)||"queue"!==n.mechanism)throw e.validationError(i);if("enterable"===t&&"ended"===n.phase&&d(n))return{phase:"enterable",mechanism:"queue",distribution:n.distribution,consumer:b(n.distribution)};if(n.phase!==t)throw e.validationError(i);return n}}function b(e){return{status:"not_queued",distributionId:e.id}}function f(e,t,i,n){return{phase:"ended",mechanism:"queue",distribution:e,consumer:t,outcome:{...i,distributionType:i.distributionType??e.type,distributionId:i.distributionId??e.id,at:i.at??/* @__PURE__ */(new Date).toISOString()},...n?{checkout:n}:{}}}function y(e){return"LEFT"===e.status?"left":"EXPIRED"===e.status?"expired":"COMPLETED"===e.status?"completed":"DENIED"===e.status?"denied":"closed"}export{p as createQueueDriver,l as projectQueueSequence,m as withQueueTerminalConsumer};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AdmissionGrant, GrantedSettlement, QueueConsumerStatus, SequenceOutcome } from '@fanfare-io/fanfare-sdk-contracts/consumer-me';
|
|
2
|
-
import { GrantedSelection } from '@fanfare-io/fanfare-sdk-contracts/selection';
|
|
2
|
+
import { GrantedSelection, SelectionMode } from '@fanfare-io/fanfare-sdk-contracts/selection';
|
|
3
3
|
import { ReadableAtom } from 'nanostores';
|
|
4
4
|
import { QueueDisplayState } from '../experiences/distribution-monitor.types';
|
|
5
5
|
import { DistributionSummary } from '../experiences/journey.types';
|
|
@@ -46,6 +46,7 @@ export type QueueSequence = QueueScheduled | QueueEnterable | QueueParticipating
|
|
|
46
46
|
export interface QueueScheduled {
|
|
47
47
|
/** Mechanism discriminator for queue narrowing. */
|
|
48
48
|
mechanism: "queue";
|
|
49
|
+
selectionMode?: SelectionMode;
|
|
49
50
|
/** Phase discriminator; scheduled queues cannot be entered yet. */
|
|
50
51
|
phase: "scheduled";
|
|
51
52
|
/** Queue distribution facts from the journey projector. */
|
|
@@ -59,6 +60,7 @@ export interface QueueScheduled {
|
|
|
59
60
|
export interface QueueEnterable {
|
|
60
61
|
/** Mechanism discriminator for queue narrowing. */
|
|
61
62
|
mechanism: "queue";
|
|
63
|
+
selectionMode?: SelectionMode;
|
|
62
64
|
/** Phase discriminator; `enter()` is legal on the matching view. */
|
|
63
65
|
phase: "enterable";
|
|
64
66
|
/** Open queue distribution facts from the journey projector. */
|
|
@@ -85,6 +87,7 @@ export interface QueueEnterable {
|
|
|
85
87
|
export interface QueueParticipating {
|
|
86
88
|
/** Mechanism discriminator for queue narrowing. */
|
|
87
89
|
mechanism: "queue";
|
|
90
|
+
selectionMode?: SelectionMode;
|
|
88
91
|
/** Phase discriminator; the queue display is live while participating. */
|
|
89
92
|
phase: "participating";
|
|
90
93
|
/** Queue distribution facts from the journey projector. */
|
|
@@ -100,6 +103,7 @@ export interface QueueParticipating {
|
|
|
100
103
|
export interface QueueGranted {
|
|
101
104
|
/** Mechanism discriminator for queue narrowing. */
|
|
102
105
|
mechanism: "queue";
|
|
106
|
+
selectionMode?: SelectionMode;
|
|
103
107
|
/** Phase discriminator; `claim()` is legal on the matching view. */
|
|
104
108
|
phase: "granted";
|
|
105
109
|
/** Queue distribution facts from the journey projector. */
|
|
@@ -126,6 +130,7 @@ export interface QueueGranted {
|
|
|
126
130
|
export interface QueueEnded {
|
|
127
131
|
/** Mechanism discriminator for queue narrowing. */
|
|
128
132
|
mechanism: "queue";
|
|
133
|
+
selectionMode?: SelectionMode;
|
|
129
134
|
/** Phase discriminator; no queue actions are legal after this phase. */
|
|
130
135
|
phase: "ended";
|
|
131
136
|
/** Queue distribution facts from the journey projector. */
|
|
@@ -155,6 +160,7 @@ export interface QueueScheduledView {
|
|
|
155
160
|
phase: "scheduled";
|
|
156
161
|
/** Mechanism discriminator for queue rendering. */
|
|
157
162
|
mechanism: "queue";
|
|
163
|
+
selectionMode?: SelectionMode;
|
|
158
164
|
/** Queue distribution facts from the journey projector. */
|
|
159
165
|
distribution: DistributionSummary & {
|
|
160
166
|
type: "queue";
|
|
@@ -177,6 +183,7 @@ export type QueueEnterableView = {
|
|
|
177
183
|
phase: "enterable";
|
|
178
184
|
/** Mechanism discriminator for queue rendering. */
|
|
179
185
|
mechanism: "queue";
|
|
186
|
+
selectionMode?: SelectionMode;
|
|
180
187
|
/** Money moves after the win; entry places no hold. */
|
|
181
188
|
checkoutMode: "at_end";
|
|
182
189
|
/** Open queue distribution facts from the journey projector. */
|
|
@@ -197,6 +204,7 @@ export type QueueEnterableView = {
|
|
|
197
204
|
phase: "enterable";
|
|
198
205
|
/** Mechanism discriminator for queue rendering. */
|
|
199
206
|
mechanism: "queue";
|
|
207
|
+
selectionMode?: SelectionMode;
|
|
200
208
|
/** Fanfare places a payment authorization hold at entry and captures it on win. */
|
|
201
209
|
checkoutMode: "pre_auth";
|
|
202
210
|
/** Open queue distribution facts from the journey projector. */
|
|
@@ -236,6 +244,7 @@ export interface QueueParticipatingView {
|
|
|
236
244
|
phase: "participating";
|
|
237
245
|
/** Mechanism discriminator for queue rendering. */
|
|
238
246
|
mechanism: "queue";
|
|
247
|
+
selectionMode?: SelectionMode;
|
|
239
248
|
/** Consumer queue participation facts. */
|
|
240
249
|
consumer: QueueSequenceConsumerState;
|
|
241
250
|
/** Live queue display facts, such as position and estimated wait time. */
|
|
@@ -254,6 +263,7 @@ interface QueueGrantedViewBase {
|
|
|
254
263
|
phase: "granted";
|
|
255
264
|
/** Mechanism discriminator for queue rendering. */
|
|
256
265
|
mechanism: "queue";
|
|
266
|
+
selectionMode?: SelectionMode;
|
|
257
267
|
/** Queue distribution facts from the journey projector. */
|
|
258
268
|
distribution: DistributionSummary & {
|
|
259
269
|
type: "queue";
|
|
@@ -334,6 +344,7 @@ export type QueueEndedView = {
|
|
|
334
344
|
phase: "ended";
|
|
335
345
|
/** Mechanism discriminator for queue rendering. */
|
|
336
346
|
mechanism: "queue";
|
|
347
|
+
selectionMode?: SelectionMode;
|
|
337
348
|
/** Consumer queue facts at the terminal outcome. */
|
|
338
349
|
consumer: QueueSequenceConsumerState;
|
|
339
350
|
/** Server-derived terminal outcome for the queue participation. */
|
|
@@ -349,6 +360,7 @@ export type QueueEndedView = {
|
|
|
349
360
|
phase: "ended";
|
|
350
361
|
/** Mechanism discriminator for queue rendering. */
|
|
351
362
|
mechanism: "queue";
|
|
363
|
+
selectionMode?: SelectionMode;
|
|
352
364
|
/** Consumer queue facts at the terminal outcome. */
|
|
353
365
|
consumer: QueueSequenceConsumerState;
|
|
354
366
|
/** Server-derived terminal outcome for the queue participation. */
|
|
@@ -369,6 +381,7 @@ export type QueueEndedView = {
|
|
|
369
381
|
phase: "ended";
|
|
370
382
|
/** Mechanism discriminator for queue rendering. */
|
|
371
383
|
mechanism: "queue";
|
|
384
|
+
selectionMode?: SelectionMode;
|
|
372
385
|
/** Consumer queue facts at the terminal outcome. */
|
|
373
386
|
consumer: QueueSequenceConsumerState;
|
|
374
387
|
/** Server-derived terminal outcome for the queue participation. */
|
|
@@ -402,6 +415,7 @@ export interface QueueGrantedAwaitingAssignmentView {
|
|
|
402
415
|
phase: "granted";
|
|
403
416
|
/** Mechanism discriminator. */
|
|
404
417
|
mechanism: "queue";
|
|
418
|
+
selectionMode?: SelectionMode;
|
|
405
419
|
/** Distribution associated with this grant. */
|
|
406
420
|
distribution: DistributionSummary & {
|
|
407
421
|
type: "queue";
|
|
@@ -423,6 +437,7 @@ export interface QueueGrantedSelectionRequiredView {
|
|
|
423
437
|
phase: "granted";
|
|
424
438
|
/** Mechanism discriminator. */
|
|
425
439
|
mechanism: "queue";
|
|
440
|
+
selectionMode?: SelectionMode;
|
|
426
441
|
/** Distribution associated with this grant. */
|
|
427
442
|
distribution: DistributionSummary & {
|
|
428
443
|
type: "queue";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createError as e}from"../core/errors.js";import{buildGrantPaymentAffordance as
|
|
1
|
+
import{createError as e}from"../core/errors.js";import{selectionModeFields as t,buildGrantPaymentAffordance as i}from"../experiences/sequence-driver.js";function n(e){return new a(e)}function s(i){const n=function(t){const{distribution:i,consumer:n,grant:s,settlement:r,selection:a,outcome:c}=t;if(!i)return{phase:"unavailable"};const l=function(t){if("timed_release"!==t.type)throw e.validationError("Timed-release driver received a non-timed-release distribution");return t}(i),m=n&&"timed_release"===n.mechanism?function(e){const{mechanism:t,...i}=e;return i}(n):o(i);if(s)return"completed"===c?.type?d(l,m,c):s.expiresAt&&Date.now()>new Date(s.expiresAt).getTime()?"open"===l.lifecycle?{phase:"enterable",mechanism:"timed_release",distribution:l,consumer:o(l)}:d(l,m,{type:"expired"}):r&&a&&"required"!==a.status?{phase:"granted",mechanism:"timed_release",distribution:l,consumer:m,grant:s,settlement:r,selection:a}:{phase:"unavailable"};const u=c??function(e){return"completed"===e.status?{type:"completed"}:"denied"===e.status?{type:"denied",reason:e.deniedReason}:"left"===e.status?{type:"left"}:void 0}(m);if(u)return d(l,m,u);if(function(e){return"entered"===e.status}(m))return{phase:"participating",mechanism:"timed_release",distribution:l,consumer:m};if("scheduled"===l.lifecycle)return{phase:"scheduled",mechanism:"timed_release",distribution:l};if("open"===l.lifecycle)return{phase:"enterable",mechanism:"timed_release",distribution:l,consumer:m};return d(l,m,{type:"closed"})}(i);return"unavailable"===n.phase?n:{...n,...t(i)}}function r(e,t){return e&&"timed_release"===e.mechanism&&t?"left"===t.type?{...e,status:"left"}:"denied"===t.type?{...e,status:"denied",deniedReason:t.reason}:"completed"===t.type?{...e,status:"completed"}:{...e,status:"not_entered"}:e}class a{constructor(e){this.deps=e,this.mechanism="timed_release"}project(e){return s(e)}buildView(n,s){if("unavailable"===n.phase)return{phase:"unavailable",reason:n.reason};const r=function(t){if(!("mechanism"in t)||"timed_release"!==t.mechanism)throw e.validationError("Timed-release driver received a non-timed-release sequence");return t}(n);switch(r.phase){case"scheduled":return{phase:"scheduled",mechanism:"timed_release",...t(r),distribution:r.distribution,startsAt:r.distribution.startsAt??r.distribution.opensAt};case"enterable":return{phase:"enterable",mechanism:"timed_release",...t(r),distribution:r.distribution,consumer:r.consumer,loadSelectionOptions:s.loadSelectionOptions,enter:e=>this.enter({selection:e})};case"participating":return{phase:"participating",mechanism:"timed_release",...t(r),consumer:r.consumer,display$:s.displayAtom,leave:()=>this.leave(),complete:()=>this.complete()};case"granted":{const e={phase:"granted",mechanism:"timed_release",...t(r),distribution:r.distribution,consumer:r.consumer,grant:r.grant},{settlement:n}=r,a=r.selection;if("awaiting_assignment"===a.status)return{...e,settlement:n,selection:a};if("internal"===n.processor&&"at_end"===n.mode){const t=i(n,r.pendingAction,s);return t?{...e,settlement:n,selection:a,loadSelectionOptions:s.loadSelectionOptions,claim:()=>s.claim(),payment:t}:{...e,settlement:n,selection:a,loadSelectionOptions:s.loadSelectionOptions,claim:()=>s.claim()}}return"external"===n.processor?{...e,settlement:n,selection:a,loadSelectionOptions:s.loadSelectionOptions,claim:()=>s.claim()}:{...e,settlement:n,selection:a}}case"ended":return{phase:"ended",mechanism:"timed_release",...t(r),consumer:r.consumer,outcome:r.outcome}}}startMonitoring(e){this.activeMonitorId=e.participation.id,this.deps.timedReleases.startMonitoring(e.participation.id,{displayAtom:e.displayAtom},e.onUpdate)}stopMonitoring(){this.activeMonitorId&&(this.deps.timedReleases.stopMonitoring(this.activeMonitorId),this.activeMonitorId=void 0)}async enter(e){await this.deps.runSerializedOperation(async()=>{await this.enterWithinOperation(e)})}async enterWithinOperation(e){const t=this.currentTimedReleaseSequence("enterable","No open timed release to enter").distribution,i=e?.selection?await this.deps.timedReleases.enter(t.id,void 0,e.selection):await this.deps.timedReleases.enter(t.id,void 0),n=function(e){if("ENTERED"===e.status)return e.admissionGrant?{type:"granted",token:e.admissionGrant,expiresAt:e.expiresAt?new Date(e.expiresAt).getTime():void 0}:null;if("COMPLETED"===e.status)return{type:"ended",outcome:{type:"completed"}};return{type:"ended",outcome:{type:"LEFT"===e.status?"left":"denied",reason:"reason"in e?e.reason:void 0}}}(i);if(n)return void this.deps.applyMonitorUpdate(n);const r="ENTERED"===i.status?i.selection:void 0,a={...(o=t.id,{mechanism:"timed_release",status:"entered",id:o,distributionId:o}),...r?{selection:r}:{}};var o;this.deps.ensureDisplayAtom({id:t.id,type:"timed_release"}),this.deps.commit(s({distribution:t,consumer:a})),this.deps.emitEvent("sequence_change","success","user","Entered timed release",{distributionId:t.id})}async leave(){await this.deps.runSerializedOperation(async()=>{await this.leaveWithinOperation()})}async leaveWithinOperation(){const e=this.currentTimedReleaseSequence("participating"),t=e.consumer.distributionId??e.consumer.id??e.distribution.id;this.deps.stopRuntimeMonitoring(!0),await this.deps.timedReleases.leave(t),this.deps.applyMonitorUpdate({type:"ended",outcome:{type:"left"}}),this.deps.emitEvent("sequence_change","info","user","Left participation",{type:"timed_release"})}async complete(){await this.deps.runSerializedOperation(async()=>{const e=this.currentTimedReleaseSequence("participating"),t=e.consumer.distributionId??e.consumer.id??e.distribution.id,i=this.deps.timedReleases.complete(t);i?this.deps.applyMonitorUpdate({type:"granted",token:i}):this.deps.applyMonitorUpdate({type:"ended",outcome:{type:"completed"}}),this.deps.emitEvent("sequence_change","success","user","Completed timed release",{timedReleaseId:t})})}currentTimedReleaseSequence(t,i="Not participating in a timed release"){const n=this.deps.getCurrentSequence();if(!n||n.phase!==t||!("mechanism"in n)||"timed_release"!==n.mechanism)throw e.validationError(i);return n}}function o(e){return{status:"not_entered",distributionId:e.id}}function d(e,t,i){return{phase:"ended",mechanism:"timed_release",distribution:e,consumer:t,outcome:{...i,distributionType:i.distributionType??e.type,distributionId:i.distributionId??e.id,at:i.at??/* @__PURE__ */(new Date).toISOString()}}}export{n as createTimedReleaseDriver,s as projectTimedReleaseSequence,r as withTimedReleaseTerminalConsumer};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AdmissionGrant, GrantedSettlement, SequenceOutcome, TimedReleaseConsumerStatus } from '@fanfare-io/fanfare-sdk-contracts/consumer-me';
|
|
2
|
-
import { GrantedSelection } from '@fanfare-io/fanfare-sdk-contracts/selection';
|
|
2
|
+
import { GrantedSelection, SelectionMode } from '@fanfare-io/fanfare-sdk-contracts/selection';
|
|
3
3
|
import { ReadableAtom } from 'nanostores';
|
|
4
4
|
import { TimedReleaseDisplayState } from '../experiences/distribution-monitor.types';
|
|
5
5
|
import { DistributionSummary } from '../experiences/journey.types';
|
|
@@ -44,6 +44,7 @@ export type TimedReleaseSequence = TimedReleaseScheduled | TimedReleaseEnterable
|
|
|
44
44
|
export interface TimedReleaseScheduled {
|
|
45
45
|
/** Mechanism discriminator for timed release narrowing. */
|
|
46
46
|
mechanism: "timed_release";
|
|
47
|
+
selectionMode?: SelectionMode;
|
|
47
48
|
/** Phase discriminator; scheduled timed releases cannot be entered yet. */
|
|
48
49
|
phase: "scheduled";
|
|
49
50
|
/** Timed release distribution facts from the journey projector. */
|
|
@@ -57,6 +58,7 @@ export interface TimedReleaseScheduled {
|
|
|
57
58
|
export interface TimedReleaseEnterable {
|
|
58
59
|
/** Mechanism discriminator for timed release narrowing. */
|
|
59
60
|
mechanism: "timed_release";
|
|
61
|
+
selectionMode?: SelectionMode;
|
|
60
62
|
/** Phase discriminator; `enter()` is legal on the matching view. */
|
|
61
63
|
phase: "enterable";
|
|
62
64
|
/** Open timed release distribution facts from the journey projector. */
|
|
@@ -72,6 +74,7 @@ export interface TimedReleaseEnterable {
|
|
|
72
74
|
export interface TimedReleaseParticipating {
|
|
73
75
|
/** Mechanism discriminator for timed release narrowing. */
|
|
74
76
|
mechanism: "timed_release";
|
|
77
|
+
selectionMode?: SelectionMode;
|
|
75
78
|
/** Phase discriminator; timed release display is live while participating. */
|
|
76
79
|
phase: "participating";
|
|
77
80
|
/** Timed release distribution facts from the journey projector. */
|
|
@@ -87,6 +90,7 @@ export interface TimedReleaseParticipating {
|
|
|
87
90
|
export interface TimedReleaseGranted {
|
|
88
91
|
/** Mechanism discriminator for timed release narrowing. */
|
|
89
92
|
mechanism: "timed_release";
|
|
93
|
+
selectionMode?: SelectionMode;
|
|
90
94
|
/** Phase discriminator; `claim()` is legal on the matching view. */
|
|
91
95
|
phase: "granted";
|
|
92
96
|
/** Timed release distribution facts from the journey projector. */
|
|
@@ -114,6 +118,7 @@ export interface TimedReleaseGranted {
|
|
|
114
118
|
export interface TimedReleaseEnded {
|
|
115
119
|
/** Mechanism discriminator for timed release narrowing. */
|
|
116
120
|
mechanism: "timed_release";
|
|
121
|
+
selectionMode?: SelectionMode;
|
|
117
122
|
/** Phase discriminator; no timed release actions are legal after this phase. */
|
|
118
123
|
phase: "ended";
|
|
119
124
|
/** Timed release distribution facts from the journey projector. */
|
|
@@ -141,6 +146,7 @@ export interface TimedReleaseScheduledView {
|
|
|
141
146
|
phase: "scheduled";
|
|
142
147
|
/** Mechanism discriminator for timed release rendering. */
|
|
143
148
|
mechanism: "timed_release";
|
|
149
|
+
selectionMode?: SelectionMode;
|
|
144
150
|
/** Timed release distribution facts from the journey projector. */
|
|
145
151
|
distribution: DistributionSummary & {
|
|
146
152
|
type: "timed_release";
|
|
@@ -156,6 +162,7 @@ export interface TimedReleaseEnterableView {
|
|
|
156
162
|
phase: "enterable";
|
|
157
163
|
/** Mechanism discriminator for timed release rendering. */
|
|
158
164
|
mechanism: "timed_release";
|
|
165
|
+
selectionMode?: SelectionMode;
|
|
159
166
|
/** Open timed release distribution facts from the journey projector. */
|
|
160
167
|
distribution: DistributionSummary & {
|
|
161
168
|
type: "timed_release";
|
|
@@ -181,6 +188,7 @@ export interface TimedReleaseParticipatingView {
|
|
|
181
188
|
phase: "participating";
|
|
182
189
|
/** Mechanism discriminator for timed release rendering. */
|
|
183
190
|
mechanism: "timed_release";
|
|
191
|
+
selectionMode?: SelectionMode;
|
|
184
192
|
/** Consumer timed release participation facts. */
|
|
185
193
|
consumer: TimedReleaseSequenceConsumerState;
|
|
186
194
|
/** Live timed release display facts, such as release timing and availability. */
|
|
@@ -209,6 +217,7 @@ interface TimedReleaseGrantedViewBase {
|
|
|
209
217
|
phase: "granted";
|
|
210
218
|
/** Mechanism discriminator for timed release rendering. */
|
|
211
219
|
mechanism: "timed_release";
|
|
220
|
+
selectionMode?: SelectionMode;
|
|
212
221
|
/** Timed release distribution facts from the journey projector. */
|
|
213
222
|
distribution: DistributionSummary & {
|
|
214
223
|
type: "timed_release";
|
|
@@ -279,6 +288,7 @@ export interface TimedReleaseEndedView {
|
|
|
279
288
|
phase: "ended";
|
|
280
289
|
/** Mechanism discriminator for timed release rendering. */
|
|
281
290
|
mechanism: "timed_release";
|
|
291
|
+
selectionMode?: SelectionMode;
|
|
282
292
|
/** Consumer timed release facts at the terminal outcome. */
|
|
283
293
|
consumer: TimedReleaseSequenceConsumerState;
|
|
284
294
|
/** Server-derived terminal outcome for the timed release participation. */
|
|
@@ -290,6 +300,7 @@ export interface TimedReleaseGrantedAwaitingAssignmentView {
|
|
|
290
300
|
phase: "granted";
|
|
291
301
|
/** Mechanism discriminator. */
|
|
292
302
|
mechanism: "timed_release";
|
|
303
|
+
selectionMode?: SelectionMode;
|
|
293
304
|
/** Distribution associated with this grant. */
|
|
294
305
|
distribution: DistributionSummary & {
|
|
295
306
|
type: "timed_release";
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const o="0.
|
|
1
|
+
const o="0.19.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.19.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",
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
"uuid": "^14.0.0",
|
|
116
116
|
"wretch": "^2.11.0",
|
|
117
117
|
"zustand": "^5.0.6",
|
|
118
|
-
"@fanfare-io/fanfare-sdk-contracts": "0.
|
|
118
|
+
"@fanfare-io/fanfare-sdk-contracts": "0.19.0"
|
|
119
119
|
},
|
|
120
120
|
"peerDependencies": {
|
|
121
121
|
"valibot": "^1.1.0"
|
|
@@ -154,7 +154,7 @@
|
|
|
154
154
|
"vite-plugin-dts": "^4.5.4",
|
|
155
155
|
"vite-tsconfig-paths": "^5.1.4",
|
|
156
156
|
"vitest": "^5.0.0",
|
|
157
|
-
"@fanfare-io/shared-models": "0.
|
|
157
|
+
"@fanfare-io/shared-models": "0.19.0"
|
|
158
158
|
},
|
|
159
159
|
"sideEffects": false,
|
|
160
160
|
"keywords": [
|