@fanfare-io/fanfare-sdk-core 0.1.0 → 0.2.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.
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Public harness surface — an in-browser, fetch-intercepting mock of the
3
+ * Fanfare consumer API so integrators can run and verify a storefront
4
+ * integration without a live Fanfare environment.
5
+ *
6
+ * `installHarnessMockServer` installs a stateful mock backend (queue
7
+ * positions count down per poll, draws resolve, gates accept the test OTP /
8
+ * access code) that the real SDK talks to unchanged; point the SDK's `apiUrl`
9
+ * at the returned `apiBaseUrl` (with `environment: "development"`). The
10
+ * pre-built `HARNESS_SCENARIOS` cover every distribution mechanism plus the
11
+ * gated, denied, and grant-expiry paths.
12
+ *
13
+ * Browser-only: the mock intercepts `window.fetch`. Install it from a client
14
+ * effect, never during SSR.
15
+ *
16
+ * These symbols are also reachable via `./test-utils` (internal scaffolding
17
+ * for the first-party adapters); this subpath is the supported customer
18
+ * entry point.
19
+ */
20
+ export { DEFAULT_HARNESS_MOCK_API_BASE_URL, DEFAULT_HARNESS_MOCK_BEACON_BASE_URL, DEFAULT_TEST_OTP_CODE, HARNESS_SCENARIOS, installHarnessMockServer, normalizeHarnessScenario, } from './test-utils/harness-scenarios';
21
+ export type { HarnessRequestLog, HarnessScenarioDefinition, HarnessScenarioInput, HarnessScenarioKey, InstallHarnessMockServerOptions, InstalledHarnessMockServer, } from './test-utils/harness-scenarios';
@@ -0,0 +1 @@
1
+ import{DEFAULT_HARNESS_MOCK_API_BASE_URL as s,DEFAULT_HARNESS_MOCK_BEACON_BASE_URL as r,DEFAULT_TEST_OTP_CODE as t,HARNESS_SCENARIOS as e,installHarnessMockServer as o,normalizeHarnessScenario as i}from"./test-utils/harness-scenarios.js";export{s as DEFAULT_HARNESS_MOCK_API_BASE_URL,r as DEFAULT_HARNESS_MOCK_BEACON_BASE_URL,t as DEFAULT_TEST_OTP_CODE,e as HARNESS_SCENARIOS,o as installHarnessMockServer,i as normalizeHarnessScenario};
@@ -0,0 +1,96 @@
1
+ import { JourneySnapshot } from './experiences/journey.types';
2
+ /** Static key map backing AccessStatus. Order is stable; drives exhaustiveness tests. */
3
+ export declare const ACCESS_STATUSES: readonly ["unconfigured", "loading", "blocked", "available", "granted", "ended"];
4
+ /**
5
+ * Access status for a product surface. Drive EITHER geometry from it:
6
+ * slot replacement (render the widget while not "granted") or adjacent
7
+ * gating (hide your buy form until "granted").
8
+ *
9
+ * - "unconfigured": no experience on this product → show native purchase UI
10
+ * - "loading": journey booting
11
+ * - "blocked": gated / queued / awaiting result — purchase must not proceed
12
+ * - "available": open for participation (enterable)
13
+ * - "granted": shopper holds a grant — reveal purchase
14
+ * - "ended": terminal without grant (denied / expired / closed)
15
+ */
16
+ export type AccessStatus = (typeof ACCESS_STATUSES)[number];
17
+ /**
18
+ * PURE, SSR-safe. post-#1103 JourneySnapshot → AccessStatus. A `null` snapshot
19
+ * (no session yet / pre-boot) maps to "loading". Never returns "unconfigured":
20
+ * that is decided UPSTREAM of any snapshot (no experience mapped to the product)
21
+ * and there is no snapshot to inspect at that point.
22
+ */
23
+ export declare function snapshotToAccessStatus(snapshot: JourneySnapshot | null): AccessStatus;
24
+ export interface ExperienceResolver {
25
+ /**
26
+ * Return the experience id for a product, or null when the product is not
27
+ * covered (the storefront then renders its native purchase UI and the SDK
28
+ * never boots). May be sync (metafield already on your product object) or
29
+ * async (a lookup call).
30
+ */
31
+ resolve(product: {
32
+ id: string;
33
+ handle: string;
34
+ }): string | null | Promise<string | null>;
35
+ }
36
+ export interface GrantRecord {
37
+ /**
38
+ * The client-visible grant value the adapter records when the shopper clears
39
+ * the drop. Today this is the internal admission token; post-ENG-913 it is the
40
+ * opaque, single-use handoff token minted at claim (see `capabilityGrant`).
41
+ */
42
+ token: string;
43
+ experienceId: string;
44
+ /** ms timestamp; absent = no client-side expiry known. */
45
+ expiresAt?: number;
46
+ /**
47
+ * ENG-913 mint-at-claim seam (optional, forward-compatible). The capability
48
+ * grant (a.k.a. `sequenceCapabilityGrant` on the routing contract) the SDK
49
+ * derives from the routing decision. When a claim-time minter is wired
50
+ * (`createHandoffToken({ capabilityGrant })`), the recorder MINTS at claim and
51
+ * stores the resulting handoff token in `token`, carrying the originating
52
+ * capability grant here for diagnostics / re-mint. Absent today: the
53
+ * placeholder verifier checks only client-side expiry, so none is recorded.
54
+ */
55
+ capabilityGrant?: string;
56
+ /**
57
+ * ENG-913 mint-at-claim seam (optional, forward-compatible). Set true once
58
+ * `token` is a server-minted, single-use handoff token (vs. the pre-ENG-913
59
+ * internal admission token). Lets the checkout verifier distinguish a
60
+ * redeemable handoff from a capability grant without a surface change.
61
+ */
62
+ handoffToken?: boolean;
63
+ }
64
+ export interface VerificationResult {
65
+ ok: boolean;
66
+ /** Static reason key on denial (e.g. "grant_expired", "redeem_failed", "replayed"). */
67
+ reason?: string;
68
+ }
69
+ export interface CheckoutVerifier {
70
+ /**
71
+ * Called at checkout entry with the grant the adapter recorded when the
72
+ * shopper cleared the drop.
73
+ *
74
+ * TOTAL: resolves for EVERY outcome — valid, expired, replayed, malformed, and
75
+ * network/redeem-denied handoffs all resolve to { ok:false, reason }. NEVER
76
+ * rejects: the checkout gate consumes this with `.then()` only, so a thrown
77
+ * redeem failure would strand the gate in "checking" or surface as an
78
+ * unhandled rejection. The ENG-913 implementation MUST wrap core's throwing
79
+ * redeem path (`processHandoffToken` throws on invalid/expired/replayed) into a
80
+ * denied result.
81
+ */
82
+ verify(grant: GrantRecord): Promise<VerificationResult>;
83
+ }
84
+ /**
85
+ * Checkout-entry guard state. "checking" → verifying; "granted" → proceed;
86
+ * "denied" → bounce the shopper back to the drop. Products outside the drop are
87
+ * the caller's policy.
88
+ */
89
+ export type CheckoutAccess = {
90
+ state: "checking";
91
+ } | {
92
+ state: "granted";
93
+ } | {
94
+ state: "denied";
95
+ reason: string;
96
+ };
@@ -0,0 +1 @@
1
+ const e=["unconfigured","loading","blocked","available","granted","ended"];function a(e){if(null===e)return"loading";switch(e.journeyStage){case"ready":case"routing":return"loading";case"gated":return"blocked";case"routed":switch(e.sequence.phase){case"enterable":return"available";case"granted":return"granted";case"ended":case"unavailable":return"ended";default:return"blocked"}}}export{e as ACCESS_STATUSES,a as snapshotToAccessStatus};
@@ -1,18 +1,5 @@
1
1
  import { MockServer } from './mock-server';
2
2
  export type HarnessScenarioKey = "queue" | "waitlist-queue" | "auth-queue" | "access-code-queue" | "queue-denied" | "draw" | "draw-denied" | "timed-release" | "auction" | "auth-draw" | "admission-cycle";
3
- /**
4
- * Optional fast-forward marker. When passed on a scenario input, the
5
- * corresponding distribution mock primes its internal state so the SDK
6
- * routes straight to the named stage instead of starting at the pre-entry
7
- * stage. Stages that don't apply to a distribution are ignored.
8
- *
9
- * Currently supported per distribution:
10
- * - queue: "start" (default), "granted"
11
- * - draw: "start" (default), "granted"
12
- * - auction: "start" (default), "granted"
13
- * - timed-release: "start" (default), "granted"
14
- */
15
- export type HarnessStage = "start" | "granted";
16
3
  export type HarnessScenarioDefinition = {
17
4
  key: HarnessScenarioKey;
18
5
  label: string;
@@ -24,11 +11,16 @@ export type HarnessScenarioDefinition = {
24
11
  drawId?: string;
25
12
  timedReleaseId?: string;
26
13
  auctionId?: string;
27
- stage?: HarnessStage;
14
+ /**
15
+ * Draw scenarios only: how far in the future the draw resolves (drawTime /
16
+ * entryDeadline), in milliseconds. Defaults to 2 hours. The SDK schedules
17
+ * its draw status check at drawTime, so demos that want a visibly resolving
18
+ * draw should pass a short delay (e.g. 45_000).
19
+ */
20
+ drawDelayMs?: number;
28
21
  };
29
22
  export type HarnessScenarioInput = HarnessScenarioKey | (Partial<HarnessScenarioDefinition> & {
30
23
  key: HarnessScenarioKey;
31
- stage?: HarnessStage;
32
24
  });
33
25
  export type HarnessRequestLog = {
34
26
  api: ReturnType<MockServer["getRequests"]>;
@@ -1 +1 @@
1
- import{isMoneyString as e,isMoneyGreaterThan as t,isMoneyGreaterThanOrEqualTo as n}from"../core/money.js";import{MockServer as s,ResponseBuilder as o}from"./mock-server.js";const a="http://mock.local/api",i="http://mock.local/beacon",u="424242";function r(e){const t={isEntered:!1,enteredAt:null};try{const n=window.localStorage.getItem(e);if(!n)return t;const s=JSON.parse(n);return{isEntered:!0===s.isEntered,enteredAt:"string"==typeof s.enteredAt?s.enteredAt:null}}catch{return t}}function d(e,t){window.localStorage.setItem(e,JSON.stringify(t))}const c={queue:{key:"queue",label:"Queue Journey",experienceId:"experience_queue_story_1",sequenceId:"sequence_queue_story_1",queueId:"queue_queue_story_1"},"waitlist-queue":{key:"waitlist-queue",label:"Waitlist to Queue Journey",experienceId:"experience_waitlist_queue_story_1",sequenceId:"sequence_waitlist_queue_story_1",queueId:"queue_waitlist_queue_story_1",waitlistId:"waitlist_waitlist_queue_story_1"},"auth-queue":{key:"auth-queue",label:"Auth-Gated Queue Journey",experienceId:"experience_auth_queue_story_1",sequenceId:"sequence_auth_queue_story_1",queueId:"queue_auth_queue_story_1"},"access-code-queue":{key:"access-code-queue",label:"Access-Code Queue Journey",experienceId:"experience_access_code_queue_story_1",sequenceId:"sequence_access_code_queue_story_1",queueId:"queue_access_code_queue_story_1",accessCode:"VIP123"},draw:{key:"draw",label:"Draw Journey",experienceId:"experience_draw_story_1",sequenceId:"sequence_draw_story_1",drawId:"draw_draw_story_1"},"timed-release":{key:"timed-release",label:"Timed Release Journey",experienceId:"experience_timed_release_story_1",sequenceId:"sequence_timed_release_story_1",timedReleaseId:"timed_release_story_1"},auction:{key:"auction",label:"Auction Journey",experienceId:"experience_auction_story_1",sequenceId:"sequence_auction_story_1",auctionId:"auction_auction_story_1"},"auth-draw":{key:"auth-draw",label:"Auth-Gated Draw Journey",experienceId:"experience_auth_draw_story_1",sequenceId:"sequence_auth_draw_story_1",drawId:"draw_auth_draw_story_1"},"admission-cycle":{key:"admission-cycle",label:"Admission Cycle Journey",experienceId:"experience_admission_cycle_story_1",sequenceId:"sequence_admission_cycle_story_1",queueId:"queue_admission_cycle_story_1"},"queue-denied":{key:"queue-denied",label:"Queue Denied (not selected)",experienceId:"experience_queue_denied_story_1",sequenceId:"sequence_queue_denied_story_1",queueId:"queue_queue_denied_story_1"},"draw-denied":{key:"draw-denied",label:"Draw Denied (not selected)",experienceId:"experience_draw_denied_story_1",sequenceId:"sequence_draw_denied_story_1",drawId:"draw_draw_denied_story_1"}};function _(e){return e.startsWith("http://")||e.startsWith("https://")?e:new URL(e,window.location.origin).toString()}function l(e){if(!e)return c.queue;if("string"==typeof e)return c[e]??c.queue;return{...c[e.key]??c.queue,...e}}async function m(e){try{const t=await e.clone().json();return"object"==typeof t&&null!==t?t:void 0}catch{return}}function I(e,t){return{baseUrl:e,defaultDelay:t.defaultDelay??30,logRequests:t.logRequests??!1,fallbackToNetwork:!1}}function p(e){return function(e){const t=e.headers.get("DPoP"),n=e.headers.get("X-Admission-Key-Thumbprint");if(!t||!n)return!1;const s=t.split(".");return 3===s.length&&!s.some(e=>0===e.length)&&/^[A-Za-z0-9_-]{16,}$/.test(n)}(e)?null:o.badRequest("Missing admission proof headers")}function y(e={}){const t=e.scenarios?.length?e.scenarios.map(e=>l(e)):[l(e.scenario)],n=t[0],d=_(e.apiBaseUrl??a),c=_(e.beaconBaseUrl??i),p=e.otpCode??u,y=new s(I(d,e)),E=new s(I(c,e)),h=/* @__PURE__ */new Date,A=h.toISOString(),x=new Date(h.getTime()+864e5).toISOString(),T={sessionType:null};!function(e,t){const n={id:"session_mock_demo",consumerId:"consumer_mock_demo",guestId:"guest_mock_demo",type:"guest",email:null,phone:null,createdAt:t.nowIso,expiresAt:t.expiresAtIso};e.post("/auth/guest",()=>(t.authState.sessionType="guest",o.ok({session:n,accessToken:"guest_access_token_mock_demo",refreshToken:"guest_refresh_token_mock_demo",beaconToken:"guest_beacon_token_mock_demo"}))),e.post("/auth/refresh",()=>o.ok({accessToken:`access_token_mock_demo_${Date.now()}`,refreshToken:"guest_refresh_token_mock_demo",beaconToken:"authenticated"===t.authState.sessionType?"authenticated_beacon_token_mock_demo":"guest_beacon_token_mock_demo"})),e.post("/auth/otp/request",o.ok({ok:!0})),e.post("/auth/otp/verify",async e=>{const n=await m(e);return("string"==typeof n?.code?n.code:void 0)!==t.otpCode?o.error("Invalid verification code",401):(t.authState.sessionType="authenticated",o.ok({session:{id:"session_authenticated_mock_demo",consumerId:"consumer_authenticated_mock_demo",type:"authenticated",email:"string"==typeof n?.email?n.email:"sdk-harness@example.com",phone:"string"==typeof n?.phone?n.phone:null,createdAt:t.nowIso,expiresAt:t.expiresAtIso},accessToken:"authenticated_access_token_mock_demo",refreshToken:"authenticated_refresh_token_mock_demo",beaconToken:"authenticated_beacon_token_mock_demo"}))}),e.post("/auth/external/exchange",async e=>{const n=await m(e);return("string"==typeof n?.exchangeCode?n.exchangeCode:void 0)?(t.authState.sessionType="authenticated",o.ok({session:{id:"session_external_mock_demo",consumerId:"consumer_external_mock_demo",type:"authenticated",email:"external-auth@example.com",phone:null,createdAt:t.nowIso,expiresAt:t.expiresAtIso},accessToken:"external_access_token_mock_demo",refreshToken:"external_refresh_token_mock_demo",beaconToken:"authenticated_beacon_token_mock_demo"})):o.error("Invalid exchange code",401)})}(y,{nowIso:A,expiresAtIso:x,otpCode:p,authState:T}),function(e){const t=()=>o.ok({ok:!0});e.post("/events",t),e.post("/events/batch",t)}(E);for(const s of t){const e=s.waitlistId?`__fanfare_harness_waitlist__:${s.key}:${s.experienceId}`:void 0,t=s.waitlistId?r(e??""):void 0;k(y,s,{authState:T,expiresAtIso:x,waitlistState:t}),s.queueId&&w(y,{queueId:s.queueId,experienceId:s.experienceId,name:"Journey Queue",initialPosition:"admission-cycle"===s.key?2:5,initialEstimatedWaitSeconds:90,autoExpireAfterGrant:"admission-cycle"===s.key,forceDenyOnEnter:"queue-denied"===s.key}),s.waitlistId&&g(y,{waitlistId:s.waitlistId,sequenceId:s.sequenceId,state:t??{isEntered:!1,enteredAt:null},storageKey:e??""}),s.drawId&&q(y,{drawId:s.drawId,forceDenyOnEnter:"draw-denied"===s.key}),s.timedReleaseId&&D(y,{timedReleaseId:s.timedReleaseId,closeAt:new Date(Date.now()+9e5).toISOString()}),s.auctionId&&S(y,{auctionId:s.auctionId})}return y.start(),E.start(),{apiBaseUrl:d,beaconBaseUrl:c,scenario:n,scenarios:t,stop(){E.stop(),y.stop()},getRequests:()=>({api:y.getRequests(),beacon:E.getRequests()})}}function k(e,t,n){const s=(/* @__PURE__ */new Date).toISOString();e.get("/consumers/me",o.ok({active:{journeys:[]}})),e.get(`/experiences/${t.experienceId}`,o.ok({id:t.experienceId,name:t.label,createdAt:s,updatedAt:s,i18n:{en:{"start.title":t.label,"start.description":"Mock data served from the harness mock server."}}})),e.post(`/experiences/${t.experienceId}/enter`,o.ok({experienceId:t.experienceId,enteredAt:s}));const a=e=>({id:t.sequenceId,name:e,experienceId:t.experienceId,priority:1,color:"#000000"}),i=(e,n,s)=>({schemaVersion:1,experienceId:t.experienceId,outcome:"gated",selected:{sequence:e,status:"gated",gates:[n],reasons:s},offers:[],outcomeReasons:s}),u=e=>({schemaVersion:1,experienceId:t.experienceId,outcome:"routed",selected:{sequence:e,status:"admissible",gates:[],reasons:[],sequenceCapabilityGrant:`mock_sequence_capability_grant_${t.sequenceId}`,sequenceCapabilityGrantExpiresAt:n.expiresAtIso},offers:[],outcomeReasons:[]});"auth-queue"===t.key||"auth-draw"===t.key?e.post(`/experiences/${t.experienceId}/route`,()=>"authenticated"!==n.authState.sessionType?o.ok(i(a("auth-draw"===t.key?"Auth-Gated Draw Sequence":"Auth-Gated Queue Sequence"),{type:"authentication",status:"required",reason:{code:"AUTH_REQUIRED"}},[{code:"AUTH_REQUIRED"}])):o.ok(u(a("auth-draw"===t.key?"Auth-Gated Draw Sequence":"Auth-Gated Queue Sequence")))):"access-code-queue"===t.key?e.post(`/experiences/${t.experienceId}/route`,async e=>{const n=await m(e),s="string"==typeof n?.accessCode?n.accessCode:void 0;return s?s!==t.accessCode?o.ok(i(a("Access-Code Queue Sequence"),{type:"access_code",status:"invalid",reason:{code:"ACCESS_CODE_INVALID"}},[{code:"ACCESS_CODE_INVALID"}])):o.ok(u(a("Access-Code Queue Sequence"))):o.ok(i(a("Access-Code Queue Sequence"),{type:"access_code",status:"missing",reason:{code:"ACCESS_CODE_REQUIRED"}},[{code:"ACCESS_CODE_REQUIRED"}]))}):e.post(`/experiences/${t.experienceId}/route`,o.ok(u(a(`${t.label} Sequence`)))),"waitlist-queue"!==t.key?"draw"!==t.key&&"auth-draw"!==t.key&&"draw-denied"!==t.key?"timed-release"!==t.key?"auction"!==t.key?e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=/* @__PURE__ */(new Date).toISOString();return o.ok({recentPast:void 0,active:{type:"queue",id:t.queueId,status:"active",details:{id:t.queueId,type:"queue",openAt:e,metadata:{label:"Journey Queue"},estimatedWaitTime:300,queueLength:10}},upcoming:void 0})}):e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=Date.now(),n=new Date(e).toISOString();return o.ok({recentPast:void 0,active:{type:"auction",id:t.auctionId,status:"active",details:{id:t.auctionId,type:"auction",openAt:n,endsAt:new Date(e+36e5).toISOString(),startsAt:n,currencyCode:"USD",reservePrice:"50.00",bidIncrement:"10.00"}},upcoming:void 0})}):e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=Date.now();return o.ok({recentPast:void 0,active:{type:"timed_release",id:t.timedReleaseId,status:"active",details:{id:t.timedReleaseId,type:"timed_release",openAt:new Date(e).toISOString(),closeAt:new Date(e+9e5).toISOString()}},upcoming:void 0})}):e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=Date.now(),n=new Date(e+72e5).toISOString();return o.ok({recentPast:void 0,active:{type:"draw",id:t.drawId,status:"active",details:{id:t.drawId,type:"draw",openAt:new Date(e).toISOString(),drawTime:n,entryDeadline:n}},upcoming:void 0})}):e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=/* @__PURE__ */(new Date).toISOString();return n.waitlistState?.isEntered?o.ok({recentPast:void 0,active:{type:"queue",id:t.queueId,status:"active",details:{id:t.queueId,type:"queue",openAt:e,closeAt:new Date(Date.now()+18e5).toISOString(),metadata:{label:"Journey Queue (Window Open)"},estimatedWaitTime:300,queueLength:10}},upcoming:void 0}):o.ok({recentPast:void 0,active:void 0,upcoming:{type:"queue",id:t.queueId,startsAt:new Date(Date.now()+6e4).toISOString(),waitlistId:t.waitlistId}})})}function w(e,t){const{queueId:n,experienceId:s="experience_mock",name:a="Mock Queue",initialPosition:i=12,initialEstimatedWaitSeconds:u=300,autoExpireAfterGrant:r=!1,forceDenyOnEnter:d=!1}=t;let c=!1,_=!1,l=i,m=u,I=0;e.get(`/queues/${n}`,o.ok({id:n,experienceId:s,name:a,status:"open",capacity:500,currentSize:247,estimatedWaitTime:m,openAt:new Date(Date.now()-3e5).toISOString(),closeAt:new Date(Date.now()+36e5).toISOString()})),e.post(`/queues/${n}/enter`,e=>{const t=p(e);return t||(d?o.ok({status:"DENIED"}):(c=!0,_=!1,I=0,l=i,m=u,o.ok({position:l,estimatedWaitTimeInSeconds:m,status:"QUEUED"})))}),e.post(`/queues/${n}/leave`,()=>(c=!1,_=!1,I=0,o.ok({}))),e.get(`/queues/${n}/status`,()=>c?_?(I+=1,r&&I>1?(c=!1,_=!1,o.ok({status:"EXPIRED"})):o.ok({status:"GRANTED",admissionGrant:`admission_grant_${n}`,expiresAt:new Date(Date.now()+6e5).toISOString()})):(l=Math.max(1,l-1),m=Math.max(0,m-30),l<=1?(_=!0,I=1,o.ok({status:"GRANTED",admissionGrant:`admission_grant_${n}`,expiresAt:new Date(Date.now()+6e5).toISOString()})):o.ok({status:"QUEUED",position:l,estimatedWaitTimeInSeconds:m})):o.ok({status:"NOT_QUEUED"}))}function q(e,t){const{drawId:n,drawAtOffsetMs:s=72e5,forceDenyOnEnter:a=!1}=t;let i="NOT_ENTERED",u=0;e.get(`/draws/${n}`,()=>o.ok({id:n,openAt:new Date(Date.now()-6e4).toISOString(),closeAt:null,timeZone:"UTC",drawAt:new Date(Date.now()+s).toISOString(),capacity:null,continueSelectingUntilCompleted:null})),e.get(`/draws/${n}/status`,()=>"NOT_ENTERED"===i?o.ok({status:"NOT_ENTERED"}):(u+=1,u>=2?o.ok({status:"WON",wonAt:/* @__PURE__ */(new Date).toISOString(),admissionGrant:`admission_grant_${n}`}):o.ok({status:"ENTERED"}))),e.post(`/draws/${n}/enter`,e=>{const t=p(e);return t||(a?o.ok({status:"DENIED"}):(i="ENTERED",u=0,o.ok({status:"ENTERED"})))}),e.post(`/draws/${n}/leave`,()=>(i="NOT_ENTERED",u=0,o.ok({})))}function g(e,t){const{waitlistId:n,sequenceId:s,state:a,storageKey:i}=t;e.get(`/waitlists/${n}/status`,()=>o.ok({waitlistId:n,isEntered:a.isEntered,enteredAt:a.enteredAt??void 0})),e.post(`/waitlists/${n}/enter`,()=>(a.isEntered=!0,a.enteredAt=/* @__PURE__ */(new Date).toISOString(),d(i,a),o.ok({id:`waitlist_entry_${n}`,waitlistId:n,sequenceId:s,consumerId:"consumer_mock_demo",enteredAt:a.enteredAt})));const u=()=>(a.isEntered=!1,a.enteredAt=null,d(i,a),o.ok({}));e.delete(`/waitlists/${n}/leave`,u),e.post(`/waitlists/${n}/leave`,u)}function D(e,t){const{timedReleaseId:n,closeAt:s}=t;let a="NOT_ENTERED",i=null,u=null;e.get(`/timed-releases/${n}`,o.ok({id:n,openAt:new Date(Date.now()-6e4).toISOString(),closeAt:s,timeZone:"America/Los_Angeles",supportsGuest:!0})),e.get(`/timed-releases/${n}/status`,()=>"ENTERED"===a?o.ok({status:"ENTERED",enteredAt:i??/* @__PURE__ */(new Date).toISOString()}):"COMPLETED"===a?o.ok({status:"COMPLETED",completedAt:u??/* @__PURE__ */(new Date).toISOString()}):"LEFT"===a?o.ok({status:"LEFT",leftAt:/* @__PURE__ */(new Date).toISOString()}):o.ok({status:"NOT_ENTERED"})),e.post(`/timed-releases/${n}/enter`,async e=>{const t=await m(e),n="string"==typeof t?.variantId?t.variantId:void 0;return a="ENTERED",i=/* @__PURE__ */(new Date).toISOString(),o.ok({status:"ENTERED",enteredAt:i,selectedVariantId:n})}),e.post(`/timed-releases/${n}/leave`,()=>(a="LEFT",o.ok({}))),e.post(`/timed-releases/${n}/complete`,()=>(a="COMPLETED",u=/* @__PURE__ */(new Date).toISOString(),o.ok({success:!0,admissionGrant:`admission_grant_${n}`})))}function S(s,a){const{auctionId:i}=a,u=/* @__PURE__ */new Date,r=u.toISOString(),d=new Date(u.getTime()+6e5).toISOString();let c="100.00",_=null,l=12,I=!1,p=[{bidId:"bid_1",consumerId:"consumer_mock_demo",amount:"80.00",timestamp:r},{bidId:"bid_2",consumerId:"consumer_mock_demo",amount:"90.00",timestamp:r}];s.get(`/auctions/${i}`,o.ok({id:i,openAt:r,closeAt:d,settleAt:d,currencyCode:"USD",reservePrice:null,minBidIncrement:"10.00",autoExtendSeconds:null,timeZone:"UTC"})),s.get(`/auctions/${i}/highest-bid`,()=>o.ok({amount:c})),s.get(`/auctions/${i}/status`,()=>{const e=null===_?"NOT_BID":n(_,c)?"WINNING":I?"OUTBID":"NOT_BID";return o.ok({status:e,lastBidAmount:_??void 0,bidCount:l,auctionEndTime:d})}),s.post(`/auctions/${i}/enter`,()=>(I=!0,o.ok({}))),s.post(`/auctions/${i}/leave`,()=>(I=!1,_=null,o.ok({}))),s.post(`/auctions/${i}/bid`,async s=>{const a=await m(s),i=a?.amount,u="string"==typeof i?i:"";return e(u)?(_=u,l+=1,t(u,c)&&(c=u),p=[...p,{bidId:`bid_${p.length+1}`,consumerId:"consumer_mock_demo",amount:u,timestamp:/* @__PURE__ */(new Date).toISOString()}],o.ok({status:n(u,c)?"WINNING":"OUTBID",lastBidAmount:u,bidCount:l,winningBidAmount:c,winningBidTime:/* @__PURE__ */(new Date).toISOString(),auctionEndTime:d,paymentToken:null})):o.badRequest("Invalid bid amount")}),s.get(`/auctions/${i}/bids/history`,()=>o.ok(p.map(e=>({...e,isHighest:e.amount===c}))))}export{a as DEFAULT_HARNESS_MOCK_API_BASE_URL,i as DEFAULT_HARNESS_MOCK_BEACON_BASE_URL,u as DEFAULT_TEST_OTP_CODE,c as HARNESS_SCENARIOS,y as installHarnessMockServer,l as normalizeHarnessScenario};
1
+ import{isMoneyString as e,isMoneyGreaterThan as t,isMoneyGreaterThanOrEqualTo as n}from"../core/money.js";import{MockServer as s,ResponseBuilder as o}from"./mock-server.js";const a="http://mock.local/api",i="http://mock.local/beacon",u="424242";function r(e){const t={isEntered:!1,enteredAt:null};try{const n=window.localStorage.getItem(e);if(!n)return t;const s=JSON.parse(n);return{isEntered:!0===s.isEntered,enteredAt:"string"==typeof s.enteredAt?s.enteredAt:null}}catch{return t}}function d(e,t){window.localStorage.setItem(e,JSON.stringify(t))}const c={queue:{key:"queue",label:"Queue Journey",experienceId:"experience_queue_story_1",sequenceId:"sequence_queue_story_1",queueId:"queue_queue_story_1"},"waitlist-queue":{key:"waitlist-queue",label:"Waitlist to Queue Journey",experienceId:"experience_waitlist_queue_story_1",sequenceId:"sequence_waitlist_queue_story_1",queueId:"queue_waitlist_queue_story_1",waitlistId:"waitlist_waitlist_queue_story_1"},"auth-queue":{key:"auth-queue",label:"Auth-Gated Queue Journey",experienceId:"experience_auth_queue_story_1",sequenceId:"sequence_auth_queue_story_1",queueId:"queue_auth_queue_story_1"},"access-code-queue":{key:"access-code-queue",label:"Access-Code Queue Journey",experienceId:"experience_access_code_queue_story_1",sequenceId:"sequence_access_code_queue_story_1",queueId:"queue_access_code_queue_story_1",accessCode:"VIP123"},draw:{key:"draw",label:"Draw Journey",experienceId:"experience_draw_story_1",sequenceId:"sequence_draw_story_1",drawId:"draw_draw_story_1"},"timed-release":{key:"timed-release",label:"Timed Release Journey",experienceId:"experience_timed_release_story_1",sequenceId:"sequence_timed_release_story_1",timedReleaseId:"timed_release_story_1"},auction:{key:"auction",label:"Auction Journey",experienceId:"experience_auction_story_1",sequenceId:"sequence_auction_story_1",auctionId:"auction_auction_story_1"},"auth-draw":{key:"auth-draw",label:"Auth-Gated Draw Journey",experienceId:"experience_auth_draw_story_1",sequenceId:"sequence_auth_draw_story_1",drawId:"draw_auth_draw_story_1"},"admission-cycle":{key:"admission-cycle",label:"Admission Cycle Journey",experienceId:"experience_admission_cycle_story_1",sequenceId:"sequence_admission_cycle_story_1",queueId:"queue_admission_cycle_story_1"},"queue-denied":{key:"queue-denied",label:"Queue Denied (not selected)",experienceId:"experience_queue_denied_story_1",sequenceId:"sequence_queue_denied_story_1",queueId:"queue_queue_denied_story_1"},"draw-denied":{key:"draw-denied",label:"Draw Denied (not selected)",experienceId:"experience_draw_denied_story_1",sequenceId:"sequence_draw_denied_story_1",drawId:"draw_draw_denied_story_1"}};function _(e){return e.startsWith("http://")||e.startsWith("https://")?e:new URL(e,window.location.origin).toString()}function l(e){if(!e)return c.queue;if("string"==typeof e)return c[e]??c.queue;return{...c[e.key]??c.queue,...e}}async function m(e){try{const t=await e.clone().json();return"object"==typeof t&&null!==t?t:void 0}catch{return}}function I(e,t){return{baseUrl:e,defaultDelay:t.defaultDelay??30,logRequests:t.logRequests??!1,fallbackToNetwork:!1}}function p(e){return function(e){const t=e.headers.get("DPoP"),n=e.headers.get("X-Admission-Key-Thumbprint");if(!t||!n)return!1;const s=t.split(".");return 3===s.length&&!s.some(e=>0===e.length)&&/^[A-Za-z0-9_-]{16,}$/.test(n)}(e)?null:o.badRequest("Missing admission proof headers")}function y(e={}){const t=e.scenarios?.length?e.scenarios.map(e=>l(e)):[l(e.scenario)],n=t[0],d=_(e.apiBaseUrl??a),c=_(e.beaconBaseUrl??i),p=e.otpCode??u,y=new s(I(d,e)),E=new s(I(c,e)),h=/* @__PURE__ */new Date,A=h.toISOString(),x=new Date(h.getTime()+864e5).toISOString(),T={sessionType:null};!function(e,t){const n={id:"session_mock_demo",consumerId:"consumer_mock_demo",guestId:"guest_mock_demo",type:"guest",email:null,phone:null,createdAt:t.nowIso,expiresAt:t.expiresAtIso};e.post("/auth/guest",()=>(t.authState.sessionType="guest",o.ok({session:n,accessToken:"guest_access_token_mock_demo",refreshToken:"guest_refresh_token_mock_demo",beaconToken:"guest_beacon_token_mock_demo"}))),e.post("/auth/refresh",()=>o.ok({accessToken:`access_token_mock_demo_${Date.now()}`,refreshToken:"guest_refresh_token_mock_demo",beaconToken:"authenticated"===t.authState.sessionType?"authenticated_beacon_token_mock_demo":"guest_beacon_token_mock_demo"})),e.post("/auth/otp/request",o.ok({ok:!0})),e.post("/auth/otp/verify",async e=>{const n=await m(e);return("string"==typeof n?.code?n.code:void 0)!==t.otpCode?o.error("Invalid verification code",401):(t.authState.sessionType="authenticated",o.ok({session:{id:"session_authenticated_mock_demo",consumerId:"consumer_authenticated_mock_demo",type:"authenticated",email:"string"==typeof n?.email?n.email:"sdk-harness@example.com",phone:"string"==typeof n?.phone?n.phone:null,createdAt:t.nowIso,expiresAt:t.expiresAtIso},accessToken:"authenticated_access_token_mock_demo",refreshToken:"authenticated_refresh_token_mock_demo",beaconToken:"authenticated_beacon_token_mock_demo"}))}),e.post("/auth/external/exchange",async e=>{const n=await m(e);return("string"==typeof n?.exchangeCode?n.exchangeCode:void 0)?(t.authState.sessionType="authenticated",o.ok({session:{id:"session_external_mock_demo",consumerId:"consumer_external_mock_demo",type:"authenticated",email:"external-auth@example.com",phone:null,createdAt:t.nowIso,expiresAt:t.expiresAtIso},accessToken:"external_access_token_mock_demo",refreshToken:"external_refresh_token_mock_demo",beaconToken:"authenticated_beacon_token_mock_demo"})):o.error("Invalid exchange code",401)})}(y,{nowIso:A,expiresAtIso:x,otpCode:p,authState:T}),function(e){const t=()=>o.ok({ok:!0});e.post("/events",t),e.post("/events/batch",t)}(E);for(const s of t){const e=s.waitlistId?`__fanfare_harness_waitlist__:${s.key}:${s.experienceId}`:void 0,t=s.waitlistId?r(e??""):void 0;k(y,s,{authState:T,expiresAtIso:x,waitlistState:t}),s.queueId&&w(y,{queueId:s.queueId,experienceId:s.experienceId,name:"Journey Queue",initialPosition:"admission-cycle"===s.key?2:5,initialEstimatedWaitSeconds:90,autoExpireAfterGrant:"admission-cycle"===s.key,forceDenyOnEnter:"queue-denied"===s.key}),s.waitlistId&&g(y,{waitlistId:s.waitlistId,sequenceId:s.sequenceId,state:t??{isEntered:!1,enteredAt:null},storageKey:e??""}),s.drawId&&q(y,{drawId:s.drawId,forceDenyOnEnter:"draw-denied"===s.key}),s.timedReleaseId&&D(y,{timedReleaseId:s.timedReleaseId,closeAt:new Date(Date.now()+9e5).toISOString()}),s.auctionId&&S(y,{auctionId:s.auctionId})}return y.start(),E.start(),{apiBaseUrl:d,beaconBaseUrl:c,scenario:n,scenarios:t,stop(){E.stop(),y.stop()},getRequests:()=>({api:y.getRequests(),beacon:E.getRequests()})}}function k(e,t,n){const s=(/* @__PURE__ */new Date).toISOString();e.get("/consumers/me",o.ok({active:{journeys:[]}})),e.get(`/experiences/${t.experienceId}`,o.ok({id:t.experienceId,name:t.label,createdAt:s,updatedAt:s,i18n:{en:{"start.title":t.label,"start.description":"Mock data served from the harness mock server."}}})),e.post(`/experiences/${t.experienceId}/enter`,o.ok({experienceId:t.experienceId,enteredAt:s}));const a=e=>({id:t.sequenceId,name:e,experienceId:t.experienceId,priority:1,color:"#000000"}),i=(e,n,s)=>({schemaVersion:1,experienceId:t.experienceId,outcome:"gated",selected:{sequence:e,status:"gated",gates:[n],reasons:s},offers:[],outcomeReasons:s}),u=e=>({schemaVersion:1,experienceId:t.experienceId,outcome:"routed",selected:{sequence:e,status:"admissible",gates:[],reasons:[],sequenceCapabilityGrant:`mock_sequence_capability_grant_${t.sequenceId}`,sequenceCapabilityGrantExpiresAt:n.expiresAtIso},offers:[],outcomeReasons:[]});"auth-queue"===t.key||"auth-draw"===t.key?e.post(`/experiences/${t.experienceId}/route`,()=>"authenticated"!==n.authState.sessionType?o.ok(i(a("auth-draw"===t.key?"Auth-Gated Draw Sequence":"Auth-Gated Queue Sequence"),{type:"authentication",status:"required",reason:{code:"AUTH_REQUIRED"}},[{code:"AUTH_REQUIRED"}])):o.ok(u(a("auth-draw"===t.key?"Auth-Gated Draw Sequence":"Auth-Gated Queue Sequence")))):"access-code-queue"===t.key?e.post(`/experiences/${t.experienceId}/route`,async e=>{const n=await m(e),s="string"==typeof n?.accessCode?n.accessCode:void 0;return s?s!==t.accessCode?o.ok(i(a("Access-Code Queue Sequence"),{type:"access_code",status:"invalid",reason:{code:"ACCESS_CODE_INVALID"}},[{code:"ACCESS_CODE_INVALID"}])):o.ok(u(a("Access-Code Queue Sequence"))):o.ok(i(a("Access-Code Queue Sequence"),{type:"access_code",status:"missing",reason:{code:"ACCESS_CODE_REQUIRED"}},[{code:"ACCESS_CODE_REQUIRED"}]))}):e.post(`/experiences/${t.experienceId}/route`,o.ok(u(a(`${t.label} Sequence`)))),"waitlist-queue"!==t.key?"draw"!==t.key&&"auth-draw"!==t.key&&"draw-denied"!==t.key?"timed-release"!==t.key?"auction"!==t.key?e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=/* @__PURE__ */(new Date).toISOString();return o.ok({recentPast:void 0,active:{type:"queue",id:t.queueId,status:"active",details:{id:t.queueId,type:"queue",openAt:e,metadata:{label:"Journey Queue"},estimatedWaitTime:300,queueLength:10}},upcoming:void 0})}):e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=Date.now(),n=new Date(e).toISOString();return o.ok({recentPast:void 0,active:{type:"auction",id:t.auctionId,status:"active",details:{id:t.auctionId,type:"auction",openAt:n,endsAt:new Date(e+36e5).toISOString(),startsAt:n,currencyCode:"USD",reservePrice:"50.00",bidIncrement:"10.00"}},upcoming:void 0})}):e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=Date.now();return o.ok({recentPast:void 0,active:{type:"timed_release",id:t.timedReleaseId,status:"active",details:{id:t.timedReleaseId,type:"timed_release",openAt:new Date(e).toISOString(),closeAt:new Date(e+9e5).toISOString()}},upcoming:void 0})}):e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=Date.now(),n=new Date(e+(t.drawDelayMs??72e5)).toISOString();return o.ok({recentPast:void 0,active:{type:"draw",id:t.drawId,status:"active",details:{id:t.drawId,type:"draw",openAt:new Date(e).toISOString(),drawTime:n,entryDeadline:n}},upcoming:void 0})}):e.get(`/sequences/${t.sequenceId}/distributions`,()=>{const e=/* @__PURE__ */(new Date).toISOString();return n.waitlistState?.isEntered?o.ok({recentPast:void 0,active:{type:"queue",id:t.queueId,status:"active",details:{id:t.queueId,type:"queue",openAt:e,closeAt:new Date(Date.now()+18e5).toISOString(),metadata:{label:"Journey Queue (Window Open)"},estimatedWaitTime:300,queueLength:10}},upcoming:void 0}):o.ok({recentPast:void 0,active:void 0,upcoming:{type:"queue",id:t.queueId,startsAt:new Date(Date.now()+6e4).toISOString(),waitlistId:t.waitlistId}})})}function w(e,t){const{queueId:n,experienceId:s="experience_mock",name:a="Mock Queue",initialPosition:i=12,initialEstimatedWaitSeconds:u=300,autoExpireAfterGrant:r=!1,forceDenyOnEnter:d=!1}=t;let c=!1,_=!1,l=i,m=u,I=0;e.get(`/queues/${n}`,o.ok({id:n,experienceId:s,name:a,status:"open",capacity:500,currentSize:247,estimatedWaitTime:m,openAt:new Date(Date.now()-3e5).toISOString(),closeAt:new Date(Date.now()+36e5).toISOString()})),e.post(`/queues/${n}/enter`,e=>{const t=p(e);return t||(d?o.ok({status:"DENIED"}):(c=!0,_=!1,I=0,l=i,m=u,o.ok({position:l,estimatedWaitTimeInSeconds:m,status:"QUEUED"})))}),e.post(`/queues/${n}/leave`,()=>(c=!1,_=!1,I=0,o.ok({}))),e.get(`/queues/${n}/status`,()=>c?_?(I+=1,r&&I>1?(c=!1,_=!1,o.ok({status:"EXPIRED"})):o.ok({status:"GRANTED",admissionGrant:`admission_grant_${n}`,expiresAt:new Date(Date.now()+6e5).toISOString()})):(l=Math.max(1,l-1),m=Math.max(0,m-30),l<=1?(_=!0,I=1,o.ok({status:"GRANTED",admissionGrant:`admission_grant_${n}`,expiresAt:new Date(Date.now()+6e5).toISOString()})):o.ok({status:"QUEUED",position:l,estimatedWaitTimeInSeconds:m})):o.ok({status:"NOT_QUEUED"}))}function q(e,t){const{drawId:n,drawAtOffsetMs:s=72e5,forceDenyOnEnter:a=!1}=t;let i="NOT_ENTERED",u=0;e.get(`/draws/${n}`,()=>o.ok({id:n,openAt:new Date(Date.now()-6e4).toISOString(),closeAt:null,timeZone:"UTC",drawAt:new Date(Date.now()+s).toISOString(),capacity:null,continueSelectingUntilCompleted:null})),e.get(`/draws/${n}/status`,()=>"NOT_ENTERED"===i?o.ok({status:"NOT_ENTERED"}):(u+=1,u>=2?o.ok({status:"WON",wonAt:/* @__PURE__ */(new Date).toISOString(),admissionGrant:`admission_grant_${n}`}):o.ok({status:"ENTERED"}))),e.post(`/draws/${n}/enter`,e=>{const t=p(e);return t||(a?o.ok({status:"DENIED"}):(i="ENTERED",u=0,o.ok({status:"ENTERED"})))}),e.post(`/draws/${n}/leave`,()=>(i="NOT_ENTERED",u=0,o.ok({})))}function g(e,t){const{waitlistId:n,sequenceId:s,state:a,storageKey:i}=t;e.get(`/waitlists/${n}/status`,()=>o.ok({waitlistId:n,isEntered:a.isEntered,enteredAt:a.enteredAt??void 0})),e.post(`/waitlists/${n}/enter`,()=>(a.isEntered=!0,a.enteredAt=/* @__PURE__ */(new Date).toISOString(),d(i,a),o.ok({id:`waitlist_entry_${n}`,waitlistId:n,sequenceId:s,consumerId:"consumer_mock_demo",enteredAt:a.enteredAt})));const u=()=>(a.isEntered=!1,a.enteredAt=null,d(i,a),o.ok({}));e.delete(`/waitlists/${n}/leave`,u),e.post(`/waitlists/${n}/leave`,u)}function D(e,t){const{timedReleaseId:n,closeAt:s}=t;let a="NOT_ENTERED",i=null,u=null;e.get(`/timed-releases/${n}`,o.ok({id:n,openAt:new Date(Date.now()-6e4).toISOString(),closeAt:s,timeZone:"America/Los_Angeles",supportsGuest:!0})),e.get(`/timed-releases/${n}/status`,()=>"ENTERED"===a?o.ok({status:"ENTERED",enteredAt:i??/* @__PURE__ */(new Date).toISOString()}):"COMPLETED"===a?o.ok({status:"COMPLETED",completedAt:u??/* @__PURE__ */(new Date).toISOString()}):"LEFT"===a?o.ok({status:"LEFT",leftAt:/* @__PURE__ */(new Date).toISOString()}):o.ok({status:"NOT_ENTERED"})),e.post(`/timed-releases/${n}/enter`,async e=>{const t=await m(e),n="string"==typeof t?.variantId?t.variantId:void 0;return a="ENTERED",i=/* @__PURE__ */(new Date).toISOString(),o.ok({status:"ENTERED",enteredAt:i,selectedVariantId:n})}),e.post(`/timed-releases/${n}/leave`,()=>(a="LEFT",o.ok({}))),e.post(`/timed-releases/${n}/complete`,()=>(a="COMPLETED",u=/* @__PURE__ */(new Date).toISOString(),o.ok({success:!0,admissionGrant:`admission_grant_${n}`})))}function S(s,a){const{auctionId:i}=a,u=/* @__PURE__ */new Date,r=u.toISOString(),d=new Date(u.getTime()+6e5).toISOString();let c="100.00",_=null,l=12,I=!1,p=[{bidId:"bid_1",consumerId:"consumer_mock_demo",amount:"80.00",timestamp:r},{bidId:"bid_2",consumerId:"consumer_mock_demo",amount:"90.00",timestamp:r}];s.get(`/auctions/${i}`,o.ok({id:i,openAt:r,closeAt:d,settleAt:d,currencyCode:"USD",reservePrice:null,minBidIncrement:"10.00",autoExtendSeconds:null,timeZone:"UTC"})),s.get(`/auctions/${i}/highest-bid`,()=>o.ok({amount:c})),s.get(`/auctions/${i}/status`,()=>{const e=null===_?"NOT_BID":n(_,c)?"WINNING":I?"OUTBID":"NOT_BID";return o.ok({status:e,lastBidAmount:_??void 0,bidCount:l,auctionEndTime:d})}),s.post(`/auctions/${i}/enter`,()=>(I=!0,o.ok({}))),s.post(`/auctions/${i}/leave`,()=>(I=!1,_=null,o.ok({}))),s.post(`/auctions/${i}/bid`,async s=>{const a=await m(s),i=a?.amount,u="string"==typeof i?i:"";return e(u)?(_=u,l+=1,t(u,c)&&(c=u),p=[...p,{bidId:`bid_${p.length+1}`,consumerId:"consumer_mock_demo",amount:u,timestamp:/* @__PURE__ */(new Date).toISOString()}],o.ok({status:n(u,c)?"WINNING":"OUTBID",lastBidAmount:u,bidCount:l,winningBidAmount:c,winningBidTime:/* @__PURE__ */(new Date).toISOString(),auctionEndTime:d,paymentToken:null})):o.badRequest("Invalid bid amount")}),s.get(`/auctions/${i}/bids/history`,()=>o.ok(p.map(e=>({...e,isHighest:e.amount===c}))))}export{a as DEFAULT_HARNESS_MOCK_API_BASE_URL,i as DEFAULT_HARNESS_MOCK_BEACON_BASE_URL,u as DEFAULT_TEST_OTP_CODE,c as HARNESS_SCENARIOS,y as installHarnessMockServer,l as normalizeHarnessScenario};
package/dist/version.d.ts CHANGED
@@ -2,4 +2,4 @@
2
2
  * SDK version
