@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.
- package/dist/harness.d.ts +21 -0
- package/dist/harness.js +1 -0
- package/dist/storefront.d.ts +96 -0
- package/dist/storefront.js +1 -0
- package/dist/test-utils/harness-scenarios.d.ts +7 -15
- package/dist/test-utils/harness-scenarios.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +12 -4
|
@@ -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';
|
package/dist/harness.js
ADDED
|
@@ -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
|
-
|
|
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
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const o="0.
|
|
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.
|
|
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.
|
|
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.
|
|
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",
|