@tickean/checkout-js 0.1.0 → 0.2.11

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/README.md CHANGED
@@ -2,4 +2,13 @@
2
2
 
3
3
  Framework-agnostic TypeScript client for Tickean Headless Checkout.
4
4
 
5
- See repository root README and `docs/readme/` for guides.
5
+ ## APIs
6
+
7
+ - `createTickean(options)` — low-level client (unchanged public method signatures)
8
+ - `createCheckoutController(options)` — state machine with cart, quote debounce, OTP, purchase+payment, persistence, telemetry
9
+
10
+ ## Phases
11
+
12
+ `initializing` → `browsing` → `quoting` → `verifying_buyer` → `ready_to_purchase` → `purchasing` → `requires_action` | `processing` → `completed` | `failed` | `expired`
13
+
14
+ See repository root README for monorepo build/test commands.
package/dist/index.d.mts CHANGED
@@ -7,7 +7,8 @@ declare class TickeanError extends Error {
7
7
  readonly code: string;
8
8
  readonly details?: Record<string, unknown>;
9
9
  readonly status?: number;
10
- constructor(payload: TickeanErrorPayload, status?: number);
10
+ readonly requestId?: string;
11
+ constructor(payload: TickeanErrorPayload, status?: number, requestId?: string);
11
12
  }