3
3
  * This is automatically updated during the build process
4
4
  */
5
- export declare const version = "0.1.0";
5
+ export declare const version = "0.2.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- const o="0.1.0";export{o as version};
1
+ const o="0.2.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.1.0",
3
+ "version": "0.2.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",
@@ -66,6 +66,10 @@
66
66
  "types": "./dist/theme.d.ts",
67
67
  "import": "./dist/theme.js"
68
68
  },
69
+ "./storefront": {
70
+ "types": "./dist/storefront.d.ts",
71
+ "import": "./dist/storefront.js"
72
+ },
69
73
  "./events": {
70
74
  "types": "./dist/events.d.ts",
71
75
  "import": "./dist/events.js"
@@ -90,6 +94,10 @@
90
94
  "types": "./dist/handoff/index.d.ts",
91
95
  "import": "./dist/handoff/index.js"
92
96
  },
97
+ "./harness": {
98
+ "types": "./dist/harness.d.ts",
99
+ "import": "./dist/harness.js"
100
+ },
93
101
  "./draws": {
94
102
  "types": "./dist/draws/public.d.ts",
95
103
  "import": "./dist/draws/public.js"
@@ -114,7 +122,7 @@
114
122
  "uuid": "^14.0.0",
115
123
  "wretch": "^2.11.0",
116
124
  "zustand": "^5.0.6",
117
- "@fanfare-io/fanfare-sdk-contracts": "0.1.0"
125
+ "@fanfare-io/fanfare-sdk-contracts": "0.2.0"
118
126
  },
