@seatlayer/js 0.10.2 → 0.12.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/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { PickerSeat, SeatHoverDetails } from '@seatlayer/core';
2
- export { SeatHoverDetails } from '@seatlayer/core';
1
+ import { PickerSeat, SeatHoverDetails, ChartDoc, ChartTheme, ExpandedSeat } from '@seatlayer/core';
2
+ export { ExpandedSeat, SeatHoverDetails } from '@seatlayer/core';
3
3
 
4
4
  /**
5
5
  * Minimal client for the public embed surface of workers/api (the `/pub/*`
@@ -575,4 +575,450 @@ declare class SeatPicker {
575
575
  destroy(): void;
576
576
  }
577
577
 
578
- export { ApiError, type BestAvailableResult, type CheckoutHandoff, type CheckoutLineItem, EmbeddedDesigner, type EmbeddedDesignerEventType, type EmbeddedDesignerMessage, type EmbeddedDesignerOptions, type GAAreaAvailability, type HoldConflict, type HoldLineItem, type HoldResult, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedSeat };
578
+ /**
579
+ * Organizer manage-surface client for workers/api (the `/v1/events/:key/*`
580
+ * inventory routes + the public realtime channel). Companion to api.ts (the
581
+ * buyer `/pub/*` client) — kept separate because the manage surface is
582
+ * token-authed (Bearer) and cross-origin from the CMS:
583
+ *
584
+ * - Writes + reports send `Authorization: Bearer <token>` where the token is
585
+ * a short-lived, event-scoped organizer manage token (`mse_…`, minted by
586
+ * NestJS) OR a tenant secret key (`sk_…`). Both are accepted by the worker's
587
+ * `eitherAuth` on block / unblock / unblock-all / unbook / hold-ttl / report
588
+ * / log. The Authorization header also exempts the call from the worker's
589
+ * cookie-CSRF gate, so no extra client header is needed.
590
+ * - `credentials: 'omit'` — there is no session cookie; the CMS runs
591
+ * cross-origin. The worker's credentialed CORS still echoes the CMS origin.
592
+ * - Realtime read (`/pub/events/:key/subscribe`, `/objects`, `/chart`) is
593
+ * PUBLIC (wildcard CORS, no token) — the live board subscribes with no auth.
594
+ *
595
+ * `box-book` is intentionally omitted for M1 (box office ships in M2, and the
596
+ * route is still session-only server-side).
597
+ */
598
+
599
+ declare class ManageApiError extends Error {
600
+ status: number;
601
+ code?: string;
602
+ /** Present when a block/unbook 409s because seats were just taken. */
603
+ conflicts?: {
604
+ label: string;
605
+ reason?: string;
606
+ }[];
607
+ constructor(status: number, message: string, code?: string, conflicts?: {
608
+ label: string;
609
+ reason?: string;
610
+ }[]);
611
+ }
612
+ interface ReportByStatus {
613
+ free: number;
614
+ held: number;
615
+ booked: number;
616
+ not_for_sale: number;
617
+ }
618
+ interface ReportCategoryRow {
619
+ category: string;
620
+ total: number;
621
+ free: number;
622
+ held: number;
623
+ booked: number;
624
+ not_for_sale: number;
625
+ /** Exact sum of booked unit_price snapshots, in major currency units. */
626
+ bookedRevenue: number;
627
+ }
628
+ interface ReportCategoryMeta {
629
+ key: string;
630
+ label: string;
631
+ color: string;
632
+ price: number;
633
+ }
634
+ interface ReportResult {
635
+ report: {
636
+ byStatus: ReportByStatus;
637
+ byCategory: ReportCategoryRow[];
638
+ bySection?: ControlRoomSectionMetric[];
639
+ };
640
+ event: {
641
+ key: string;
642
+ name: string;
643
+ seatTotal: number;
644
+ currency?: string;
645
+ };
646
+ categories: ReportCategoryMeta[];
647
+ }
648
+ interface ControlRoomSectionMetric {
649
+ sectionId: string;
650
+ sectionLabel: string;
651
+ zoneId: string | null;
652
+ total: number;
653
+ free: number;
654
+ held: number;
655
+ booked: number;
656
+ not_for_sale: number;
657
+ bookedRevenue: number;
658
+ }
659
+ interface ControlRoomSnapshot {
660
+ version: number;
661
+ currency: string;
662
+ totals: {
663
+ free: number;
664
+ held: number;
665
+ booked: number;
666
+ blocked: number;
667
+ };
668
+ revenue: {
669
+ gross: number;
670
+ bySection: ControlRoomSectionMetric[];
671
+ };
672
+ velocity: {
673
+ windowMinutes: number;
674
+ bySection: Array<{
675
+ sectionId: string;
676
+ netBooked: number;
677
+ grossRevenue: number;
678
+ previousNetBooked: number;
679
+ trend: 'rising' | 'steady' | 'cooling';
680
+ }>;
681
+ };
682
+ presence: {
683
+ shoppingSessions: number;
684
+ activeHolds: number;
685
+ };
686
+ event: {
687
+ key: string;
688
+ name: string;
689
+ seatTotal: number;
690
+ currency?: string;
691
+ };
692
+ }
693
+ interface LogEntry {
694
+ id: number;
695
+ at: number;
696
+ action: string;
697
+ labels: string[];
698
+ ref: string | null;
699
+ }
700
+ interface LogPage {
701
+ entries: LogEntry[];
702
+ nextBefore: number | null;
703
+ }
704
+ interface PubObjectsResult {
705
+ /** Every non-free seat's status keyed by label (free seats omitted). */
706
+ seats: Record<string, string>;
707
+ hidden?: string[];
708
+ closed?: string[];
709
+ updatedAt: number;
710
+ }
711
+ interface PubChartResult {
712
+ event: {
713
+ key: string;
714
+ name: string;
715
+ status?: string;
716
+ venue?: string | null;
717
+ startsAt?: number | null;
718
+ currency?: string;
719
+ mode?: string;
720
+ };
721
+ doc: ChartDoc;
722
+ }
723
+ /**
724
+ * Bound to one apiBase + one event-scoped token. Rebuild (or `setToken`) when a
725
+ * token is re-minted on 401.
726
+ */
727
+ declare class ManageApi {
728
+ private base;
729
+ private token;
730
+ constructor(apiBase: string, token: string);
731
+ /** Swap the Bearer token in place (SeatManager re-mints on 401). */
732
+ setToken(token: string): void;
733
+ private auth;
734
+ private pub;
735
+ chart(key: string): Promise<PubChartResult>;
736
+ objects(key: string): Promise<PubObjectsResult>;
737
+ socketUrl(key: string): string;
738
+ /** Take FREE seats off sale in one batched call. Optional `releaseAt` (epoch
739
+ * ms, future) auto-returns them to sale; `reason` tags the block (M3 uses it).
740
+ * Throws ManageApiError 409 (conflicts) if any seat was just taken. */
741
+ block(key: string, labels: string[], opts?: {
742
+ releaseAt?: number;
743
+ reason?: string;
744
+ }): Promise<{
745
+ ok: true;
746
+ blocked: string[];
747
+ }>;
748
+ /** Return specific blocked seats to sale (one batched call). */
749
+ unblock(key: string, labels: string[]): Promise<{
750
+ ok: true;
751
+ unblocked: string[];
752
+ }>;
753
+ /** Return every blocked seat to sale; resolves with the freed count. */
754
+ unblockAll(key: string): Promise<{
755
+ ok: true;
756
+ freed: number;
757
+ }>;
758
+ /** Cancel bookings — return BOOKED seats to free (credit not refunded).
759
+ * Guarded by the original booking reference. */
760
+ unbook(key: string, labels: string[], bookingRef: string): Promise<{
761
+ ok: true;
762
+ unbooked: string[];
763
+ }>;
764
+ /** Set (ms, clamped 1–60 min server-side) or clear (null) the hold TTL. */
765
+ setHoldTtl(key: string, holdTtlMs: number | null): Promise<{
766
+ ok: true;
767
+ holdTtlMs: number | null;
768
+ }>;
769
+ report(key: string): Promise<ReportResult>;
770
+ controlRoom(key: string, windowMinutes?: number): Promise<ControlRoomSnapshot>;
771
+ log(key: string, opts?: {
772
+ limit?: number;
773
+ before?: number;
774
+ }): Promise<LogPage>;
775
+ /** CSV report as a Blob (Bearer auth can't ride a plain <a href>). Host builds
776
+ * an object URL for download. */
777
+ reportCsv(key: string): Promise<Blob>;
778
+ }
779
+
780
+ /**
781
+ * SeatManager — the organizer manage surface, packaged for the SDK.
782
+ *
783
+ * Productizes the SeatLayer dashboard's ManageEventPage into a framework-
784
+ * agnostic class (mirrors how SeatPicker productized the buyer flow). It mounts
785
+ * the shared engine in `manageMode`, subscribes to the event's realtime channel
786
+ * and drives three control-room tools on one persistent canvas:
787
+ *
788
+ * - **view** — a live board: realtime seat repaint (flash on hold/book),
789
+ * live KPI tallies + gross revenue, and a streaming activity
790
+ * feed derived from the delta stream + audit log. Read-only.
791
+ * - **inspect** — select one seat to read its live inventory context.
792
+ * - **block** — bulk-first block/unblock: marquee-drag, ⌘A select-all,
793
+ * whole-category / whole-section select, single-seat fallback →
794
+ * one batched block/unblock (optimistic, reconciled by the WS),
795
+ * and timed auto-release.
796
+ *
797
+ * Auth: reads (chart/objects/WS) are public; writes/reports carry a Bearer
798
+ * event-scoped manage token (`mse_…`) or a tenant secret key (`sk_…`) via
799
+ * {@link ManageApi}. Box office + Sections + full Reports UI are M2/M3.
800
+ */
801
+
802
+ type SeatManagerMode = 'view' | 'inspect' | 'block';
803
+ /** DO seat status — 'blocked' has no engine analogue (→ 'not_for_sale'). */
804
+ type DoStatus = 'free' | 'held' | 'booked' | 'blocked';
805
+ /** Live KPI snapshot pushed to `onTallies` on every state change. */
806
+ interface SeatManagerTallies {
807
+ free: number;
808
+ held: number;
809
+ booked: number;
810
+ blocked: number;
811
+ /** Total seats on the chart. */
812
+ total: number;
813
+ /** booked / total, 0–100. */
814
+ capacityPct: number;
815
+ /** booked / (total − blocked), 0–100 — sell-through of sellable inventory. */
816
+ sellThroughPct: number;
817
+ /** Exact Σ booked unit_price snapshots from the authenticated report. */
818
+ grossRevenue: number;
819
+ /** Revenue is never reconstructed from chart list price. */
820
+ revenueStatus: 'loading' | 'current' | 'stale';
821
+ /** ISO-4217 currency for grossRevenue. */
822
+ currency: string;
823
+ }
824
+ /** One streamed activity line for the live feed. */
825
+ interface SeatManagerActivity {
826
+ id: string;
827
+ at: number;
828
+ label: string;
829
+ /** Full labels affected by this one backend/realtime operation. */
830
+ labels: string[];
831
+ count: number;
832
+ /** Human verb: held / booked / released / blocked / unblocked. */
833
+ verb: string;
834
+ status: DoStatus;
835
+ }
836
+ /** Fired after a successful organizer action, for host toasts/telemetry. */
837
+ interface SeatManagerActionResult {
838
+ action: 'block' | 'unblock' | 'unblockAll' | 'cancelBooking' | 'setHoldTtl';
839
+ labels: string[];
840
+ count: number;
841
+ }
842
+ interface SeatManagerOptions {
843
+ /** CSS selector or element to mount into. */
844
+ container: string | HTMLElement;
845
+ /** API origin. Defaults to https://api.seatlayer.io. */
846
+ apiBase?: string;
847
+ /** Event key (e.g. `ev_xxx` / `west-end-p3`). */
848
+ eventKey: string;
849
+ /** Bearer manage token — event-scoped `mse_…` or a tenant secret `sk_…`. */
850
+ token: string;
851
+ /** Absolute token expiry (epoch ms). Enables proactive in-place rotation. */
852
+ tokenExpiresAt?: number;
853
+ /** Initial mode. Default 'view'. */
854
+ mode?: SeatManagerMode;
855
+ /** ISO-4217 fallback currency for revenue (chart/event currency wins). */
856
+ currency?: string;
857
+ /** Chart theme override for the chrome (rails/bar). Chart colors come from the doc. */
858
+ theme?: ChartTheme;
859
+ /**
860
+ * Keep the canvas painting even when the tab is hidden/backgrounded (a war-room
861
+ * board on a second monitor). Calls `forceDraw()` after each delta so Chrome's
862
+ * rAF throttling on occluded tabs never leaves the board stale. Default true.
863
+ */
864
+ keepLiveWhileHidden?: boolean;
865
+ /** Chart + first snapshot are loaded and the board is live. */
866
+ onReady?: () => void;
867
+ /** Live KPI tallies changed. */
868
+ onTallies?: (tallies: SeatManagerTallies) => void;
869
+ /** A grouped live/audit activity item arrived. */
870
+ onActivity?: (activity: SeatManagerActivity) => void;
871
+ /** Exact private control-room projection changed. */
872
+ onControlRoom?: (snapshot: ControlRoomSnapshot) => void;
873
+ /** Called before token expiry. The manager swaps the result without remounting. */
874
+ onTokenRefresh?: () => Promise<{
875
+ token: string;
876
+ expiresAt: number;
877
+ }>;
878
+ /** Tool/mode changed from inside the shared cockpit. */
879
+ onModeChange?: (mode: SeatManagerMode) => void;
880
+ /** Block-mode selection changed (marquee / ⌘A / category / section / tap). */
881
+ onSelectionChange?: (seats: ExpandedSeat[]) => void;
882
+ /** A block/unblock/cancel action completed successfully. */
883
+ onActionComplete?: (result: SeatManagerActionResult) => void;
884
+ onError?: (err: unknown) => void;
885
+ }
886
+ declare class SeatManager {
887
+ private readonly opts;
888
+ private readonly api;
889
+ private readonly key;
890
+ private readonly keepLive;
891
+ private host;
892
+ private root;
893
+ private mapHost;
894
+ private els;
895
+ private renderer;
896
+ private doc;
897
+ private mode;
898
+ private labelToId;
899
+ private labelToSeat;
900
+ private allIds;
901
+ private status;
902
+ private currency;
903
+ private authoritativeGrossRevenue;
904
+ private revenueStatus;
905
+ private revenueRequest;
906
+ private revenueRefreshTimer;
907
+ private controlRoomSnapshot;
908
+ private trendWindowMinutes;
909
+ private heatEnabled;
910
+ private ws;
911
+ private reconnectTimer;
912
+ private attempt;
913
+ private closed;
914
+ private ready;
915
+ private feed;
916
+ private feedTimer;
917
+ private toastTimer;
918
+ private releaseAt;
919
+ private layoutObserver;
920
+ private tokenExpiresAt;
921
+ private tokenRefreshTimer;
922
+ private tokenRefreshInFlight;
923
+ private sectionByObject;
924
+ private sectionLabelById;
925
+ private lastSyncedAt;
926
+ private readonly onFullscreenChange;
927
+ private readonly onKeyDown;
928
+ constructor(options: SeatManagerOptions);
929
+ /** Build the DOM, load the chart, subscribe to realtime, mount the board. */
930
+ render(): Promise<this>;
931
+ setMode(mode: SeatManagerMode): void;
932
+ /** Toggle the normalized sales-velocity outline overlay without changing seat colors. */
933
+ setHeatOverlay(enabled: boolean): void;
934
+ /** Change the current-vs-previous sales window and refresh the private projection. */
935
+ setTrendWindow(windowMinutes: number): Promise<ControlRoomSnapshot>;
936
+ enterFullscreen(): Promise<void>;
937
+ exitFullscreen(): Promise<void>;
938
+ isFullscreen(): boolean;
939
+ private toggleFullscreen;
940
+ /** Rotate the delegated credential without rebuilding DOM, canvas or socket. */
941
+ setToken(token: string, expiresAt?: number): void;
942
+ private scheduleTokenRefresh;
943
+ private rotateToken;
944
+ /** Bulk block the given labels (or the current selection when omitted). */
945
+ block(labels?: string[], opts?: {
946
+ releaseAt?: number;
947
+ reason?: string;
948
+ }): Promise<void>;
949
+ unblock(labels?: string[]): Promise<void>;
950
+ unblockAll(): Promise<void>;
951
+ /** Cancel bookings (BOOKED → free), guarded by the original booking ref. */
952
+ cancelBooking(labels: string[], bookingRef: string): Promise<void>;
953
+ selectAll(): ExpandedSeat[];
954
+ selectSection(sectionId: string): ExpandedSeat[];
955
+ selectByLabels(labels: string[]): ExpandedSeat[];
956
+ clearSelection(): void;
957
+ getSelection(): ExpandedSeat[];
958
+ getReport(): Promise<ReportResult>;
959
+ getControlRoomSnapshot(windowMinutes?: number): Promise<ControlRoomSnapshot>;
960
+ getLog(opts?: {
961
+ limit?: number;
962
+ before?: number;
963
+ }): Promise<{
964
+ entries: LogEntry[];
965
+ nextBefore: number | null;
966
+ }>;
967
+ setHoldTtl(ms: number | null): Promise<void>;
968
+ /** M2 — box-office booking from free seats. Stubbed (route is session-only today). */
969
+ boxBook(_labels: string[], _bookingRef: string): Promise<void>;
970
+ zoomToFit(): void;
971
+ destroy(): void;
972
+ private buildRenderer;
973
+ private updateRendererInteraction;
974
+ private handleSeatSelect;
975
+ private repaintAll;
976
+ private connect;
977
+ private scheduleReconnect;
978
+ private onMessage;
979
+ private resnapshot;
980
+ private applySnapshot;
981
+ /** Optimistic local write shared by delta stream + organizer actions. */
982
+ private setSeatLocal;
983
+ /** Keep the canvas painting on hidden/occluded tabs (war-room second monitor). */
984
+ private afterPaint;
985
+ private flash;
986
+ private applyReportRevenue;
987
+ private refreshControlRoom;
988
+ private scheduleRevenueRefresh;
989
+ private recomputeTallies;
990
+ private verbFor;
991
+ private pushActivity;
992
+ private seedFeed;
993
+ private startFeedClock;
994
+ private selectionLabels;
995
+ private syncSelection;
996
+ private buildChrome;
997
+ private updateContainerLayout;
998
+ private sectionOptions;
999
+ private buildSectionOptions;
1000
+ private paintModeTabs;
1001
+ private paintHeatButton;
1002
+ private paintFullscreenButton;
1003
+ private paintTrendWindow;
1004
+ private setLive;
1005
+ private updateZoomHint;
1006
+ private paintKpis;
1007
+ private paintRail;
1008
+ private renderViewRail;
1009
+ private paintMonitorInsights;
1010
+ private applyHeatOverlay;
1011
+ private renderInspectRail;
1012
+ private paintLegend;
1013
+ private paintFeed;
1014
+ private renderBlockRail;
1015
+ private selectCategory;
1016
+ private paintSelBar;
1017
+ private done;
1018
+ private toastOk;
1019
+ private toastErr;
1020
+ private toast;
1021
+ private fail;
1022
+ }
1023
+
1024
+ export { ApiError, type BestAvailableResult, type CheckoutHandoff, type CheckoutLineItem, type ControlRoomSectionMetric, type ControlRoomSnapshot, EmbeddedDesigner, type EmbeddedDesignerEventType, type EmbeddedDesignerMessage, type EmbeddedDesignerOptions, type GAAreaAvailability, type HoldConflict, type HoldLineItem, type HoldResult, type LogEntry, type LogPage, ManageApi, ManageApiError, type ReportByStatus, type ReportCategoryMeta, type ReportCategoryRow, type ReportResult, SeatManager, type SeatManagerActionResult, type SeatManagerActivity, type SeatManagerMode, type SeatManagerOptions, type SeatManagerTallies, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedSeat };