@bookitive/js 0.1.3 → 0.1.4

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/index.d.ts CHANGED
@@ -1,29 +1,59 @@
1
- /** @example "VALIDATION_FAILED" */
2
- declare enum ResponseType {
1
+ /**
2
+ * Type is the stable, machine-readable error code.
3
+ * @example "CONFLICT"
4
+ */
5
+ declare enum DtoErrorCode {
3
6
  ErrInvalidPayload = "INVALID_PAYLOAD",
4
7
  ErrValidationFailed = "VALIDATION_FAILED",
5
8
  ErrNotFound = "NOT_FOUND",
6
- ErrNotImplemented = "NOT_IMPLEMENTED",
7
9
  ErrConflict = "CONFLICT",
8
- ErrInternal = "INTERNAL_ERROR",
9
- ErrUnauthorized = "UNAUTHORIZED",
10
10
  ErrForbidden = "FORBIDDEN",
11
- ErrMissingOrganizationID = "MISSING_ORGANIZATION_ID",
12
- ErrMissingUserID = "MISSING_USER_ID"
11
+ ErrInternal = "INTERNAL_ERROR"
12
+ }
13
+ interface DtoAPIError {
14
+ /** Data carries optional structured context for the error. */
15
+ data?: any;
16
+ /** Fields maps a request field to a validation message, when applicable. */
17
+ fields?: Record<string, string>;
18
+ /**
19
+ * Msg is a human-readable description of what went wrong.
20
+ * @example "seat is no longer available"
21
+ */
22
+ msg?: string;
23
+ /**
24
+ * Timestamp is when the error was produced (RFC 3339).
25
+ * @example "2026-06-20T18:00:00Z"
26
+ */
27
+ timestamp?: string;
28
+ /**
29
+ * TraceID identifies this request in our logs; include it in support asks.
30
+ * @example "01JABCDoftraceZ"
31
+ */
32
+ traceId?: string;
33
+ /** Type is the stable, machine-readable error code. */
34
+ type?: DtoErrorCode;
13
35
  }
14
36
  interface DtoPublicAvailability {
37
+ /** GARemaining maps a standing area id to its remaining capacity. */
15
38
  gaRemaining?: Record<string, number>;
16
39
  /**
17
40
  * ReservedSeats marks which unavailable seats are merely reserved and may
18
41
  * free up again — present only when the event shares reserved status.
19
42
  * @uniqueItems false
43
+ * @example ["1810000000000000502"]
20
44
  */
21
45
  reservedSeats?: string[];
46
+ /** TicketTypeRemaining maps a ticket type id to its remaining capacity. */
22
47
  ticketTypeRemaining?: Record<string, number>;
23
- /** @uniqueItems false */
48
+ /**
49
+ * UnavailableSeats lists the ids of seats that cannot currently be bought.
50
+ * @uniqueItems false
51
+ * @example ["1810000000000000501","1810000000000000502"]
52
+ */
24
53
  unavailableSeats?: string[];
25
54
  }
26
55
  interface DtoPublicEvent {
56
+ /** Event is the event's public identity: name, times, venue, currency. */
27
57
  event?: DtoPublicEventInfo;
28
58
  /**
29
59
  * Floors lets a host page render its floor tabs without loading the full
@@ -31,169 +61,528 @@ interface DtoPublicEvent {
31
61
  * @uniqueItems false
32
62
  */
33
63
  floors?: DtoPublicFloorInfo[];
64
+ /** Org is the organizer's public branding (name, logo, accent colour). */
34
65
  org?: DtoPublicOrg;
35
- /** @uniqueItems false */
66
+ /**
67
+ * TicketTypes are the sellable ticket categories with prices and limits.
68
+ * @uniqueItems false
69
+ */
36
70
  ticketTypes?: DtoPublicTicketType[];
37
71
  }
72
+ /** Event is the event's public identity: name, times, venue, currency. */
38
73
  interface DtoPublicEventInfo {
74
+ /**
75
+ * Currency is the ISO 4217 code all prices are quoted in.
76
+ * @example "CZK"
77
+ */
39
78
  currency?: string;
79
+ /**
80
+ * EndTime is when the event ends (RFC 3339), when known.
81
+ * @example "2026-06-20T23:00:00Z"
82
+ */
40
83
  endTime?: string;
84
+ /**
85
+ * HoldTTLSeconds is how long a checkout holds selected seats before expiry.
86
+ * @example 900
87
+ */
41
88
  holdTtlSeconds?: number;
89
+ /**
90
+ * LocationName is the venue's display name, when set.
91
+ * @example "Výstaviště Praha"
92
+ */
42
93
  locationName?: string;
94
+ /**
95
+ * Name is the event's public display name.
96
+ * @example "Rockfest 2026"
97
+ */
43
98
  name?: string;
99
+ /**
100
+ * Slug is the event's URL identifier (the {eventSlug} path parameter).
101
+ * @example "rockfest-2026"
102
+ */
44
103
  slug?: string;
104
+ /**
105
+ * StartTime is when doors/the event begins (RFC 3339).
106
+ * @example "2026-06-20T18:00:00Z"
107
+ */
45
108
  startTime?: string;
46
109
  }
47
110
  interface DtoPublicFloor {
48
- /** @uniqueItems false */
111
+ /**
112
+ * Cons are short caveats for this floor, shown alongside the pros.
113
+ * @uniqueItems false
114
+ * @example ["Standing only"]
115
+ */
49
116
  cons?: string[];
117
+ /**
118
+ * Description is optional customer-facing copy shown on the floor's tab.
119
+ * @example "Standing area in front of the main stage"
120
+ */
50
121
  description?: string;
122
+ /**
123
+ * ID is the floor's stable id; it matches PublicFloorInfo.id.
124
+ * @example "1810000000000000101"
125
+ */
51
126
  id?: string;
127
+ /**
128
+ * Mode is "single" (one open space) or "sections" (subdivided blocks).
129
+ * @example "sections"
130
+ */
52
131
  mode?: 'single' | 'sections';
132
+ /**
133
+ * Name is the floor's display label.
134
+ * @example "Ground floor"
135
+ */
53
136
  name?: string;
137
+ /**
138
+ * Position is the 1-based tab order among the event's floors.
139
+ * @example 1
140
+ */
54
141
  position?: number;
55
- /** @uniqueItems false */
142
+ /**
143
+ * Pros are short selling points for this floor, shown as a checklist.
144
+ * @uniqueItems false
145
+ * @example ["Closest to the stage","Great atmosphere"]
146
+ */
56
147
  pros?: string[];
57
- /** @uniqueItems false */
148
+ /**
149
+ * Sections are the floor's blocks; a single-mode floor has exactly one.
150
+ * @uniqueItems false
151
+ */
58
152
  sections?: DtoPublicSection[];
59
153
  }
60
154
  interface DtoPublicFloorInfo {
61
- /** @uniqueItems false */
155
+ /**
156
+ * Cons are short caveats for this floor, shown alongside the pros.
157
+ * @uniqueItems false
158
+ * @example ["Standing only"]
159
+ */
62
160
  cons?: string[];
161
+ /**
162
+ * Description is optional customer-facing copy shown on the floor's tab.
163
+ * @example "Standing area in front of the main stage"
164
+ */
63
165
  description?: string;
166
+ /**
167
+ * ID is the floor's stable id; it matches a floor in the seating endpoint.
168
+ * @example "1810000000000000101"
169
+ */
64
170
  id?: string;
171
+ /**
172
+ * Mode is "single" (one open space) or "sections" (subdivided blocks).
173
+ * @example "sections"
174
+ */
65
175
  mode?: 'single' | 'sections';
176
+ /**
177
+ * Name is the floor's display label.
178
+ * @example "Ground floor"
179
+ */
66
180
  name?: string;
181
+ /**
182
+ * Position is the 1-based tab order among the event's floors.
183
+ * @example 1
184
+ */
67
185
  position?: number;
68
- /** @uniqueItems false */
186
+ /**
187
+ * Pros are short selling points for this floor, shown as a checklist.
188
+ * @uniqueItems false
189
+ * @example ["Closest to the stage","Great atmosphere"]
190
+ */
69
191
  pros?: string[];
70
192
  }
71
193
  interface DtoPublicGAArea {
194
+ /**
195
+ * Capacity is the total number of standing tickets this area can sell.
196
+ * @example 500
197
+ */
72
198
  capacity?: number;
199
+ /**
200
+ * H is the area's height on the floor canvas.
201
+ * @example 200
202
+ */
73
203
  h?: number;
204
+ /**
205
+ * ID is the standing area's stable id, referenced by availability/orders.
206
+ * @example "1810000000000000601"
207
+ */
74
208
  id?: string;
209
+ /**
210
+ * Label is the standing area's display name.
211
+ * @example "Pit"
212
+ */
75
213
  label?: string;
214
+ /**
215
+ * Rotation is the area's rotation in degrees.
216
+ * @example 0
217
+ */
76
218
  rotation?: number;
219
+ /**
220
+ * TicketTypeID is the standing ticket type mapped to this area, when priced.
221
+ * @example "1810000000000000201"
222
+ */
77
223
  ticketTypeId?: string;
224
+ /**
225
+ * W is the area's width on the floor canvas.
226
+ * @example 600
227
+ */
78
228
  w?: number;
229
+ /**
230
+ * X is the area's left offset on the floor canvas.
231
+ * @example 100
232
+ */
79
233
  x?: number;
234
+ /**
235
+ * Y is the area's top offset on the floor canvas.
236
+ * @example 400
237
+ */
80
238
  y?: number;
81
239
  }
82
240
  interface DtoPublicOrder {
241
+ /**
242
+ * Currency is the ISO 4217 code the total is quoted in.
243
+ * @example "CZK"
244
+ */
83
245
  currency?: string;
246
+ /**
247
+ * ExpiresAt is when the held seats and this order expire (RFC 3339).
248
+ * @example "2026-06-20T18:15:00Z"
249
+ */
84
250
  expiresAt?: string;
251
+ /** Payment carries the bank-transfer instructions for pending orders. */
85
252
  payment?: DtoPublicPaymentDetail;
253
+ /**
254
+ * Reference is the order's human-facing reference (also the payment symbol).
255
+ * @example "RF26-000142"
256
+ */
86
257
  reference?: string;
258
+ /**
259
+ * Status is the order lifecycle state at creation time.
260
+ * @example "pending"
261
+ */
87
262
  status?: 'pending' | 'paid' | 'cancelled' | 'expired';
263
+ /**
264
+ * TotalCents is the amount due in the event currency's minor units.
265
+ * @example 149000
266
+ */
88
267
  totalCents?: number;
89
268
  }
269
+ /** Customer is the buyer's contact details. */
270
+ interface DtoPublicOrderCustomer {
271
+ /**
272
+ * Email is where the payment instructions and tickets are sent.
273
+ * @example "jana@example.com"
274
+ */
275
+ email: string;
276
+ /**
277
+ * Name is the buyer's full name.
278
+ * @maxLength 200
279
+ * @example "Jana Nováková"
280
+ */
281
+ name: string;
282
+ /**
283
+ * Phone is an optional contact number.
284
+ * @maxLength 50
285
+ * @example "+420123456789"
286
+ */
287
+ phone?: string;
288
+ }
289
+ interface DtoPublicOrderItem {
290
+ /**
291
+ * GAAreaID is the standing area's id for standing ticket types.
292
+ * @example "1810000000000000601"
293
+ */
294
+ gaAreaId?: string;
295
+ /**
296
+ * Quantity is how many to buy — always 1 for a seat, 1+ for standing.
297
+ * @min 1
298
+ * @example 1
299
+ */
300
+ quantity: number;
301
+ /**
302
+ * SeatID is the chosen seat's id for seated ticket types.
303
+ * @example "1810000000000000501"
304
+ */
305
+ seatId?: string;
306
+ /**
307
+ * TicketTypeID is the ticket type being bought (from the event endpoint).
308
+ * @example "1810000000000000201"
309
+ */
310
+ ticketTypeId: string;
311
+ }
312
+ interface DtoPublicOrderRequest {
313
+ /**
314
+ * CaptchaToken is the client-side captcha solution, verified server-side.
315
+ * @example "03AGdBq26…"
316
+ */
317
+ captchaToken?: string;
318
+ /** Customer is the buyer's contact details. */
319
+ customer: DtoPublicOrderCustomer;
320
+ /**
321
+ * Items are the order lines; at least one is required.
322
+ * @minItems 1
323
+ * @uniqueItems false
324
+ */
325
+ items: DtoPublicOrderItem[];
326
+ }
327
+ /** Org is the organizer's public branding (name, logo, accent colour). */
90
328
  interface DtoPublicOrg {
329
+ /**
330
+ * AccentColor is the organizer's brand colour as a hex string, if set.
331
+ * @example "#E5482F"
332
+ */
91
333
  accentColor?: string;
334
+ /**
335
+ * LogoURL is an absolute URL to the organizer's logo, if set.
336
+ * @example "https://cdn.bookitive.com/orgs/rockfest/logo.png"
337
+ */
92
338
  logoUrl?: string;
339
+ /**
340
+ * Name is the organizer's public display name.
341
+ * @example "Rockfest Productions"
342
+ */
93
343
  name?: string;
344
+ /**
345
+ * Slug is the organizer's URL identifier (the {orgSlug} path parameter).
346
+ * @example "rockfest"
347
+ */
94
348
  slug?: string;
95
349
  }
350
+ /** Payment carries the bank-transfer instructions for pending orders. */
96
351
  interface DtoPublicPaymentDetail {
97
- /** BankAccount is the organizer's free-form payment destination. */
352
+ /**
353
+ * BankAccount is the organizer's free-form payment destination.
354
+ * @example "123456789/0100"
355
+ */
98
356
  bankAccount?: string;
99
- /** VariableSymbol identifies the payment — it equals the order reference. */
357
+ /**
358
+ * VariableSymbol identifies the payment — it equals the order reference.
359
+ * @example "26000142"
360
+ */
100
361
  variableSymbol?: string;
101
362
  }
102
363
  interface DtoPublicSeat {
364
+ /**
365
+ * Code is the human-facing seat label (section prefix + table + seat).
366
+ * @example "L12-3"
367
+ */
103
368
  code?: string;
369
+ /**
370
+ * ID is the seat's stable id; availability and orders reference it.
371
+ * @example "1810000000000000501"
372
+ */
104
373
  id?: string;
374
+ /**
375
+ * TableID is the owning table's id, when the seat belongs to a table.
376
+ * @example "1810000000000000401"
377
+ */
105
378
  tableId?: string;
379
+ /**
380
+ * TicketTypeID is the ticket type mapped to this seat, when priced.
381
+ * @example "1810000000000000201"
382
+ */
106
383
  ticketTypeId?: string;
384
+ /**
385
+ * X is the seat centre's x on the floor canvas.
386
+ * @example 245
387
+ */
107
388
  x?: number;
389
+ /**
390
+ * Y is the seat centre's y on the floor canvas.
391
+ * @example 158
392
+ */
108
393
  y?: number;
109
394
  }
110
395
  interface DtoPublicSeating {
111
- /** @uniqueItems false */
396
+ /**
397
+ * Floors are the chart's floors in tab order, each with its geometry.
398
+ * @uniqueItems false
399
+ */
112
400
  floors?: DtoPublicFloor[];
113
401
  }
114
402
  interface DtoPublicSection {
403
+ /** Decorations is opaque visual scenery (stage, walls, doors) — never sold. */
115
404
  decorations?: object;
116
- /** @uniqueItems false */
405
+ /**
406
+ * GAAreas are the standing areas (sold by quantity) in this section.
407
+ * @uniqueItems false
408
+ */
117
409
  gaAreas?: DtoPublicGAArea[];
410
+ /**
411
+ * H is the section's height on the floor canvas, if sized.
412
+ * @example 300
413
+ */
118
414
  h?: number;
415
+ /**
416
+ * ID is the section's stable id.
417
+ * @example "1810000000000000301"
418
+ */
119
419
  id?: string;
420
+ /**
421
+ * Name is the section's display label.
422
+ * @example "Left block"
423
+ */
120
424
  name?: string;
425
+ /** Polygon is the section's outline as an array of {x,y} points, if shaped. */
121
426
  polygon?: object;
427
+ /**
428
+ * Prefix is prepended to seat codes in this section (e.g. "L" → "L12-3").
429
+ * @example "L"
430
+ */
122
431
  prefix?: string;
123
- /** @uniqueItems false */
432
+ /**
433
+ * Seats are the individually sellable seats in this section.
434
+ * @uniqueItems false
435
+ */
124
436
  seats?: DtoPublicSeat[];
437
+ /** Settings is opaque render config (chair gap/size, label typography). */
125
438
  settings?: object;
126
- /** @uniqueItems false */
439
+ /**
440
+ * Tables are the seated tables in this section.
441
+ * @uniqueItems false
442
+ */
127
443
  tables?: DtoPublicTable[];
444
+ /**
445
+ * W is the section's width on the floor canvas, if sized.
446
+ * @example 400
447
+ */
128
448
  w?: number;
449
+ /**
450
+ * X is the section's left offset on the floor canvas, if positioned.
451
+ * @example 120
452
+ */
129
453
  x?: number;
454
+ /**
455
+ * Y is the section's top offset on the floor canvas, if positioned.
456
+ * @example 80
457
+ */
130
458
  y?: number;
131
459
  }
132
460
  interface DtoPublicTable {
461
+ /**
462
+ * Curve is the arc for row tables, in degrees (0 = straight row).
463
+ * @example 0
464
+ */
133
465
  curve?: number;
466
+ /**
467
+ * H is the height for rect tables, in canvas units.
468
+ * @example 60
469
+ */
134
470
  h?: number;
471
+ /**
472
+ * ID is the table's stable id, referenced by PublicSeat.tableId.
473
+ * @example "1810000000000000401"
474
+ */
135
475
  id?: string;
476
+ /**
477
+ * Number is the table's display number within its section.
478
+ * @example 12
479
+ */
136
480
  number?: number;
481
+ /**
482
+ * Radius is the radius for round tables, in canvas units.
483
+ * @example 45
484
+ */
137
485
  radius?: number;
486
+ /**
487
+ * Rotation is the table's rotation in degrees.
488
+ * @example 0
489
+ */
138
490
  rotation?: number;
491
+ /**
492
+ * Shape is the table outline: "round", "rect", or "row".
493
+ * @example "round"
494
+ */
139
495
  shape?: 'round' | 'rect' | 'row';
140
- /** @uniqueItems false */
496
+ /**
497
+ * Sides is the seat count per edge for rect tables [top,right,bottom,left].
498
+ * @uniqueItems false
499
+ */
141
500
  sides?: number[];
501
+ /**
502
+ * Spacing is the gap between seats on a row table, in canvas units.
503
+ * @example 24
504
+ */
142
505
  spacing?: number;
506
+ /**
507
+ * W is the width for rect tables, in canvas units.
508
+ * @example 120
509
+ */
143
510
  w?: number;
511
+ /**
512
+ * X is the table centre's x on the floor canvas.
513
+ * @example 240.5
514
+ */
144
515
  x?: number;
516
+ /**
517
+ * Y is the table centre's y on the floor canvas.
518
+ * @example 160
519
+ */
145
520
  y?: number;
146
521
  }
147
522
  interface DtoPublicTicketType {
523
+ /**
524
+ * Color is the swatch used to tint seats/areas of this type, as hex.
525
+ * @example "#E5482F"
526
+ */
148
527
  color?: string;
149
- /** @uniqueItems false */
528
+ /**
529
+ * Cons are short caveats for this ticket type, shown alongside the pros.
530
+ * @uniqueItems false
531
+ * @example ["No seating"]
532
+ */
150
533
  cons?: string[];
534
+ /**
535
+ * Description is optional customer-facing copy for this ticket type.
536
+ * @example "Front-stage standing with a dedicated bar"
537
+ */
151
538
  description?: string;
539
+ /**
540
+ * ID is the ticket type's stable id, referenced by order items and seats.
541
+ * @example "1810000000000000201"
542
+ */
152
543
  id?: string;
544
+ /**
545
+ * Kind is "seated" (maps to a seat) or "standing" (sold by quantity).
546
+ * @example "standing"
547
+ */
153
548
  kind?: 'seated' | 'standing';
549
+ /**
550
+ * MaxPerOrder caps how many of this type a single order may contain.
551
+ * @example 6
552
+ */
154
553
  maxPerOrder?: number;
155
554
  /**
156
555
  * MinPerOrder appears only when it is a real constraint (> 1) — the
157
556
  * limit applies to orders that include this type at all.
557
+ * @example 1
158
558
  */
159
559
  minPerOrder?: number;
560
+ /**
561
+ * Name is the ticket type's display label.
562
+ * @example "VIP"
563
+ */
160
564
  name?: string;
565
+ /**
566
+ * PriceCents is the unit price in the event's currency's minor units.
567
+ * @example 149000
568
+ */
161
569
  priceCents?: number;
162
- /** @uniqueItems false */
570
+ /**
571
+ * Pros are short selling points for this ticket type, shown as a checklist.
572
+ * @uniqueItems false
573
+ * @example ["Best view","Dedicated bar","Fast-track entry"]
574
+ */
163
575
  pros?: string[];
576
+ /**
577
+ * SaleEndTime is when this type stops selling (RFC 3339), if scheduled.
578
+ * @example "2026-06-20T16:00:00Z"
579
+ */
164
580
  saleEndTime?: string;
165
- saleStartTime?: string;
166
- }
167
- interface PublichandlerPayloadPublicOrder {
168
- captchaToken?: string;
169
- customer: {
170
- email: string;
171
- /** @maxLength 200 */
172
- name: string;
173
- /** @maxLength 50 */
174
- phone?: string;
175
- };
176
581
  /**
177
- * @minItems 1
178
- * @uniqueItems false
582
+ * SaleStartTime is when this type goes on sale (RFC 3339), if scheduled.
583
+ * @example "2026-01-15T10:00:00Z"
179
584
  */
180
- items: PublichandlerPayloadPublicOrderItem[];
181
- }
182
- interface PublichandlerPayloadPublicOrderItem {
183
- gaAreaId?: string;
184
- /** @min 1 */
185
- quantity: number;
186
- seatId?: string;
187
- ticketTypeId: string;
188
- }
189
- interface ResponseAPIError {
190
- data?: any;
191
- fields?: Record<string, string>;
192
- /** @example "see fields" */
193
- msg: string;
194
- timestamp?: string;
195
- traceId?: string;
196
- type: ResponseType;
585
+ saleStartTime?: string;
197
586
  }
198
587
 
199
588
  /** One seat changing state. "reserved" appears only when the event shares
@@ -230,10 +619,10 @@ interface BookitiveClientOptions {
230
619
  /** API failure with the backend's error envelope attached. */
231
620
  declare class BookitiveError extends Error {
232
621
  readonly status: number;
233
- /** The backend error code (e.g. ResponseType.ErrConflict), or "UNKNOWN" when
622
+ /** The backend error code (e.g. DtoErrorCode.ErrConflict), or "UNKNOWN" when
234
623
  * the response carried no JSON envelope. */
235
- readonly type: ResponseType | 'UNKNOWN';
236
- constructor(status: number, body: ResponseAPIError | undefined, fallback: string);
624
+ readonly type: DtoErrorCode | 'UNKNOWN';
625
+ constructor(status: number, body: DtoAPIError | undefined, fallback: string);
237
626
  /** The selection raced another buyer — refresh availability and reselect. */
238
627
  get isConflict(): boolean;
239
628
  }
@@ -252,7 +641,7 @@ declare class BookitiveClient {
252
641
  * A 409 (error.isConflict) means a seat was just taken — refresh and
253
642
  * reselect.
254
643
  */
255
- checkout(order: PublichandlerPayloadPublicOrder): Promise<DtoPublicOrder>;
644
+ checkout(order: DtoPublicOrderRequest): Promise<DtoPublicOrder>;
256
645
  /**
257
646
  * Subscribes to live availability over websocket: `startstate` fires with
258
647
  * the full snapshot on every (re)connect, then `seat` deltas stream in.
@@ -261,4 +650,4 @@ declare class BookitiveClient {
261
650
  live(handlers: LiveHandlers): LiveSubscription;
262
651
  }
263
652
 
264
- export { BookitiveClient, type BookitiveClientOptions, BookitiveError, type DtoPublicAvailability, type DtoPublicEvent, type DtoPublicEventInfo, type DtoPublicFloor, type DtoPublicFloorInfo, type DtoPublicGAArea, type DtoPublicOrder, type DtoPublicOrg, type DtoPublicPaymentDetail, type DtoPublicSeat, type DtoPublicSeating, type DtoPublicSection, type DtoPublicTable, type DtoPublicTicketType, type LiveHandlers, LiveSubscription, type PublichandlerPayloadPublicOrder, type PublichandlerPayloadPublicOrderItem, type ResponseAPIError, ResponseType, type SeatDelta };
653
+ export { BookitiveClient, type BookitiveClientOptions, BookitiveError, type DtoAPIError, DtoErrorCode, type DtoPublicAvailability, type DtoPublicEvent, type DtoPublicEventInfo, type DtoPublicFloor, type DtoPublicFloorInfo, type DtoPublicGAArea, type DtoPublicOrder, type DtoPublicOrderCustomer, type DtoPublicOrderItem, type DtoPublicOrderRequest, type DtoPublicOrg, type DtoPublicPaymentDetail, type DtoPublicSeat, type DtoPublicSeating, type DtoPublicSection, type DtoPublicTable, type DtoPublicTicketType, type LiveHandlers, LiveSubscription, type SeatDelta };
package/dist/index.js CHANGED
@@ -1,17 +1,13 @@
1
1
  // src/generated/api.ts
2
- var ResponseType = /* @__PURE__ */ ((ResponseType2) => {
3
- ResponseType2["ErrInvalidPayload"] = "INVALID_PAYLOAD";
4
- ResponseType2["ErrValidationFailed"] = "VALIDATION_FAILED";
5
- ResponseType2["ErrNotFound"] = "NOT_FOUND";
6
- ResponseType2["ErrNotImplemented"] = "NOT_IMPLEMENTED";
7
- ResponseType2["ErrConflict"] = "CONFLICT";
8
- ResponseType2["ErrInternal"] = "INTERNAL_ERROR";
9
- ResponseType2["ErrUnauthorized"] = "UNAUTHORIZED";
10
- ResponseType2["ErrForbidden"] = "FORBIDDEN";
11
- ResponseType2["ErrMissingOrganizationID"] = "MISSING_ORGANIZATION_ID";
12
- ResponseType2["ErrMissingUserID"] = "MISSING_USER_ID";
13
- return ResponseType2;
14
- })(ResponseType || {});
2
+ var DtoErrorCode = /* @__PURE__ */ ((DtoErrorCode2) => {
3
+ DtoErrorCode2["ErrInvalidPayload"] = "INVALID_PAYLOAD";
4
+ DtoErrorCode2["ErrValidationFailed"] = "VALIDATION_FAILED";
5
+ DtoErrorCode2["ErrNotFound"] = "NOT_FOUND";
6
+ DtoErrorCode2["ErrConflict"] = "CONFLICT";
7
+ DtoErrorCode2["ErrForbidden"] = "FORBIDDEN";
8
+ DtoErrorCode2["ErrInternal"] = "INTERNAL_ERROR";
9
+ return DtoErrorCode2;
10
+ })(DtoErrorCode || {});
15
11
 
16
12
  // src/live.ts
17
13
  var INITIAL_BACKOFF_MS = 1e3;
@@ -67,7 +63,7 @@ var LiveSubscription = class {
67
63
  // src/client.ts
68
64
  var BookitiveError = class extends Error {
69
65
  status;
70
- /** The backend error code (e.g. ResponseType.ErrConflict), or "UNKNOWN" when
66
+ /** The backend error code (e.g. DtoErrorCode.ErrConflict), or "UNKNOWN" when
71
67
  * the response carried no JSON envelope. */
72
68
  type;
73
69
  constructor(status, body, fallback) {
@@ -146,7 +142,7 @@ var BookitiveClient = class {
146
142
  export {
147
143
  BookitiveClient,
148
144
  BookitiveError,
149
- LiveSubscription,
150
- ResponseType
145
+ DtoErrorCode,
146
+ LiveSubscription
151
147
  };
152
148
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/generated/api.ts","../src/live.ts","../src/client.ts"],"sourcesContent":["/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------------\n * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##\n * ## ##\n * ## AUTHOR: acacode ##\n * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##\n * ---------------------------------------------------------------\n */\n\n/** @example \"VALIDATION_FAILED\" */\nexport enum ResponseType {\n\tErrInvalidPayload = 'INVALID_PAYLOAD',\n\tErrValidationFailed = 'VALIDATION_FAILED',\n\tErrNotFound = 'NOT_FOUND',\n\tErrNotImplemented = 'NOT_IMPLEMENTED',\n\tErrConflict = 'CONFLICT',\n\tErrInternal = 'INTERNAL_ERROR',\n\tErrUnauthorized = 'UNAUTHORIZED',\n\tErrForbidden = 'FORBIDDEN',\n\tErrMissingOrganizationID = 'MISSING_ORGANIZATION_ID',\n\tErrMissingUserID = 'MISSING_USER_ID',\n}\n\nexport interface DtoPublicAvailability {\n\tgaRemaining?: Record<string, number>;\n\t/**\n\t * ReservedSeats marks which unavailable seats are merely reserved and may\n\t * free up again — present only when the event shares reserved status.\n\t * @uniqueItems false\n\t */\n\treservedSeats?: string[];\n\tticketTypeRemaining?: Record<string, number>;\n\t/** @uniqueItems false */\n\tunavailableSeats?: string[];\n}\n\nexport interface DtoPublicEvent {\n\tevent?: DtoPublicEventInfo;\n\t/**\n\t * Floors lets a host page render its floor tabs without loading the full\n\t * seating payload; ids match the seating endpoint's floors.\n\t * @uniqueItems false\n\t */\n\tfloors?: DtoPublicFloorInfo[];\n\torg?: DtoPublicOrg;\n\t/** @uniqueItems false */\n\tticketTypes?: DtoPublicTicketType[];\n}\n\nexport interface DtoPublicEventInfo {\n\tcurrency?: string;\n\tendTime?: string;\n\tholdTtlSeconds?: number;\n\tlocationName?: string;\n\tname?: string;\n\tslug?: string;\n\tstartTime?: string;\n}\n\nexport interface DtoPublicFloor {\n\t/** @uniqueItems false */\n\tcons?: string[];\n\tdescription?: string;\n\tid?: string;\n\tmode?: 'single' | 'sections';\n\tname?: string;\n\tposition?: number;\n\t/** @uniqueItems false */\n\tpros?: string[];\n\t/** @uniqueItems false */\n\tsections?: DtoPublicSection[];\n}\n\nexport interface DtoPublicFloorInfo {\n\t/** @uniqueItems false */\n\tcons?: string[];\n\tdescription?: string;\n\tid?: string;\n\tmode?: 'single' | 'sections';\n\tname?: string;\n\tposition?: number;\n\t/** @uniqueItems false */\n\tpros?: string[];\n}\n\nexport interface DtoPublicGAArea {\n\tcapacity?: number;\n\th?: number;\n\tid?: string;\n\tlabel?: string;\n\trotation?: number;\n\tticketTypeId?: string;\n\tw?: number;\n\tx?: number;\n\ty?: number;\n}\n\nexport interface DtoPublicOrder {\n\tcurrency?: string;\n\texpiresAt?: string;\n\tpayment?: DtoPublicPaymentDetail;\n\treference?: string;\n\tstatus?: 'pending' | 'paid' | 'cancelled' | 'expired';\n\ttotalCents?: number;\n}\n\nexport interface DtoPublicOrg {\n\taccentColor?: string;\n\tlogoUrl?: string;\n\tname?: string;\n\tslug?: string;\n}\n\nexport interface DtoPublicPaymentDetail {\n\t/** BankAccount is the organizer's free-form payment destination. */\n\tbankAccount?: string;\n\t/** VariableSymbol identifies the payment — it equals the order reference. */\n\tvariableSymbol?: string;\n}\n\nexport interface DtoPublicSeat {\n\tcode?: string;\n\tid?: string;\n\ttableId?: string;\n\tticketTypeId?: string;\n\tx?: number;\n\ty?: number;\n}\n\nexport interface DtoPublicSeating {\n\t/** @uniqueItems false */\n\tfloors?: DtoPublicFloor[];\n}\n\nexport interface DtoPublicSection {\n\tdecorations?: object;\n\t/** @uniqueItems false */\n\tgaAreas?: DtoPublicGAArea[];\n\th?: number;\n\tid?: string;\n\tname?: string;\n\tpolygon?: object;\n\tprefix?: string;\n\t/** @uniqueItems false */\n\tseats?: DtoPublicSeat[];\n\tsettings?: object;\n\t/** @uniqueItems false */\n\ttables?: DtoPublicTable[];\n\tw?: number;\n\tx?: number;\n\ty?: number;\n}\n\nexport interface DtoPublicTable {\n\tcurve?: number;\n\th?: number;\n\tid?: string;\n\tnumber?: number;\n\tradius?: number;\n\trotation?: number;\n\tshape?: 'round' | 'rect' | 'row';\n\t/** @uniqueItems false */\n\tsides?: number[];\n\tspacing?: number;\n\tw?: number;\n\tx?: number;\n\ty?: number;\n}\n\nexport interface DtoPublicTicketType {\n\tcolor?: string;\n\t/** @uniqueItems false */\n\tcons?: string[];\n\tdescription?: string;\n\tid?: string;\n\tkind?: 'seated' | 'standing';\n\tmaxPerOrder?: number;\n\t/**\n\t * MinPerOrder appears only when it is a real constraint (> 1) — the\n\t * limit applies to orders that include this type at all.\n\t */\n\tminPerOrder?: number;\n\tname?: string;\n\tpriceCents?: number;\n\t/** @uniqueItems false */\n\tpros?: string[];\n\tsaleEndTime?: string;\n\tsaleStartTime?: string;\n}\n\nexport interface PublichandlerPayloadPublicOrder {\n\tcaptchaToken?: string;\n\tcustomer: {\n\t\temail: string;\n\t\t/** @maxLength 200 */\n\t\tname: string;\n\t\t/** @maxLength 50 */\n\t\tphone?: string;\n\t};\n\t/**\n\t * @minItems 1\n\t * @uniqueItems false\n\t */\n\titems: PublichandlerPayloadPublicOrderItem[];\n}\n\nexport interface PublichandlerPayloadPublicOrderItem {\n\tgaAreaId?: string;\n\t/** @min 1 */\n\tquantity: number;\n\tseatId?: string;\n\tticketTypeId: string;\n}\n\nexport interface ResponseAPIError {\n\tdata?: any;\n\tfields?: Record<string, string>;\n\t/** @example \"see fields\" */\n\tmsg: string;\n\ttimestamp?: string;\n\ttraceId?: string;\n\ttype: ResponseType;\n}\n","// Live availability over websocket: {\"event\":\"startstate\"|\"seat\", data}.\n// Startstate re-fires on every reconnect, so consumers treat it as the\n// resync point and apply deltas on top.\nimport type { DtoPublicAvailability } from './generated/api.js';\n\n/** One seat changing state. \"reserved\" appears only when the event shares\n * reserved status publicly — a reserved seat may free up again. */\nexport interface SeatDelta {\n\tseatId: string;\n\ttaken: boolean;\n\tstatus: 'free' | 'reserved' | 'taken';\n}\n\nexport interface LiveHandlers {\n\t/** Full snapshot — on connect and on every reconnect. */\n\tonStartstate?: (availability: DtoPublicAvailability) => void;\n\t/** One seat changed. */\n\tonSeat?: (delta: SeatDelta) => void;\n\t/** Connection state changes (drive a \"live\" indicator if you like). */\n\tonConnectionChange?: (connected: boolean) => void;\n}\n\nconst INITIAL_BACKOFF_MS = 1000;\nconst MAX_BACKOFF_MS = 15000;\n\nexport class LiveSubscription {\n\t#url: string;\n\t#handlers: LiveHandlers;\n\t#ws: WebSocket | null = null;\n\t#backoff = INITIAL_BACKOFF_MS;\n\t#retry: ReturnType<typeof setTimeout> | null = null;\n\t#closed = false;\n\n\tconstructor(url: string, handlers: LiveHandlers) {\n\t\tthis.#url = url.replace(/^http/, 'ws');\n\t\tthis.#handlers = handlers;\n\t\tthis.#connect();\n\t}\n\n\tclose(): void {\n\t\tthis.#closed = true;\n\t\tif (this.#retry) clearTimeout(this.#retry);\n\t\tthis.#ws?.close();\n\t}\n\n\t#connect(): void {\n\t\tif (this.#closed) return;\n\t\tconst ws = new WebSocket(this.#url);\n\t\tthis.#ws = ws;\n\t\tws.onopen = () => {\n\t\t\tthis.#backoff = INITIAL_BACKOFF_MS;\n\t\t\tthis.#handlers.onConnectionChange?.(true);\n\t\t};\n\t\tws.onmessage = (event) => {\n\t\t\tlet message: { event?: string; data?: unknown };\n\t\t\ttry {\n\t\t\t\tmessage = JSON.parse(event.data as string);\n\t\t\t} catch {\n\t\t\t\treturn; // ignore malformed / non-JSON frames rather than throwing\n\t\t\t}\n\t\t\tif (message.event === 'startstate') {\n\t\t\t\tthis.#handlers.onStartstate?.(message.data as DtoPublicAvailability);\n\t\t\t} else if (message.event === 'seat') {\n\t\t\t\tthis.#handlers.onSeat?.(message.data as SeatDelta);\n\t\t\t}\n\t\t};\n\t\tws.onclose = () => {\n\t\t\tthis.#handlers.onConnectionChange?.(false);\n\t\t\tif (this.#closed) return;\n\t\t\t// Equal-jitter backoff: reconnect somewhere in [backoff/2, backoff) so a\n\t\t\t// mass disconnect doesn't produce a synchronized reconnect thundering herd.\n\t\t\tconst delay = this.#backoff / 2 + Math.random() * (this.#backoff / 2);\n\t\t\tthis.#retry = setTimeout(() => this.#connect(), delay);\n\t\t\tthis.#backoff = Math.min(this.#backoff * 2, MAX_BACKOFF_MS);\n\t\t};\n\t}\n}\n","// The typed core of @bookitive/js: a thin fetch wrapper over the public\n// checkout API, addressed by org + event slug. All response and payload types\n// are generated from the backend's public swagger — they cannot drift.\nimport { ResponseType } from './generated/api.js';\nimport type {\n\tDtoPublicAvailability,\n\tDtoPublicEvent,\n\tDtoPublicOrder,\n\tDtoPublicSeating,\n\tPublichandlerPayloadPublicOrder,\n\tResponseAPIError,\n} from './generated/api.js';\nimport { LiveSubscription, type LiveHandlers } from './live.js';\n\nexport interface BookitiveClientOptions {\n\t/** API origin, e.g. \"https://api.bookitive.com\" (no trailing slash). */\n\tbaseUrl: string;\n\t/** Organization slug — the {org} in events.bookitive.com/{org}/{event}. */\n\torg: string;\n\t/** Event slug. */\n\tevent: string;\n\t/** Custom fetch (SSR frameworks pass their own). Defaults to global fetch. */\n\tfetch?: typeof fetch;\n}\n\n/** API failure with the backend's error envelope attached. */\nexport class BookitiveError extends Error {\n\treadonly status: number;\n\t/** The backend error code (e.g. ResponseType.ErrConflict), or \"UNKNOWN\" when\n\t * the response carried no JSON envelope. */\n\treadonly type: ResponseType | 'UNKNOWN';\n\n\tconstructor(status: number, body: ResponseAPIError | undefined, fallback: string) {\n\t\tsuper(body?.msg ?? fallback);\n\t\tthis.name = 'BookitiveError';\n\t\tthis.status = status;\n\t\tthis.type = body?.type ?? 'UNKNOWN';\n\t}\n\n\t/** The selection raced another buyer — refresh availability and reselect. */\n\tget isConflict(): boolean {\n\t\treturn this.type === ResponseType.ErrConflict || this.status === 409;\n\t}\n}\n\nexport class BookitiveClient {\n\treadonly #base: string;\n\treadonly #fetch: typeof fetch;\n\n\tconstructor(options: BookitiveClientOptions) {\n\t\tthis.#base = `${options.baseUrl.replace(/\\/$/, '')}/public/v1/orgs/${encodeURIComponent(\n\t\t\toptions.org\n\t\t)}/events/${encodeURIComponent(options.event)}`;\n\t\t// bind, or a browser's fetch throws \"Illegal invocation\" when called\n\t\t// detached from window\n\t\tthis.#fetch = options.fetch ?? ((...args) => fetch(...args));\n\t}\n\n\t/** Event identity, org branding, priced ticket types, and floor tabs. */\n\tevent(): Promise<DtoPublicEvent> {\n\t\treturn this.#get<DtoPublicEvent>('');\n\t}\n\n\t/** Static chart geometry: floors → sections → tables, seats, GA areas. */\n\tseating(): Promise<DtoPublicSeating> {\n\t\treturn this.#get<DtoPublicSeating>('/seating');\n\t}\n\n\t/** Live sellability snapshot (poll it, or use live() for push updates). */\n\tavailability(): Promise<DtoPublicAvailability> {\n\t\treturn this.#get<DtoPublicAvailability>('/availability');\n\t}\n\n\t/**\n\t * Places a bank-transfer reservation: seats are held atomically for the\n\t * event's hold TTL and payment instructions are emailed (and returned).\n\t * A 409 (error.isConflict) means a seat was just taken — refresh and\n\t * reselect.\n\t */\n\tasync checkout(order: PublichandlerPayloadPublicOrder): Promise<DtoPublicOrder> {\n\t\tconst res = await this.#fetch(`${this.#base}/orders`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify(order),\n\t\t});\n\t\treturn this.#parse<DtoPublicOrder>(res, 'checkout failed');\n\t}\n\n\t/**\n\t * Subscribes to live availability over websocket: `startstate` fires with\n\t * the full snapshot on every (re)connect, then `seat` deltas stream in.\n\t * Reconnects automatically with backoff; call close() when done.\n\t */\n\tlive(handlers: LiveHandlers): LiveSubscription {\n\t\treturn new LiveSubscription(`${this.#base}/live`, handlers);\n\t}\n\n\tasync #get<T>(path: string): Promise<T> {\n\t\tconst res = await this.#fetch(`${this.#base}${path}`);\n\t\treturn this.#parse<T>(res, `request failed: ${path || '/'}`);\n\t}\n\n\tasync #parse<T>(res: Response, fallback: string): Promise<T> {\n\t\tif (!res.ok) {\n\t\t\tlet body: ResponseAPIError | undefined;\n\t\t\ttry {\n\t\t\t\tbody = (await res.json()) as ResponseAPIError;\n\t\t\t} catch {\n\t\t\t\t// non-JSON error body — the fallback message covers it\n\t\t\t}\n\t\t\tthrow new BookitiveError(res.status, body, fallback);\n\t\t}\n\t\t// No content (204) or an explicitly empty body — don't call res.json(),\n\t\t// which would throw on an empty stream.\n\t\tif (res.status === 204 || res.headers.get('content-length') === '0') {\n\t\t\treturn undefined as T;\n\t\t}\n\t\treturn (await res.json()) as T;\n\t}\n}\n"],"mappings":"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","names":["ResponseType"]}
1
+ {"version":3,"sources":["../src/generated/api.ts","../src/live.ts","../src/client.ts"],"sourcesContent":["/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------------\n * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##\n * ## ##\n * ## AUTHOR: acacode ##\n * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##\n * ---------------------------------------------------------------\n */\n\n/**\n * Type is the stable, machine-readable error code.\n * @example \"CONFLICT\"\n */\nexport enum DtoErrorCode {\n\tErrInvalidPayload = 'INVALID_PAYLOAD',\n\tErrValidationFailed = 'VALIDATION_FAILED',\n\tErrNotFound = 'NOT_FOUND',\n\tErrConflict = 'CONFLICT',\n\tErrForbidden = 'FORBIDDEN',\n\tErrInternal = 'INTERNAL_ERROR',\n}\n\nexport interface DtoAPIError {\n\t/** Data carries optional structured context for the error. */\n\tdata?: any;\n\t/** Fields maps a request field to a validation message, when applicable. */\n\tfields?: Record<string, string>;\n\t/**\n\t * Msg is a human-readable description of what went wrong.\n\t * @example \"seat is no longer available\"\n\t */\n\tmsg?: string;\n\t/**\n\t * Timestamp is when the error was produced (RFC 3339).\n\t * @example \"2026-06-20T18:00:00Z\"\n\t */\n\ttimestamp?: string;\n\t/**\n\t * TraceID identifies this request in our logs; include it in support asks.\n\t * @example \"01JABCDoftraceZ\"\n\t */\n\ttraceId?: string;\n\t/** Type is the stable, machine-readable error code. */\n\ttype?: DtoErrorCode;\n}\n\nexport interface DtoPublicAvailability {\n\t/** GARemaining maps a standing area id to its remaining capacity. */\n\tgaRemaining?: Record<string, number>;\n\t/**\n\t * ReservedSeats marks which unavailable seats are merely reserved and may\n\t * free up again — present only when the event shares reserved status.\n\t * @uniqueItems false\n\t * @example [\"1810000000000000502\"]\n\t */\n\treservedSeats?: string[];\n\t/** TicketTypeRemaining maps a ticket type id to its remaining capacity. */\n\tticketTypeRemaining?: Record<string, number>;\n\t/**\n\t * UnavailableSeats lists the ids of seats that cannot currently be bought.\n\t * @uniqueItems false\n\t * @example [\"1810000000000000501\",\"1810000000000000502\"]\n\t */\n\tunavailableSeats?: string[];\n}\n\nexport interface DtoPublicEvent {\n\t/** Event is the event's public identity: name, times, venue, currency. */\n\tevent?: DtoPublicEventInfo;\n\t/**\n\t * Floors lets a host page render its floor tabs without loading the full\n\t * seating payload; ids match the seating endpoint's floors.\n\t * @uniqueItems false\n\t */\n\tfloors?: DtoPublicFloorInfo[];\n\t/** Org is the organizer's public branding (name, logo, accent colour). */\n\torg?: DtoPublicOrg;\n\t/**\n\t * TicketTypes are the sellable ticket categories with prices and limits.\n\t * @uniqueItems false\n\t */\n\tticketTypes?: DtoPublicTicketType[];\n}\n\n/** Event is the event's public identity: name, times, venue, currency. */\nexport interface DtoPublicEventInfo {\n\t/**\n\t * Currency is the ISO 4217 code all prices are quoted in.\n\t * @example \"CZK\"\n\t */\n\tcurrency?: string;\n\t/**\n\t * EndTime is when the event ends (RFC 3339), when known.\n\t * @example \"2026-06-20T23:00:00Z\"\n\t */\n\tendTime?: string;\n\t/**\n\t * HoldTTLSeconds is how long a checkout holds selected seats before expiry.\n\t * @example 900\n\t */\n\tholdTtlSeconds?: number;\n\t/**\n\t * LocationName is the venue's display name, when set.\n\t * @example \"Výstaviště Praha\"\n\t */\n\tlocationName?: string;\n\t/**\n\t * Name is the event's public display name.\n\t * @example \"Rockfest 2026\"\n\t */\n\tname?: string;\n\t/**\n\t * Slug is the event's URL identifier (the {eventSlug} path parameter).\n\t * @example \"rockfest-2026\"\n\t */\n\tslug?: string;\n\t/**\n\t * StartTime is when doors/the event begins (RFC 3339).\n\t * @example \"2026-06-20T18:00:00Z\"\n\t */\n\tstartTime?: string;\n}\n\nexport interface DtoPublicFloor {\n\t/**\n\t * Cons are short caveats for this floor, shown alongside the pros.\n\t * @uniqueItems false\n\t * @example [\"Standing only\"]\n\t */\n\tcons?: string[];\n\t/**\n\t * Description is optional customer-facing copy shown on the floor's tab.\n\t * @example \"Standing area in front of the main stage\"\n\t */\n\tdescription?: string;\n\t/**\n\t * ID is the floor's stable id; it matches PublicFloorInfo.id.\n\t * @example \"1810000000000000101\"\n\t */\n\tid?: string;\n\t/**\n\t * Mode is \"single\" (one open space) or \"sections\" (subdivided blocks).\n\t * @example \"sections\"\n\t */\n\tmode?: 'single' | 'sections';\n\t/**\n\t * Name is the floor's display label.\n\t * @example \"Ground floor\"\n\t */\n\tname?: string;\n\t/**\n\t * Position is the 1-based tab order among the event's floors.\n\t * @example 1\n\t */\n\tposition?: number;\n\t/**\n\t * Pros are short selling points for this floor, shown as a checklist.\n\t * @uniqueItems false\n\t * @example [\"Closest to the stage\",\"Great atmosphere\"]\n\t */\n\tpros?: string[];\n\t/**\n\t * Sections are the floor's blocks; a single-mode floor has exactly one.\n\t * @uniqueItems false\n\t */\n\tsections?: DtoPublicSection[];\n}\n\nexport interface DtoPublicFloorInfo {\n\t/**\n\t * Cons are short caveats for this floor, shown alongside the pros.\n\t * @uniqueItems false\n\t * @example [\"Standing only\"]\n\t */\n\tcons?: string[];\n\t/**\n\t * Description is optional customer-facing copy shown on the floor's tab.\n\t * @example \"Standing area in front of the main stage\"\n\t */\n\tdescription?: string;\n\t/**\n\t * ID is the floor's stable id; it matches a floor in the seating endpoint.\n\t * @example \"1810000000000000101\"\n\t */\n\tid?: string;\n\t/**\n\t * Mode is \"single\" (one open space) or \"sections\" (subdivided blocks).\n\t * @example \"sections\"\n\t */\n\tmode?: 'single' | 'sections';\n\t/**\n\t * Name is the floor's display label.\n\t * @example \"Ground floor\"\n\t */\n\tname?: string;\n\t/**\n\t * Position is the 1-based tab order among the event's floors.\n\t * @example 1\n\t */\n\tposition?: number;\n\t/**\n\t * Pros are short selling points for this floor, shown as a checklist.\n\t * @uniqueItems false\n\t * @example [\"Closest to the stage\",\"Great atmosphere\"]\n\t */\n\tpros?: string[];\n}\n\nexport interface DtoPublicGAArea {\n\t/**\n\t * Capacity is the total number of standing tickets this area can sell.\n\t * @example 500\n\t */\n\tcapacity?: number;\n\t/**\n\t * H is the area's height on the floor canvas.\n\t * @example 200\n\t */\n\th?: number;\n\t/**\n\t * ID is the standing area's stable id, referenced by availability/orders.\n\t * @example \"1810000000000000601\"\n\t */\n\tid?: string;\n\t/**\n\t * Label is the standing area's display name.\n\t * @example \"Pit\"\n\t */\n\tlabel?: string;\n\t/**\n\t * Rotation is the area's rotation in degrees.\n\t * @example 0\n\t */\n\trotation?: number;\n\t/**\n\t * TicketTypeID is the standing ticket type mapped to this area, when priced.\n\t * @example \"1810000000000000201\"\n\t */\n\tticketTypeId?: string;\n\t/**\n\t * W is the area's width on the floor canvas.\n\t * @example 600\n\t */\n\tw?: number;\n\t/**\n\t * X is the area's left offset on the floor canvas.\n\t * @example 100\n\t */\n\tx?: number;\n\t/**\n\t * Y is the area's top offset on the floor canvas.\n\t * @example 400\n\t */\n\ty?: number;\n}\n\nexport interface DtoPublicOrder {\n\t/**\n\t * Currency is the ISO 4217 code the total is quoted in.\n\t * @example \"CZK\"\n\t */\n\tcurrency?: string;\n\t/**\n\t * ExpiresAt is when the held seats and this order expire (RFC 3339).\n\t * @example \"2026-06-20T18:15:00Z\"\n\t */\n\texpiresAt?: string;\n\t/** Payment carries the bank-transfer instructions for pending orders. */\n\tpayment?: DtoPublicPaymentDetail;\n\t/**\n\t * Reference is the order's human-facing reference (also the payment symbol).\n\t * @example \"RF26-000142\"\n\t */\n\treference?: string;\n\t/**\n\t * Status is the order lifecycle state at creation time.\n\t * @example \"pending\"\n\t */\n\tstatus?: 'pending' | 'paid' | 'cancelled' | 'expired';\n\t/**\n\t * TotalCents is the amount due in the event currency's minor units.\n\t * @example 149000\n\t */\n\ttotalCents?: number;\n}\n\n/** Customer is the buyer's contact details. */\nexport interface DtoPublicOrderCustomer {\n\t/**\n\t * Email is where the payment instructions and tickets are sent.\n\t * @example \"jana@example.com\"\n\t */\n\temail: string;\n\t/**\n\t * Name is the buyer's full name.\n\t * @maxLength 200\n\t * @example \"Jana Nováková\"\n\t */\n\tname: string;\n\t/**\n\t * Phone is an optional contact number.\n\t * @maxLength 50\n\t * @example \"+420123456789\"\n\t */\n\tphone?: string;\n}\n\nexport interface DtoPublicOrderItem {\n\t/**\n\t * GAAreaID is the standing area's id for standing ticket types.\n\t * @example \"1810000000000000601\"\n\t */\n\tgaAreaId?: string;\n\t/**\n\t * Quantity is how many to buy — always 1 for a seat, 1+ for standing.\n\t * @min 1\n\t * @example 1\n\t */\n\tquantity: number;\n\t/**\n\t * SeatID is the chosen seat's id for seated ticket types.\n\t * @example \"1810000000000000501\"\n\t */\n\tseatId?: string;\n\t/**\n\t * TicketTypeID is the ticket type being bought (from the event endpoint).\n\t * @example \"1810000000000000201\"\n\t */\n\tticketTypeId: string;\n}\n\nexport interface DtoPublicOrderRequest {\n\t/**\n\t * CaptchaToken is the client-side captcha solution, verified server-side.\n\t * @example \"03AGdBq26…\"\n\t */\n\tcaptchaToken?: string;\n\t/** Customer is the buyer's contact details. */\n\tcustomer: DtoPublicOrderCustomer;\n\t/**\n\t * Items are the order lines; at least one is required.\n\t * @minItems 1\n\t * @uniqueItems false\n\t */\n\titems: DtoPublicOrderItem[];\n}\n\n/** Org is the organizer's public branding (name, logo, accent colour). */\nexport interface DtoPublicOrg {\n\t/**\n\t * AccentColor is the organizer's brand colour as a hex string, if set.\n\t * @example \"#E5482F\"\n\t */\n\taccentColor?: string;\n\t/**\n\t * LogoURL is an absolute URL to the organizer's logo, if set.\n\t * @example \"https://cdn.bookitive.com/orgs/rockfest/logo.png\"\n\t */\n\tlogoUrl?: string;\n\t/**\n\t * Name is the organizer's public display name.\n\t * @example \"Rockfest Productions\"\n\t */\n\tname?: string;\n\t/**\n\t * Slug is the organizer's URL identifier (the {orgSlug} path parameter).\n\t * @example \"rockfest\"\n\t */\n\tslug?: string;\n}\n\n/** Payment carries the bank-transfer instructions for pending orders. */\nexport interface DtoPublicPaymentDetail {\n\t/**\n\t * BankAccount is the organizer's free-form payment destination.\n\t * @example \"123456789/0100\"\n\t */\n\tbankAccount?: string;\n\t/**\n\t * VariableSymbol identifies the payment — it equals the order reference.\n\t * @example \"26000142\"\n\t */\n\tvariableSymbol?: string;\n}\n\nexport interface DtoPublicSeat {\n\t/**\n\t * Code is the human-facing seat label (section prefix + table + seat).\n\t * @example \"L12-3\"\n\t */\n\tcode?: string;\n\t/**\n\t * ID is the seat's stable id; availability and orders reference it.\n\t * @example \"1810000000000000501\"\n\t */\n\tid?: string;\n\t/**\n\t * TableID is the owning table's id, when the seat belongs to a table.\n\t * @example \"1810000000000000401\"\n\t */\n\ttableId?: string;\n\t/**\n\t * TicketTypeID is the ticket type mapped to this seat, when priced.\n\t * @example \"1810000000000000201\"\n\t */\n\tticketTypeId?: string;\n\t/**\n\t * X is the seat centre's x on the floor canvas.\n\t * @example 245\n\t */\n\tx?: number;\n\t/**\n\t * Y is the seat centre's y on the floor canvas.\n\t * @example 158\n\t */\n\ty?: number;\n}\n\nexport interface DtoPublicSeating {\n\t/**\n\t * Floors are the chart's floors in tab order, each with its geometry.\n\t * @uniqueItems false\n\t */\n\tfloors?: DtoPublicFloor[];\n}\n\nexport interface DtoPublicSection {\n\t/** Decorations is opaque visual scenery (stage, walls, doors) — never sold. */\n\tdecorations?: object;\n\t/**\n\t * GAAreas are the standing areas (sold by quantity) in this section.\n\t * @uniqueItems false\n\t */\n\tgaAreas?: DtoPublicGAArea[];\n\t/**\n\t * H is the section's height on the floor canvas, if sized.\n\t * @example 300\n\t */\n\th?: number;\n\t/**\n\t * ID is the section's stable id.\n\t * @example \"1810000000000000301\"\n\t */\n\tid?: string;\n\t/**\n\t * Name is the section's display label.\n\t * @example \"Left block\"\n\t */\n\tname?: string;\n\t/** Polygon is the section's outline as an array of {x,y} points, if shaped. */\n\tpolygon?: object;\n\t/**\n\t * Prefix is prepended to seat codes in this section (e.g. \"L\" → \"L12-3\").\n\t * @example \"L\"\n\t */\n\tprefix?: string;\n\t/**\n\t * Seats are the individually sellable seats in this section.\n\t * @uniqueItems false\n\t */\n\tseats?: DtoPublicSeat[];\n\t/** Settings is opaque render config (chair gap/size, label typography). */\n\tsettings?: object;\n\t/**\n\t * Tables are the seated tables in this section.\n\t * @uniqueItems false\n\t */\n\ttables?: DtoPublicTable[];\n\t/**\n\t * W is the section's width on the floor canvas, if sized.\n\t * @example 400\n\t */\n\tw?: number;\n\t/**\n\t * X is the section's left offset on the floor canvas, if positioned.\n\t * @example 120\n\t */\n\tx?: number;\n\t/**\n\t * Y is the section's top offset on the floor canvas, if positioned.\n\t * @example 80\n\t */\n\ty?: number;\n}\n\nexport interface DtoPublicTable {\n\t/**\n\t * Curve is the arc for row tables, in degrees (0 = straight row).\n\t * @example 0\n\t */\n\tcurve?: number;\n\t/**\n\t * H is the height for rect tables, in canvas units.\n\t * @example 60\n\t */\n\th?: number;\n\t/**\n\t * ID is the table's stable id, referenced by PublicSeat.tableId.\n\t * @example \"1810000000000000401\"\n\t */\n\tid?: string;\n\t/**\n\t * Number is the table's display number within its section.\n\t * @example 12\n\t */\n\tnumber?: number;\n\t/**\n\t * Radius is the radius for round tables, in canvas units.\n\t * @example 45\n\t */\n\tradius?: number;\n\t/**\n\t * Rotation is the table's rotation in degrees.\n\t * @example 0\n\t */\n\trotation?: number;\n\t/**\n\t * Shape is the table outline: \"round\", \"rect\", or \"row\".\n\t * @example \"round\"\n\t */\n\tshape?: 'round' | 'rect' | 'row';\n\t/**\n\t * Sides is the seat count per edge for rect tables [top,right,bottom,left].\n\t * @uniqueItems false\n\t */\n\tsides?: number[];\n\t/**\n\t * Spacing is the gap between seats on a row table, in canvas units.\n\t * @example 24\n\t */\n\tspacing?: number;\n\t/**\n\t * W is the width for rect tables, in canvas units.\n\t * @example 120\n\t */\n\tw?: number;\n\t/**\n\t * X is the table centre's x on the floor canvas.\n\t * @example 240.5\n\t */\n\tx?: number;\n\t/**\n\t * Y is the table centre's y on the floor canvas.\n\t * @example 160\n\t */\n\ty?: number;\n}\n\nexport interface DtoPublicTicketType {\n\t/**\n\t * Color is the swatch used to tint seats/areas of this type, as hex.\n\t * @example \"#E5482F\"\n\t */\n\tcolor?: string;\n\t/**\n\t * Cons are short caveats for this ticket type, shown alongside the pros.\n\t * @uniqueItems false\n\t * @example [\"No seating\"]\n\t */\n\tcons?: string[];\n\t/**\n\t * Description is optional customer-facing copy for this ticket type.\n\t * @example \"Front-stage standing with a dedicated bar\"\n\t */\n\tdescription?: string;\n\t/**\n\t * ID is the ticket type's stable id, referenced by order items and seats.\n\t * @example \"1810000000000000201\"\n\t */\n\tid?: string;\n\t/**\n\t * Kind is \"seated\" (maps to a seat) or \"standing\" (sold by quantity).\n\t * @example \"standing\"\n\t */\n\tkind?: 'seated' | 'standing';\n\t/**\n\t * MaxPerOrder caps how many of this type a single order may contain.\n\t * @example 6\n\t */\n\tmaxPerOrder?: number;\n\t/**\n\t * MinPerOrder appears only when it is a real constraint (> 1) — the\n\t * limit applies to orders that include this type at all.\n\t * @example 1\n\t */\n\tminPerOrder?: number;\n\t/**\n\t * Name is the ticket type's display label.\n\t * @example \"VIP\"\n\t */\n\tname?: string;\n\t/**\n\t * PriceCents is the unit price in the event's currency's minor units.\n\t * @example 149000\n\t */\n\tpriceCents?: number;\n\t/**\n\t * Pros are short selling points for this ticket type, shown as a checklist.\n\t * @uniqueItems false\n\t * @example [\"Best view\",\"Dedicated bar\",\"Fast-track entry\"]\n\t */\n\tpros?: string[];\n\t/**\n\t * SaleEndTime is when this type stops selling (RFC 3339), if scheduled.\n\t * @example \"2026-06-20T16:00:00Z\"\n\t */\n\tsaleEndTime?: string;\n\t/**\n\t * SaleStartTime is when this type goes on sale (RFC 3339), if scheduled.\n\t * @example \"2026-01-15T10:00:00Z\"\n\t */\n\tsaleStartTime?: string;\n}\n","// Live availability over websocket: {\"event\":\"startstate\"|\"seat\", data}.\n// Startstate re-fires on every reconnect, so consumers treat it as the\n// resync point and apply deltas on top.\nimport type { DtoPublicAvailability } from './generated/api.js';\n\n/** One seat changing state. \"reserved\" appears only when the event shares\n * reserved status publicly — a reserved seat may free up again. */\nexport interface SeatDelta {\n\tseatId: string;\n\ttaken: boolean;\n\tstatus: 'free' | 'reserved' | 'taken';\n}\n\nexport interface LiveHandlers {\n\t/** Full snapshot — on connect and on every reconnect. */\n\tonStartstate?: (availability: DtoPublicAvailability) => void;\n\t/** One seat changed. */\n\tonSeat?: (delta: SeatDelta) => void;\n\t/** Connection state changes (drive a \"live\" indicator if you like). */\n\tonConnectionChange?: (connected: boolean) => void;\n}\n\nconst INITIAL_BACKOFF_MS = 1000;\nconst MAX_BACKOFF_MS = 15000;\n\nexport class LiveSubscription {\n\t#url: string;\n\t#handlers: LiveHandlers;\n\t#ws: WebSocket | null = null;\n\t#backoff = INITIAL_BACKOFF_MS;\n\t#retry: ReturnType<typeof setTimeout> | null = null;\n\t#closed = false;\n\n\tconstructor(url: string, handlers: LiveHandlers) {\n\t\tthis.#url = url.replace(/^http/, 'ws');\n\t\tthis.#handlers = handlers;\n\t\tthis.#connect();\n\t}\n\n\tclose(): void {\n\t\tthis.#closed = true;\n\t\tif (this.#retry) clearTimeout(this.#retry);\n\t\tthis.#ws?.close();\n\t}\n\n\t#connect(): void {\n\t\tif (this.#closed) return;\n\t\tconst ws = new WebSocket(this.#url);\n\t\tthis.#ws = ws;\n\t\tws.onopen = () => {\n\t\t\tthis.#backoff = INITIAL_BACKOFF_MS;\n\t\t\tthis.#handlers.onConnectionChange?.(true);\n\t\t};\n\t\tws.onmessage = (event) => {\n\t\t\tlet message: { event?: string; data?: unknown };\n\t\t\ttry {\n\t\t\t\tmessage = JSON.parse(event.data as string);\n\t\t\t} catch {\n\t\t\t\treturn; // ignore malformed / non-JSON frames rather than throwing\n\t\t\t}\n\t\t\tif (message.event === 'startstate') {\n\t\t\t\tthis.#handlers.onStartstate?.(message.data as DtoPublicAvailability);\n\t\t\t} else if (message.event === 'seat') {\n\t\t\t\tthis.#handlers.onSeat?.(message.data as SeatDelta);\n\t\t\t}\n\t\t};\n\t\tws.onclose = () => {\n\t\t\tthis.#handlers.onConnectionChange?.(false);\n\t\t\tif (this.#closed) return;\n\t\t\t// Equal-jitter backoff: reconnect somewhere in [backoff/2, backoff) so a\n\t\t\t// mass disconnect doesn't produce a synchronized reconnect thundering herd.\n\t\t\tconst delay = this.#backoff / 2 + Math.random() * (this.#backoff / 2);\n\t\t\tthis.#retry = setTimeout(() => this.#connect(), delay);\n\t\t\tthis.#backoff = Math.min(this.#backoff * 2, MAX_BACKOFF_MS);\n\t\t};\n\t}\n}\n","// The typed core of @bookitive/js: a thin fetch wrapper over the public\n// checkout API, addressed by org + event slug. All response and payload types\n// are generated from the backend's public swagger — they cannot drift.\nimport { DtoErrorCode } from './generated/api.js';\nimport type {\n\tDtoAPIError,\n\tDtoPublicAvailability,\n\tDtoPublicEvent,\n\tDtoPublicOrder,\n\tDtoPublicOrderRequest,\n\tDtoPublicSeating,\n} from './generated/api.js';\nimport { LiveSubscription, type LiveHandlers } from './live.js';\n\nexport interface BookitiveClientOptions {\n\t/** API origin, e.g. \"https://api.bookitive.com\" (no trailing slash). */\n\tbaseUrl: string;\n\t/** Organization slug — the {org} in events.bookitive.com/{org}/{event}. */\n\torg: string;\n\t/** Event slug. */\n\tevent: string;\n\t/** Custom fetch (SSR frameworks pass their own). Defaults to global fetch. */\n\tfetch?: typeof fetch;\n}\n\n/** API failure with the backend's error envelope attached. */\nexport class BookitiveError extends Error {\n\treadonly status: number;\n\t/** The backend error code (e.g. DtoErrorCode.ErrConflict), or \"UNKNOWN\" when\n\t * the response carried no JSON envelope. */\n\treadonly type: DtoErrorCode | 'UNKNOWN';\n\n\tconstructor(status: number, body: DtoAPIError | undefined, fallback: string) {\n\t\tsuper(body?.msg ?? fallback);\n\t\tthis.name = 'BookitiveError';\n\t\tthis.status = status;\n\t\tthis.type = body?.type ?? 'UNKNOWN';\n\t}\n\n\t/** The selection raced another buyer — refresh availability and reselect. */\n\tget isConflict(): boolean {\n\t\treturn this.type === DtoErrorCode.ErrConflict || this.status === 409;\n\t}\n}\n\nexport class BookitiveClient {\n\treadonly #base: string;\n\treadonly #fetch: typeof fetch;\n\n\tconstructor(options: BookitiveClientOptions) {\n\t\tthis.#base = `${options.baseUrl.replace(/\\/$/, '')}/public/v1/orgs/${encodeURIComponent(\n\t\t\toptions.org\n\t\t)}/events/${encodeURIComponent(options.event)}`;\n\t\t// bind, or a browser's fetch throws \"Illegal invocation\" when called\n\t\t// detached from window\n\t\tthis.#fetch = options.fetch ?? ((...args) => fetch(...args));\n\t}\n\n\t/** Event identity, org branding, priced ticket types, and floor tabs. */\n\tevent(): Promise<DtoPublicEvent> {\n\t\treturn this.#get<DtoPublicEvent>('');\n\t}\n\n\t/** Static chart geometry: floors → sections → tables, seats, GA areas. */\n\tseating(): Promise<DtoPublicSeating> {\n\t\treturn this.#get<DtoPublicSeating>('/seating');\n\t}\n\n\t/** Live sellability snapshot (poll it, or use live() for push updates). */\n\tavailability(): Promise<DtoPublicAvailability> {\n\t\treturn this.#get<DtoPublicAvailability>('/availability');\n\t}\n\n\t/**\n\t * Places a bank-transfer reservation: seats are held atomically for the\n\t * event's hold TTL and payment instructions are emailed (and returned).\n\t * A 409 (error.isConflict) means a seat was just taken — refresh and\n\t * reselect.\n\t */\n\tasync checkout(order: DtoPublicOrderRequest): Promise<DtoPublicOrder> {\n\t\tconst res = await this.#fetch(`${this.#base}/orders`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify(order),\n\t\t});\n\t\treturn this.#parse<DtoPublicOrder>(res, 'checkout failed');\n\t}\n\n\t/**\n\t * Subscribes to live availability over websocket: `startstate` fires with\n\t * the full snapshot on every (re)connect, then `seat` deltas stream in.\n\t * Reconnects automatically with backoff; call close() when done.\n\t */\n\tlive(handlers: LiveHandlers): LiveSubscription {\n\t\treturn new LiveSubscription(`${this.#base}/live`, handlers);\n\t}\n\n\tasync #get<T>(path: string): Promise<T> {\n\t\tconst res = await this.#fetch(`${this.#base}${path}`);\n\t\treturn this.#parse<T>(res, `request failed: ${path || '/'}`);\n\t}\n\n\tasync #parse<T>(res: Response, fallback: string): Promise<T> {\n\t\tif (!res.ok) {\n\t\t\tlet body: DtoAPIError | undefined;\n\t\t\ttry {\n\t\t\t\tbody = (await res.json()) as DtoAPIError;\n\t\t\t} catch {\n\t\t\t\t// non-JSON error body — the fallback message covers it\n\t\t\t}\n\t\t\tthrow new BookitiveError(res.status, body, fallback);\n\t\t}\n\t\t// No content (204) or an explicitly empty body — don't call res.json(),\n\t\t// which would throw on an empty stream.\n\t\tif (res.status === 204 || res.headers.get('content-length') === '0') {\n\t\t\treturn undefined as T;\n\t\t}\n\t\treturn (await res.json()) as T;\n\t}\n}\n"],"mappings":"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","names":["DtoErrorCode"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bookitive/js",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Typed client for the Bookitive public checkout API — event info, seating, live availability, and orders.",
5
5
  "license": "MIT",
6
6
  "type": "module",