12
13
  type CreateTickeanOptions = {
13
14
  publishableKey: string;
@@ -16,12 +17,72 @@ type CreateTickeanOptions = {
16
17
  demo?: boolean;
17
18
  fetchImpl?: typeof fetch;
18
19
  };
20
+ type CheckoutPhase = "initializing" | "browsing" | "quoting" | "verifying_buyer" | "ready_to_purchase" | "purchasing" | "requires_action" | "processing" | "completed" | "failed" | "expired";
21
+ type NextAction = {
22
+ type: "display_instructions";
23
+ paymentInstructions: unknown;
24
+ } | {
25
+ type: "redirect";
26
+ url: string;
27
+ } | {
28
+ type: "stripe_elements";
29
+ clientSecret: string;
30
+ publishableKey?: string;
31
+ paymentIntentId?: string;
32
+ } | {
33
+ type: "airwallex_dropin";
34
+ intentId: string;
35
+ clientSecret: string;
36
+ currency?: string;
37
+ env?: string;
38
+ countryCode?: string;
39
+ } | {
40
+ type: "dlocal_fields";
41
+ merchantCheckoutToken: string;
42
+ smartFieldsApiKey?: string;
43
+ paymentId?: string;
44
+ sdkUrl?: string;
45
+ } | {
46
+ type: "fintoc_widget";
47
+ sessionToken?: string;
48
+ widgetToken?: string;
49
+ publicKey?: string;
50
+ holderType?: string;
51
+ product?: string;
52
+ } | {
53
+ type: "none";
54
+ };
19
55
  type CheckoutSession = {
20
56
  sessionId: string;
21
57
  sessionToken: string;
22
58
  expiresAt: string;
23
59
  event: PublicEvent;
24
60
  capabilities: Record<string, boolean>;
61
+ phase?: CheckoutPhase | string;
62
+ status?: string;
63
+ otpVerified?: boolean;
64
+ buyerId?: string | null;
65
+ purchaseId?: string | null;
66
+ shoppingCartReference?: string | null;
67
+ nextAction?: NextAction;
68
+ returnUrl?: string | null;
69
+ };
70
+ type PromotionNxM = {
71
+ enabled?: boolean;
72
+ buyQty?: number;
73
+ payQty?: number;
74
+ label?: string;
75
+ startsAt?: string;
76
+ endsAt?: string;
77
+ };
78
+ type QuantityDiscount = {
79
+ enabled?: boolean;
80
+ type?: "SECOND_UNIT_PERCENT" | "NTH_UNIT_PERCENT" | string;
81
+ targetUnit?: number;
82
+ percentOff?: number;
83
+ label?: string;
84
+ startsAt?: string;
85
+ endsAt?: string;
25
86
  };
26
87
  type PublicShowOption = {
27
88
  id: string;
@@ -30,15 +91,20 @@ type PublicShowOption = {
30
91
  price: number;
31
92
  currency?: string;
32
93
  stock?: number;
94
+ sold?: number;
95
+ reserved?: number;
96
+ availableStock?: number;
33
97
  maxPerPurchase?: number;
34
98
  optionType?: string;
35
99
  accessScope?: string;
36
100
  coveredShowIds?: string[];
37
101
  passIssuanceMode?: "PER_DAY" | "SINGLE_PASS";
38
102
  catalogVisibility?: "PUBLIC" | "PROMO_GATED";
39
- promotionNxM?: unknown;
40
- quantityDiscount?: unknown;
103
+ promotionNxM?: PromotionNxM | null;
104
+ quantityDiscount?: QuantityDiscount | null;
41
105
  status?: string;
106
+ /** Present on options returned via promo unlock. */
107
+ showId?: string;
42
108
  };
43
109
  type PublicShow = {
44
110
  id: string;
@@ -47,6 +113,32 @@ type PublicShow = {
47
113
  endDate?: string;
48
114
  showOptions: PublicShowOption[];
49
115
  };
116
+ type RegistrationQuestion = {
117
+ id: string;
118
+ type?: string;
119
+ label?: string;
120
+ required?: boolean;
121
+ options?: string[];
122
+ };
123
+ type RegistrationSettings = {
124
+ maxAttendeesPerPurchase?: number;
125
+ requireAttendeeEmail?: boolean;
126
+ requireAttendeePhone?: boolean;
127
+ terms?: {
128
+ required?: boolean;
129
+ label?: string | null;
130
+ pdfUrl?: string | null;
131
+ } | null;
132
+ questions?: RegistrationQuestion[];
133
+ };
134
+ type PurchaseAttendee = {
135
+ showOptionId: string;
136
+ firstName?: string;
137
+ lastName?: string;
138
+ email?: string;
139
+ phone?: string;
140
+ termsAccepted?: boolean;
141
+ };
50
142
  type PublicEvent = {
51
143
  id: string;
52
144
  slug: string;
@@ -55,6 +147,9 @@ type PublicEvent = {
55
147
  images?: unknown[];
56
148
  location?: unknown;
57
149
  availablePaymentMethods?: string[];
150
+ hasPromoGatedShowOptions?: boolean;
151
+ collectAttendeeData?: boolean;
152
+ registrationSettings?: RegistrationSettings | null;
58
153
  organization?: {
59
154
  id?: string;
60
155
  slug?: string;
@@ -72,6 +167,7 @@ type QuoteResult = {
72
167
  totalPrice: number;
73
168
  pricingBreakdown?: unknown;
74
169
  discountCode?: unknown;
170
+ message?: string;
75
171
  unlockedShowOptionIds?: string[];
76
172
  unlockedShowOptions?: PublicShowOption[];
77
173
  };
@@ -105,32 +201,94 @@ type PaymentResult = {
105
201
  fintocWidget?: unknown;
106
202
  dlocalGo?: unknown;
107
203
  airwallex?: unknown;
204
+ mercadoPago?: unknown;
205
+ nextAction?: NextAction;
206
+ requiresAction?: boolean;
108
207
  };
109
208
  type PaymentStatusResult = {
110
209
  status: string;
111
210
  purchase?: PurchaseResult["purchase"] | null;
211
+ payment?: PaymentResult | null;
212
+ nextAction?: NextAction;
213
+ requiresAction?: boolean;
214
+ phase?: CheckoutPhase | string;
215
+ };
216
+ type TelemetryEvent = {
217
+ name: string;
218
+ timestamp: number;
219
+ properties?: Record<string, unknown>;
112
220
  };
221
+ interface TelemetryAdapter {
222
+ track(event: TelemetryEvent): void;
223
+ }
224
+ type PersistedCheckoutState = {
225
+ sessionToken?: string;
226
+ eventSlug?: string;
227
+ cart?: CartItem[];
228
+ discountCode?: string | null;
229
+ phase?: CheckoutPhase;
230
+ /** Non-PII buyer flags only */
231
+ buyerVerified?: boolean;
232
+ purchaseId?: string | null;
233
+ };
234
+ interface PersistenceAdapter {
235
+ get(key: string): PersistedCheckoutState | null;
236
+ set(key: string, value: PersistedCheckoutState): void;
237
+ remove(key: string): void;
238
+ }
113
239
  interface CheckoutTransport {
114
240
  request<T>(path: string, init: {
115
241
  method?: string;
116
242
  body?: unknown;
117
243
  sessionToken?: string | null;
244
+ idempotencyKey?: string;
118
245
  }): Promise<T>;
119
246
  }
120
247
 
121
248
  type TickeanClient = ReturnType<typeof createTickean>;
122
249
  declare function createTickean(options: CreateTickeanOptions): {
123
- readonly session: CheckoutSession | null;
250
+ session: CheckoutSession | null;
124
251
  createSession(params: {
125
252
  eventSlug: string;
126
253
  returnUrl?: string;
127
254
  }): Promise<CheckoutSession>;
255
+ exchangeRecovery(params: {
256
+ code: string;
257
+ }): Promise<{
258
+ sessionId: string;
259
+ sessionToken: string;
260
+ expiresAt: string;
261
+ suggestedStep?: string | number;
262
+ event: PublicEvent;
263
+ capabilities?: Record<string, boolean>;
264
+ cart: CartItem[];
265
+ discountCode?: string | null;
266
+ buyer?: Buyer | null;
267
+ buyerVerified?: boolean;
268
+ purchase?: PurchaseResult["purchase"] | null;
269
+ payment?: PaymentResult | null;
270
+ nextAction?: NextAction;
271
+ shoppingCartReference?: string | null;
272
+ phase?: string;
273
+ }>;
274
+ getSession(): Promise<CheckoutSession>;
128
275
  getCatalog(): Promise<PublicEvent>;
129
276
  quote(params: {
130
277
  items: CartItem[];
131
278
  discountCode?: string;
132
279
  showId?: string;
133
280
  }): Promise<QuoteResult>;
281
+ lookupBuyer(params: {
282
+ phone: string;
283
+ }): Promise<{
284
+ exists: boolean;
285
+ buyer?: {
286
+ id: string;
287
+ phone: string;
288
+ name?: string;
289
+ email?: string;
290
+ };
291
+ }>;
134
292
  sendOtp(params: {
135
293
  phone: string;
136
294
  channel?: string;
@@ -150,12 +308,20 @@ declare function createTickean(options: CreateTickeanOptions): {
150
308
  expectedTotal?: number;
151
309
  shoppingCartReference?: string;
152
310
  idempotencyKey?: string;
311
+ attendees?: PurchaseAttendee[];
153
312
  }): Promise<PurchaseResult>;
154
313
  createPayment(params: {
155
314
  orderId: string;
156
315
  paymentMethod: string;
157
316
  currency: string;
158
317
  amount: number;
318
+ idempotencyKey?: string;
319
+ }): Promise<PaymentResult>;
320
+ confirmPayment(params?: {
321
+ paymentId?: string;
322
+ confirmationToken?: string;
323
+ providerPayload?: string;
324
+ idempotencyKey?: string;
159
325
  }): Promise<PaymentResult>;
160
326
  getPaymentStatus(): Promise<PaymentStatusResult>;
161
327
  watchPayment(options?: {
@@ -165,4 +331,287 @@ declare function createTickean(options: CreateTickeanOptions): {
165
331
  }): Promise<PaymentStatusResult>;
166
332
  };
167
333
 
168
- export { type Buyer, type CartItem, type CheckoutSession, type CheckoutTransport, type CreateTickeanOptions, type PaymentResult, type PaymentStatusResult, type PublicEvent, type PublicShow, type PublicShowOption, type PurchaseResult, type QuoteResult, type TickeanClient, TickeanError, type TickeanErrorPayload, createTickean };
334
+ type CheckoutState = {
335
+ phase: CheckoutPhase;
336
+ session: CheckoutSession | null;
337
+ event: PublicEvent | null;
338
+ cart: CartItem[];
339
+ discountCode: string | null;
340
+ quote: QuoteResult | null;
341
+ isQuoting: boolean;
342
+ buyer: Buyer | null;
343
+ buyerVerified: boolean;
344
+ otpSent: boolean;
345
+ purchase: PurchaseResult["purchase"] | null;
346
+ payment: PaymentResult | null;
347
+ nextAction: NextAction;
348
+ error: TickeanError | null;
349
+ loading: boolean;
350
+ };
351
+ type CheckoutAction = {
352
+ type: "INIT_START";
353
+ } | {
354
+ type: "INIT_SUCCESS";
355
+ session: CheckoutSession;
356
+ event: PublicEvent;
357
+ } | {
358
+ type: "INIT_FAILURE";
359
+ error: TickeanError;
360
+ } | {
361
+ type: "SET_CART";
362
+ cart: CartItem[];
363
+ } | {
364
+ type: "SET_DISCOUNT";
365
+ discountCode: string | null;
366
+ } | {
367
+ type: "QUOTE_START";
368
+ } | {
369
+ type: "QUOTE_SUCCESS";
370
+ quote: QuoteResult;
371
+ } | {
372
+ type: "QUOTE_FAILURE";
373
+ error: TickeanError;
374
+ } | {
375
+ type: "OTP_SENT";
376
+ } | {
377
+ type: "OTP_VERIFIED";
378
+ buyer: Buyer;
379
+ } | {
380
+ type: "SET_EVENT";
381
+ event: PublicEvent;
382
+ } | {
383
+ type: "MERGE_UNLOCKED_OPTIONS";
384
+ options: PublicShowOption[];
385
+ } | {
386
+ type: "PURCHASE_START";
387
+ } | {
388
+ type: "PURCHASE_SUCCESS";
389
+ purchase: PurchaseResult["purchase"];
390
+ payment: PaymentResult;
391
+ nextAction: NextAction;
392
+ } | {
393
+ type: "PURCHASE_FAILURE";
394
+ error: TickeanError;
395
+ } | {
396
+ type: "SET_NEXT_ACTION";
397
+ nextAction: NextAction;
398
+ payment?: PaymentResult | null;
399
+ } | {
400
+ type: "RESET_PAYMENT_FLOW";
401
+ } | {
402
+ type: "PROCESSING";
403
+ } | {
404
+ type: "COMPLETED";
405
+ purchase?: PurchaseResult["purchase"] | null;
406
+ } | {
407
+ type: "FAILED";
408
+ error: TickeanError;
409
+ } | {
410
+ type: "EXPIRED";
411
+ } | {
412
+ type: "CLEAR_ERROR";
413
+ } | {
414
+ type: "REHYDRATE";
415
+ partial: Partial<CheckoutState>;
416
+ };
417
+ declare function createInitialState(partial?: Partial<CheckoutState>): CheckoutState;
418
+ declare function checkoutReducer(state: CheckoutState, action: CheckoutAction): CheckoutState;
419
+
420
+ type CreateCheckoutControllerOptions = CreateTickeanOptions & {
421
+ eventSlug: string;
422
+ returnUrl?: string;
423
+ /** Abandonment recovery code from `?resume=` deep link. */
424
+ resumeCode?: string;
425
+ quoteDebounceMs?: number;
426
+ persistence?: PersistenceAdapter | false;
427
+ persistenceKey?: string;
428
+ telemetry?: TelemetryAdapter;
429
+ };
430
+ declare function createCheckoutController(options: CreateCheckoutControllerOptions): {
431
+ client: {
432
+ session: CheckoutSession | null;
433
+ createSession(params: {
434
+ eventSlug: string;
435
+ returnUrl?: string;
436
+ }): Promise<CheckoutSession>;
437
+ exchangeRecovery(params: {
438
+ code: string;
439
+ }): Promise<{
440
+ sessionId: string;
441
+ sessionToken: string;
442
+ expiresAt: string;
443
+ suggestedStep?: string | number;
444
+ event: PublicEvent;
445
+ capabilities?: Record<string, boolean>;
446
+ cart: CartItem[];
447
+ discountCode?: string | null;
448
+ buyer?: Buyer | null;
449
+ buyerVerified?: boolean;
450
+ purchase?: PurchaseResult["purchase"] | null;
451
+ payment?: PaymentResult | null;
452
+ nextAction?: NextAction;
453
+ shoppingCartReference?: string | null;
454
+ phase?: string;
455
+ }>;
456
+ getSession(): Promise<CheckoutSession>;
457
+ getCatalog(): Promise<PublicEvent>;
458
+ quote(params: {
459
+ items: CartItem[];
460
+ discountCode?: string;
461
+ showId?: string;
462
+ }): Promise<QuoteResult>;
463
+ lookupBuyer(params: {
464
+ phone: string;
465
+ }): Promise<{
466
+ exists: boolean;
467
+ buyer?: {
468
+ id: string;
469
+ phone: string;
470
+ name?: string;
471
+ email?: string;
472
+ };
473
+ }>;
474
+ sendOtp(params: {
475
+ phone: string;
476
+ channel?: string;
477
+ }): Promise<unknown>;
478
+ verifyOtp(params: {
479
+ phone: string;
480
+ code: string;
481
+ name?: string;
482
+ email?: string;
483
+ }): Promise<unknown>;
484
+ createPurchase(params: {
485
+ items: CartItem[];
486
+ paymentMethod: string;
487
+ currency: string;
488
+ showId?: string;
489
+ discountCode?: string;
490
+ expectedTotal?: number;
491
+ shoppingCartReference?: string;
492
+ idempotencyKey?: string;
493
+ attendees?: PurchaseAttendee[];
494
+ }): Promise<PurchaseResult>;
495
+ createPayment(params: {
496
+ orderId: string;
497
+ paymentMethod: string;
498
+ currency: string;
499
+ amount: number;
500
+ idempotencyKey?: string;
501
+ }): Promise<PaymentResult>;
502
+ confirmPayment(params?: {
503
+ paymentId?: string;
504
+ confirmationToken?: string;
505
+ providerPayload?: string;
506
+ idempotencyKey?: string;
507
+ }): Promise<PaymentResult>;
508
+ getPaymentStatus(): Promise<PaymentStatusResult>;
509
+ watchPayment(options?: {
510
+ intervalMs?: number;
511
+ timeoutMs?: number;
512
+ signal?: AbortSignal;
513
+ }): Promise<PaymentStatusResult>;
514
+ };
515
+ ready: Promise<void>;
516
+ getSnapshot: () => CheckoutState;
517
+ subscribe: (listener: (snapshot: CheckoutState) => void) => () => void;
518
+ setCartItem: (showOptionId: string, amount: number) => void;
519
+ setCart: (cart: CartItem[]) => void;
520
+ applyDiscountCode: (code: string) => Promise<QuoteResult>;
521
+ lookupBuyer: (phone: string) => Promise<{
522
+ exists: boolean;
523
+ buyer?: {
524
+ id: string;
525
+ phone: string;
526
+ name?: string;
527
+ email?: string;
528
+ };
529
+ }>;
530
+ sendOtp: (phone: string, channel?: string) => Promise<void>;
531
+ verifyOtp: (params: {
532
+ phone: string;
533
+ code: string;
534
+ name?: string;
535
+ email?: string;
536
+ }) => Promise<void>;
537
+ purchaseAndPay: (params: {
538
+ paymentMethod: string;
539
+ currency: string;
540
+ discountCode?: string;
541
+ showId?: string;
542
+ idempotencyKey?: string;
543
+ attendees?: PurchaseAttendee[];
544
+ }) => Promise<{
545
+ purchaseId: string;
546
+ payment: PaymentResult;
547
+ nextAction: NextAction;
548
+ }>;
549
+ changePaymentMethod: () => void;
550
+ confirmPayment: (params?: {
551
+ paymentId?: string;
552
+ confirmationToken?: string;
553
+ providerPayload?: string;
554
+ idempotencyKey?: string;
555
+ }) => Promise<PaymentResult>;
556
+ watchPayment: (watchOptions?: {
557
+ intervalMs?: number;
558
+ timeoutMs?: number;
559
+ signal?: AbortSignal;
560
+ }) => Promise<PaymentStatusResult>;
561
+ refreshCatalog: () => Promise<PublicEvent>;
562
+ dispose: () => void;
563
+ /** @internal test helper */
564
+ _dispatch: (action: CheckoutAction) => void;
565
+ };
566
+ type CheckoutController = ReturnType<typeof createCheckoutController>;
567
+
568
+ declare function createMemoryPersistence(): PersistenceAdapter;
569
+ /** sessionStorage adapter — stores only non-PII checkout resume data. */
570
+ declare function createSessionStoragePersistence(storage?: Storage): PersistenceAdapter;
571
+
572
+ declare function createNoopTelemetry(): TelemetryAdapter;
573
+ type TelemetryListener = (event: TelemetryEvent) => void;
574
+ declare function createEventEmitterTelemetry(listeners?: TelemetryListener[]): TelemetryAdapter & {
575
+ subscribe(listener: TelemetryListener): () => void;
576
+ };
577
+
578
+ type PaymentSocketSnapshot = {
579
+ purchaseId?: string;
580
+ orderId?: string;
581
+ paymentId?: string;
582
+ status?: string;
583
+ amount?: number;
584
+ currency?: string;
585
+ };
586
+ type PaymentSocketWatchHandle = {
587
+ promise: Promise<PaymentSocketSnapshot>;
588
+ dispose: () => void;
589
+ get connected(): boolean;
590
+ };
591
+ /**
592
+ * Join the legacy cart payment room (same as ecommerce) and resolve when
593
+ * payment:confirmed arrives. HTTP polling remains the fallback.
594
+ */
595
+ declare function watchPaymentSocket(params: {
596
+ apiBaseUrl: string;
597
+ shoppingCartReference: string;
598
+ purchaseId?: string;
599
+ signal?: AbortSignal;
600
+ timeoutMs?: number;
601
+ }): PaymentSocketWatchHandle;
602
+
603
+ /**
604
+ * Navigate the top-level browsing context (breaks out of iframes).
605
+ * Used for Mercado Pago hosted checkout so payment is not trapped in embeds.
606
+ */
607
+ declare function navigateTopLevel(url: string): void;
608
+ declare function resolveRedirectUrl(params: {
609
+ nextAction?: {
610
+ type: string;
611
+ url?: string;
612
+ } | null;
613
+ redirectUrl?: string | null;
614
+ initPoint?: string | null;
615
+ }): string | null;
616
+
617
+ export { type Buyer, type CartItem, type CheckoutAction, type CheckoutController, type CheckoutPhase, type CheckoutSession, type CheckoutState, type CheckoutTransport, type CreateCheckoutControllerOptions, type CreateTickeanOptions, type NextAction, type PaymentResult, type PaymentSocketSnapshot, type PaymentSocketWatchHandle, type PaymentStatusResult, type PersistedCheckoutState, type PersistenceAdapter, type PromotionNxM, type PublicEvent, type PublicShow, type PublicShowOption, type PurchaseAttendee, type PurchaseResult, type QuantityDiscount, type QuoteResult, type RegistrationQuestion, type RegistrationSettings, type TelemetryAdapter, type TelemetryEvent, type TelemetryListener, type TickeanClient, TickeanError, type TickeanErrorPayload, checkoutReducer, createCheckoutController, createEventEmitterTelemetry, createInitialState, createMemoryPersistence, createNoopTelemetry, createSessionStoragePersistence, createTickean, navigateTopLevel, resolveRedirectUrl, watchPaymentSocket };