119
127
  "peerDependencies": {
120
128
  "valibot": "^1.1.0",
@@ -157,7 +165,7 @@
157
165
  "vite-plugin-dts": "^4.5.4",
158
166
  "vite-tsconfig-paths": "^5.1.4",
159
167
  "vitest": "^3.2.4",
160
- "@fanfare-io/shared-models": "0.1.0"
168
+ "@fanfare-io/shared-models": "0.2.0"
161
169
  },
162
170
  "sideEffects": false,
163
171
  "keywords": [
@@ -192,7 +200,7 @@
192
200
  "prebuild-storybook": "pnpm typecheck",
193
201
  "size": "size-limit",
194
202
  "storybook": "storybook dev -p 6007 --no-open",
195
- "build:test-deps": "pnpm --filter @fanfare-io/fanfare-sdk-contracts run build:incremental",
203
+ "build:test-deps": "pnpm --filter @fanfare-io/fanfare-sdk-contracts run build:incremental && pnpm --filter @fanfare-io/fanfare-sdk-shopify run build:deps",
196
204
  "test": "pnpm build:test-deps && vitest run",
197
205
  "test:debug": "NODE_OPTIONS='--expose-gc' vitest run --reporter=verbose",
198
206
  "test:ci": "pnpm build:test-deps && vitest run --reporter=verbose --coverage",