@seatlayer/js 0.36.2 → 0.36.3
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.cjs +594 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +233 -2
- package/dist/index.d.ts +233 -2
- package/dist/index.js +589 -9
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -2029,6 +2029,100 @@ declare function retryAfterCopy(details: ArchiveBlockedDetails | null | undefine
|
|
|
2029
2029
|
declare function accessLine(access: ChannelAccessSummary | null | undefined): string;
|
|
2030
2030
|
/** Plain-language label for the access-intent control. */
|
|
2031
2031
|
declare function accessIntentLabel(intent: ChannelAccessIntent): string;
|
|
2032
|
+
/** Lifecycle the server stores. `rotated` means a newer link replaced this one. */
|
|
2033
|
+
type AccessLinkState = 'active' | 'revoked' | 'rotated';
|
|
2034
|
+
/** What the organizer surface renders: `state`, unless an active link has run
|
|
2035
|
+
* out of time or out of redemptions. Never a capability, never a hash. */
|
|
2036
|
+
type AccessLinkStatus = AccessLinkState | 'expired' | 'exhausted';
|
|
2037
|
+
/**
|
|
2038
|
+
* One hosted link, exactly as `GET …/access-links` projects it.
|
|
2039
|
+
*
|
|
2040
|
+
* There is deliberately NO `url` and NO `capability` field here — the listing
|
|
2041
|
+
* route does not return them, no other route returns them, and this type must
|
|
2042
|
+
* not tempt a caller into believing otherwise. The secret exists in exactly one
|
|
2043
|
+
* place for exactly one moment: the create/rotate response (`AccessLinkReveal`).
|
|
2044
|
+
*/
|
|
2045
|
+
interface AccessLinkRecord {
|
|
2046
|
+
id: string;
|
|
2047
|
+
channelId: string;
|
|
2048
|
+
label: string | null;
|
|
2049
|
+
includePublic: boolean;
|
|
2050
|
+
expiresAt: number;
|
|
2051
|
+
maxRedemptions: number;
|
|
2052
|
+
redemptions: number;
|
|
2053
|
+
/** Guest-weighted per-buyer ceiling handed to every session this link mints. */
|
|
2054
|
+
maxQuantity: number;
|
|
2055
|
+
sessionTtlSeconds: number;
|
|
2056
|
+
state: AccessLinkState;
|
|
2057
|
+
status: AccessLinkStatus;
|
|
2058
|
+
createdAt: number;
|
|
2059
|
+
createdBy: string | null;
|
|
2060
|
+
revokedAt: number | null;
|
|
2061
|
+
lastRedeemedAt: number | null;
|
|
2062
|
+
/** Rotation lineage: the link this replaced, and the one that replaced it. */
|
|
2063
|
+
rotatedFrom: string | null;
|
|
2064
|
+
rotatedTo: string | null;
|
|
2065
|
+
}
|
|
2066
|
+
/** A listed link, with the live session count the rotate dialog needs to state
|
|
2067
|
+
* "N buyers got in with this link and still have access". */
|
|
2068
|
+
interface AccessLinkStatusRecord extends AccessLinkRecord {
|
|
2069
|
+
activeSessions?: number;
|
|
2070
|
+
}
|
|
2071
|
+
/**
|
|
2072
|
+
* The ONE-TIME reveal. `url` and `capability` are on the wire exactly once, in
|
|
2073
|
+
* the create/rotate response, and are unrecoverable afterwards: SeatLayer stores
|
|
2074
|
+
* only a hash. Nothing may persist this — see `ChannelsMode.revealLink`.
|
|
2075
|
+
*/
|
|
2076
|
+
interface AccessLinkReveal {
|
|
2077
|
+
link: AccessLinkRecord;
|
|
2078
|
+
url: string;
|
|
2079
|
+
capability: string;
|
|
2080
|
+
revealedOnce: true;
|
|
2081
|
+
/** Rotation only: the link that just stopped working, and how many live buyer
|
|
2082
|
+
* sessions from it were ended (0 when the organizer let them finish). */
|
|
2083
|
+
previous?: AccessLinkRecord;
|
|
2084
|
+
endedSessions?: number;
|
|
2085
|
+
}
|
|
2086
|
+
/**
|
|
2087
|
+
* Owner-set defaults for a new link. Expiry is NOT here: "when the event starts"
|
|
2088
|
+
* is the server's own default (it knows `starts_at`; the cockpit does not), so
|
|
2089
|
+
* the create form expresses that choice by omitting `expiresAt` entirely rather
|
|
2090
|
+
* than by guessing a timestamp the server would then have to correct.
|
|
2091
|
+
*/
|
|
2092
|
+
declare const ACCESS_LINK_DEFAULTS: {
|
|
2093
|
+
readonly maxRedemptions: 100;
|
|
2094
|
+
readonly maxQuantity: 4;
|
|
2095
|
+
};
|
|
2096
|
+
/** Plain-language state badge for a hosted link (§9: no internal vocabulary). */
|
|
2097
|
+
declare function accessLinkBadge(link: Pick<AccessLinkRecord, 'status' | 'state'>): {
|
|
2098
|
+
text: string;
|
|
2099
|
+
kind: 'active' | 'paused' | 'archived';
|
|
2100
|
+
};
|
|
2101
|
+
/** Only an `active` link can be rotated or revoked; the server agrees (409
|
|
2102
|
+
* `access_link_not_active`), so the buttons are absent rather than failing. */
|
|
2103
|
+
declare function accessLinkIsLive(link: Pick<AccessLinkRecord, 'status' | 'state'>): boolean;
|
|
2104
|
+
/**
|
|
2105
|
+
* The policy an organizer is agreeing to, in one list. Used by BOTH the reveal
|
|
2106
|
+
* (what you just created) and the status card (what is live), so the two can
|
|
2107
|
+
* never drift into describing the same link differently.
|
|
2108
|
+
*/
|
|
2109
|
+
declare function accessLinkPolicyLines(link: AccessLinkRecord): Array<{
|
|
2110
|
+
k: string;
|
|
2111
|
+
v: string;
|
|
2112
|
+
}>;
|
|
2113
|
+
/**
|
|
2114
|
+
* Plain language for a refused hosted-link call.
|
|
2115
|
+
*
|
|
2116
|
+
* The PLATFORM BOUNDS live on the server (60s–180d expiry, 1–10 000 redemptions,
|
|
2117
|
+
* 1–100 seats per buyer, 20 live links per channel) and the server states them
|
|
2118
|
+
* in `message`. We surface that sentence rather than re-encoding the numbers
|
|
2119
|
+
* here, so the client can never disagree with the rule it is reporting.
|
|
2120
|
+
*/
|
|
2121
|
+
declare function accessLinkErrorCopy(err: {
|
|
2122
|
+
code?: string;
|
|
2123
|
+
serverMessage?: string;
|
|
2124
|
+
status?: number;
|
|
2125
|
+
} | null | undefined): string;
|
|
2032
2126
|
/**
|
|
2033
2127
|
* The chart-update refusal `channel_assignment_would_drop` (409) deliberately
|
|
2034
2128
|
* mirrors the Apply skipped buckets, so ONE review component renders both.
|
|
@@ -2143,10 +2237,17 @@ declare class ManageApiError extends Error {
|
|
|
2143
2237
|
* `channel_assignment_conflict` carries the current assignmentVersion.
|
|
2144
2238
|
*/
|
|
2145
2239
|
details?: Record<string, unknown>;
|
|
2240
|
+
/**
|
|
2241
|
+
* The server's own human sentence, when it sent one. `message` is the machine
|
|
2242
|
+
* code (that is what `error` carries), so a UI that wants to state a PLATFORM
|
|
2243
|
+
* RULE — "redemptions must be between 1 and 10 000" — reads this instead of
|
|
2244
|
+
* re-encoding the bound locally and risking disagreement with the server.
|
|
2245
|
+
*/
|
|
2246
|
+
serverMessage?: string;
|
|
2146
2247
|
constructor(status: number, message: string, code?: string, conflicts?: {
|
|
2147
2248
|
label: string;
|
|
2148
2249
|
reason?: string;
|
|
2149
|
-
}[], details?: Record<string, unknown
|
|
2250
|
+
}[], details?: Record<string, unknown>, serverMessage?: string);
|
|
2150
2251
|
}
|
|
2151
2252
|
interface ReportByStatus {
|
|
2152
2253
|
free: number;
|
|
@@ -2437,6 +2538,53 @@ declare class ManageApi {
|
|
|
2437
2538
|
ok: true;
|
|
2438
2539
|
channel: ChannelRecord;
|
|
2439
2540
|
}>;
|
|
2541
|
+
/**
|
|
2542
|
+
* Mint a hosted access link. The 201 is the ONE and ONLY time `url` and
|
|
2543
|
+
* `capability` exist outside the buyer's browser — SeatLayer keeps a hash, so
|
|
2544
|
+
* there is no route, cache, or support escalation that can produce this string
|
|
2545
|
+
* again. Callers must reveal it immediately and then let it go.
|
|
2546
|
+
*
|
|
2547
|
+
* Every omitted field takes the server's default: expiry = when the event
|
|
2548
|
+
* starts, 100 redemptions, 4 seats per buyer, this channel's allocation only.
|
|
2549
|
+
* Platform bounds are enforced server-side and reported as 422 with the rule
|
|
2550
|
+
* spelled out in `ManageApiError.serverMessage`.
|
|
2551
|
+
*
|
|
2552
|
+
* Side effect by design: this also declares the channel's access intent as
|
|
2553
|
+
* `hosted_link`, so the rail stops saying "no buyer access configured".
|
|
2554
|
+
*/
|
|
2555
|
+
createAccessLink(key: string, channelId: string, input?: {
|
|
2556
|
+
label?: string | null;
|
|
2557
|
+
/** Absolute epoch ms. Omit for "when the event starts". */
|
|
2558
|
+
expiresAt?: number;
|
|
2559
|
+
maxRedemptions?: number;
|
|
2560
|
+
maxQuantity?: number;
|
|
2561
|
+
includePublic?: boolean;
|
|
2562
|
+
}): Promise<AccessLinkReveal>;
|
|
2563
|
+
/** Status only — label, expiry, redemptions, per-buyer cap, lineage, and the
|
|
2564
|
+
* live session count. Never the url, never the capability. Needs `:view`. */
|
|
2565
|
+
accessLinks(key: string, channelId: string): Promise<{
|
|
2566
|
+
links: AccessLinkStatusRecord[];
|
|
2567
|
+
}>;
|
|
2568
|
+
/**
|
|
2569
|
+
* Rotate — the ONLY recovery for a link nobody kept. The old URL stops opening
|
|
2570
|
+
* immediately and the response is a fresh one-time reveal.
|
|
2571
|
+
*
|
|
2572
|
+
* `endActiveSessions` is REQUIRED, not defaulted: the organizer must say
|
|
2573
|
+
* whether buyers already inside finish their checkout or lose access now. The
|
|
2574
|
+
* server answers 422 `end_active_sessions_required` if it is omitted, and that
|
|
2575
|
+
* refusal is correct — a UI must not pick either branch on their behalf.
|
|
2576
|
+
*/
|
|
2577
|
+
rotateAccessLink(key: string, channelId: string, linkId: string, endActiveSessions: boolean): Promise<AccessLinkReveal & {
|
|
2578
|
+
previous: AccessLinkRecord;
|
|
2579
|
+
endedSessions: number;
|
|
2580
|
+
}>;
|
|
2581
|
+
/** Revoke. The link stops opening immediately; `endActiveSessions` decides
|
|
2582
|
+
* whether the buyers already inside keep their sessions. */
|
|
2583
|
+
revokeAccessLink(key: string, channelId: string, linkId: string, endActiveSessions?: boolean): Promise<{
|
|
2584
|
+
ok: true;
|
|
2585
|
+
link: AccessLinkRecord;
|
|
2586
|
+
endedSessions: number;
|
|
2587
|
+
}>;
|
|
2440
2588
|
report(key: string): Promise<ReportResult>;
|
|
2441
2589
|
controlRoom(key: string, windowMinutes?: number): Promise<ControlRoomSnapshot>;
|
|
2442
2590
|
log(key: string, opts?: {
|
|
@@ -2918,6 +3066,26 @@ interface ChannelsClient {
|
|
|
2918
3066
|
ok: true;
|
|
2919
3067
|
channel: ChannelRecord;
|
|
2920
3068
|
}>;
|
|
3069
|
+
/** 201 with the ONE-TIME reveal. Every omitted field takes the server default
|
|
3070
|
+
* (expiry = event start, 100 redemptions, 4 seats per buyer). */
|
|
3071
|
+
createAccessLink(key: string, channelId: string, input: {
|
|
3072
|
+
label?: string | null;
|
|
3073
|
+
expiresAt?: number;
|
|
3074
|
+
maxRedemptions?: number;
|
|
3075
|
+
maxQuantity?: number;
|
|
3076
|
+
includePublic?: boolean;
|
|
3077
|
+
}): Promise<AccessLinkReveal>;
|
|
3078
|
+
/** Status only. This response has no url and no capability, by contract. */
|
|
3079
|
+
accessLinks(key: string, channelId: string): Promise<{
|
|
3080
|
+
links: AccessLinkStatusRecord[];
|
|
3081
|
+
}>;
|
|
3082
|
+
/** `endActiveSessions` is required — the server 422s without it, deliberately. */
|
|
3083
|
+
rotateAccessLink(key: string, channelId: string, linkId: string, endActiveSessions: boolean): Promise<AccessLinkReveal>;
|
|
3084
|
+
revokeAccessLink(key: string, channelId: string, linkId: string, endActiveSessions?: boolean): Promise<{
|
|
3085
|
+
ok: true;
|
|
3086
|
+
link: unknown;
|
|
3087
|
+
endedSessions: number;
|
|
3088
|
+
}>;
|
|
2921
3089
|
}
|
|
2922
3090
|
interface ChannelsCapabilities {
|
|
2923
3091
|
view: boolean;
|
|
@@ -2996,6 +3164,15 @@ declare class ChannelsMode {
|
|
|
2996
3164
|
private dialog;
|
|
2997
3165
|
private detent;
|
|
2998
3166
|
private seatListLimit;
|
|
3167
|
+
/**
|
|
3168
|
+
* Hosted-link STATUS for the channel whose detail panel is open. This is the
|
|
3169
|
+
* listing projection — it carries no url and no capability, because no route
|
|
3170
|
+
* returns one. `unsupported` is the honest answer for a worker that predates
|
|
3171
|
+
* M8, exactly like the buyer-preview probe.
|
|
3172
|
+
*/
|
|
3173
|
+
private links;
|
|
3174
|
+
private linksChannelId;
|
|
3175
|
+
private linksState;
|
|
2999
3176
|
private previewAudience;
|
|
3000
3177
|
private previewIncludePublic;
|
|
3001
3178
|
private previewProjection;
|
|
@@ -3079,6 +3256,23 @@ declare class ChannelsMode {
|
|
|
3079
3256
|
private listRailHtml;
|
|
3080
3257
|
private selectionRailHtml;
|
|
3081
3258
|
private detailRailHtml;
|
|
3259
|
+
/**
|
|
3260
|
+
* Read the status projection for the open channel. Never paints — the caller
|
|
3261
|
+
* decides when the rail repaints, so a poll-driven reload does not fight a
|
|
3262
|
+
* user-driven one. A worker without M8 answers 404/405 and gets the honest
|
|
3263
|
+
* "needs a newer server" line rather than an error toast.
|
|
3264
|
+
*/
|
|
3265
|
+
private loadLinks;
|
|
3266
|
+
/**
|
|
3267
|
+
* The hosted-link section of the detail panel.
|
|
3268
|
+
*
|
|
3269
|
+
* STATUS ONLY, by design (comp 06 `hosted`): label, state, expiry,
|
|
3270
|
+
* redemptions, seats per buyer, live sessions. There is no Copy control here
|
|
3271
|
+
* and no field to hang one on — the URL was shown once at creation and cannot
|
|
3272
|
+
* be produced again. Rotation is the recovery path, and it says so.
|
|
3273
|
+
*/
|
|
3274
|
+
private hostedLinksHtml;
|
|
3275
|
+
private linkCardHtml;
|
|
3082
3276
|
private previewRailHtml;
|
|
3083
3277
|
private paintSelection;
|
|
3084
3278
|
private wireRail;
|
|
@@ -3119,6 +3313,43 @@ declare class ChannelsMode {
|
|
|
3119
3313
|
* per-section select actions.
|
|
3120
3314
|
*/
|
|
3121
3315
|
private renderSeatListDialog;
|
|
3316
|
+
private reloadLinks;
|
|
3317
|
+
private linkById;
|
|
3318
|
+
/**
|
|
3319
|
+
* Create. The three policy fields carry the owner's defaults and every one of
|
|
3320
|
+
* them is editable; the PLATFORM bounds (60s–180d, 1–10 000, 1–100, 20 live
|
|
3321
|
+
* links) are the server's to enforce and the server's to explain, so this form
|
|
3322
|
+
* checks only that a number is a number and surfaces the server's sentence for
|
|
3323
|
+
* everything else.
|
|
3324
|
+
*/
|
|
3325
|
+
private renderLinkCreateDialog;
|
|
3326
|
+
private createLink;
|
|
3327
|
+
/**
|
|
3328
|
+
* The ONE-TIME reveal.
|
|
3329
|
+
*
|
|
3330
|
+
* Three things make this unrecoverable rather than merely "not shown twice":
|
|
3331
|
+
*
|
|
3332
|
+
* 1. `url` is a local const. It is never assigned to a field on this class,
|
|
3333
|
+
* never handed to the host, never put in a `DialogState`.
|
|
3334
|
+
* 2. `this.dialog` is cleared FIRST, so `renderDialog()` — the only function
|
|
3335
|
+
* that rebuilds a sheet — has nothing to rebuild this one from.
|
|
3336
|
+
* 3. The string exists in exactly one DOM node inside the scrim. Dismissing
|
|
3337
|
+
* the dialog removes the scrim, and the closure goes with it.
|
|
3338
|
+
*
|
|
3339
|
+
* The server holds only a hash, so even a compromised client cannot ask for it
|
|
3340
|
+
* again. Rotation is the recovery path, and the copy says so.
|
|
3341
|
+
*/
|
|
3342
|
+
private revealLink;
|
|
3343
|
+
/**
|
|
3344
|
+
* Rotate. The organizer must SAY what happens to the buyers already inside —
|
|
3345
|
+
* the confirm stays disabled until one of the two choices is picked, because
|
|
3346
|
+
* the gentle branch and the destructive branch are both real decisions and the
|
|
3347
|
+
* server refuses (422 `end_active_sessions_required`) to guess either.
|
|
3348
|
+
*/
|
|
3349
|
+
private renderLinkRotateDialog;
|
|
3350
|
+
private rotateLink;
|
|
3351
|
+
private renderLinkRevokeDialog;
|
|
3352
|
+
private revokeLink;
|
|
3122
3353
|
private applySheetClasses;
|
|
3123
3354
|
private cycleDetent;
|
|
3124
3355
|
/** Back/Close from the full detent returns to the previous one and keeps the
|
|
@@ -3126,4 +3357,4 @@ declare class ChannelsMode {
|
|
|
3126
3357
|
handleBack(): boolean;
|
|
3127
3358
|
}
|
|
3128
3359
|
|
|
3129
|
-
export { ApiError, type ArchiveBlockedDetails, type AssignmentBuckets, type AssignmentDropDetails, type AssignmentResult, type AttachPickerFrameOptions, type BestAvailableResult, type BucketRow, BuyerAccessContext, type BuyerAccessExpiredEvent, type BuyerAccessRefreshReason, type BuyerAccessToken, type BuyerAccessTokenProvider, BuyerAccessUnavailableError, type BuyerAccessUnavailableEvent, type BuyerAccessUnavailableReason, BuyerRealtimeClient, type BuyerRealtimeOptions, type ChannelAccessIntent, type ChannelAccessSummary, type ChannelAllocationPage, type ChannelAuditEntry, type ChannelAuditPage, type ChannelCounts, type ChannelListResult, type ChannelPreviewProjection, type ChannelRecord, type ChannelSeatStatus, type ChannelState, type ChannelsCapabilities, type ChannelsClient, ChannelsMode, type ChannelsModeHost, type ChannelsSeatView, type CheckoutHandoff, type CheckoutLineItem, type ControlRoomActivityEntry, 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, PUBLIC_CHANNEL_ID, PUBLIC_CHANNEL_NAME, type Projection, type PubApiOptions, type RealtimeSink, type ReportByStatus, type ReportCategoryMeta, type ReportCategoryRow, type ReportResult, type ResumedHoldResult, SeatManager, type SeatManagerActionResult, type SeatManagerActivity, type SeatManagerCapability, type SeatManagerMode, type SeatManagerOptions, type SeatManagerTallies, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedObjectUnavailableEvent, type SelectedSeat, type SelectionSourceRow, type StatusChange, type SubscribeTicket$1 as SubscribeTicket, accessIntentLabel, accessLine, attachPickerFrame, bucketRows, bucketRowsHtml, createBuyerAccessContext, createControllerSink, dropReviewRows, isPublicChannelId, markerLetter, markerOf, mutationCount, needsMoveConfirmation, planAssignment, retryAfterCopy, selectionSources, stateBadge, suggestMarker };
|
|
3360
|
+
export { ACCESS_LINK_DEFAULTS, type AccessLinkRecord, type AccessLinkReveal, type AccessLinkState, type AccessLinkStatus, type AccessLinkStatusRecord, ApiError, type ArchiveBlockedDetails, type AssignmentBuckets, type AssignmentDropDetails, type AssignmentResult, type AttachPickerFrameOptions, type BestAvailableResult, type BucketRow, BuyerAccessContext, type BuyerAccessExpiredEvent, type BuyerAccessRefreshReason, type BuyerAccessToken, type BuyerAccessTokenProvider, BuyerAccessUnavailableError, type BuyerAccessUnavailableEvent, type BuyerAccessUnavailableReason, BuyerRealtimeClient, type BuyerRealtimeOptions, type ChannelAccessIntent, type ChannelAccessSummary, type ChannelAllocationPage, type ChannelAuditEntry, type ChannelAuditPage, type ChannelCounts, type ChannelListResult, type ChannelPreviewProjection, type ChannelRecord, type ChannelSeatStatus, type ChannelState, type ChannelsCapabilities, type ChannelsClient, ChannelsMode, type ChannelsModeHost, type ChannelsSeatView, type CheckoutHandoff, type CheckoutLineItem, type ControlRoomActivityEntry, 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, PUBLIC_CHANNEL_ID, PUBLIC_CHANNEL_NAME, type Projection, type PubApiOptions, type RealtimeSink, type ReportByStatus, type ReportCategoryMeta, type ReportCategoryRow, type ReportResult, type ResumedHoldResult, SeatManager, type SeatManagerActionResult, type SeatManagerActivity, type SeatManagerCapability, type SeatManagerMode, type SeatManagerOptions, type SeatManagerTallies, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedObjectUnavailableEvent, type SelectedSeat, type SelectionSourceRow, type StatusChange, type SubscribeTicket$1 as SubscribeTicket, accessIntentLabel, accessLine, accessLinkBadge, accessLinkErrorCopy, accessLinkIsLive, accessLinkPolicyLines, attachPickerFrame, bucketRows, bucketRowsHtml, createBuyerAccessContext, createControllerSink, dropReviewRows, isPublicChannelId, markerLetter, markerOf, mutationCount, needsMoveConfirmation, planAssignment, retryAfterCopy, selectionSources, stateBadge, suggestMarker };
|
package/dist/index.d.ts
CHANGED
|
@@ -2029,6 +2029,100 @@ declare function retryAfterCopy(details: ArchiveBlockedDetails | null | undefine
|
|
|
2029
2029
|
declare function accessLine(access: ChannelAccessSummary | null | undefined): string;
|
|
2030
2030
|
/** Plain-language label for the access-intent control. */
|
|
2031
2031
|
declare function accessIntentLabel(intent: ChannelAccessIntent): string;
|
|
2032
|
+
/** Lifecycle the server stores. `rotated` means a newer link replaced this one. */
|
|
2033
|
+
type AccessLinkState = 'active' | 'revoked' | 'rotated';
|
|
2034
|
+
/** What the organizer surface renders: `state`, unless an active link has run
|
|
2035
|
+
* out of time or out of redemptions. Never a capability, never a hash. */
|
|
2036
|
+
type AccessLinkStatus = AccessLinkState | 'expired' | 'exhausted';
|
|
2037
|
+
/**
|
|
2038
|
+
* One hosted link, exactly as `GET …/access-links` projects it.
|
|
2039
|
+
*
|
|
2040
|
+
* There is deliberately NO `url` and NO `capability` field here — the listing
|
|
2041
|
+
* route does not return them, no other route returns them, and this type must
|
|
2042
|
+
* not tempt a caller into believing otherwise. The secret exists in exactly one
|
|
2043
|
+
* place for exactly one moment: the create/rotate response (`AccessLinkReveal`).
|
|
2044
|
+
*/
|
|
2045
|
+
interface AccessLinkRecord {
|
|
2046
|
+
id: string;
|
|
2047
|
+
channelId: string;
|
|
2048
|
+
label: string | null;
|
|
2049
|
+
includePublic: boolean;
|
|
2050
|
+
expiresAt: number;
|
|
2051
|
+
maxRedemptions: number;
|
|
2052
|
+
redemptions: number;
|
|
2053
|
+
/** Guest-weighted per-buyer ceiling handed to every session this link mints. */
|
|
2054
|
+
maxQuantity: number;
|
|
2055
|
+
sessionTtlSeconds: number;
|
|
2056
|
+
state: AccessLinkState;
|
|
2057
|
+
status: AccessLinkStatus;
|
|
2058
|
+
createdAt: number;
|
|
2059
|
+
createdBy: string | null;
|
|
2060
|
+
revokedAt: number | null;
|
|
2061
|
+
lastRedeemedAt: number | null;
|
|
2062
|
+
/** Rotation lineage: the link this replaced, and the one that replaced it. */
|
|
2063
|
+
rotatedFrom: string | null;
|
|
2064
|
+
rotatedTo: string | null;
|
|
2065
|
+
}
|
|
2066
|
+
/** A listed link, with the live session count the rotate dialog needs to state
|
|
2067
|
+
* "N buyers got in with this link and still have access". */
|
|
2068
|
+
interface AccessLinkStatusRecord extends AccessLinkRecord {
|
|
2069
|
+
activeSessions?: number;
|
|
2070
|
+
}
|
|
2071
|
+
/**
|
|
2072
|
+
* The ONE-TIME reveal. `url` and `capability` are on the wire exactly once, in
|
|
2073
|
+
* the create/rotate response, and are unrecoverable afterwards: SeatLayer stores
|
|
2074
|
+
* only a hash. Nothing may persist this — see `ChannelsMode.revealLink`.
|
|
2075
|
+
*/
|
|
2076
|
+
interface AccessLinkReveal {
|
|
2077
|
+
link: AccessLinkRecord;
|
|
2078
|
+
url: string;
|
|
2079
|
+
capability: string;
|
|
2080
|
+
revealedOnce: true;
|
|
2081
|
+
/** Rotation only: the link that just stopped working, and how many live buyer
|
|
2082
|
+
* sessions from it were ended (0 when the organizer let them finish). */
|
|
2083
|
+
previous?: AccessLinkRecord;
|
|
2084
|
+
endedSessions?: number;
|
|
2085
|
+
}
|
|
2086
|
+
/**
|
|
2087
|
+
* Owner-set defaults for a new link. Expiry is NOT here: "when the event starts"
|
|
2088
|
+
* is the server's own default (it knows `starts_at`; the cockpit does not), so
|
|
2089
|
+
* the create form expresses that choice by omitting `expiresAt` entirely rather
|
|
2090
|
+
* than by guessing a timestamp the server would then have to correct.
|
|
2091
|
+
*/
|
|
2092
|
+
declare const ACCESS_LINK_DEFAULTS: {
|
|
2093
|
+
readonly maxRedemptions: 100;
|
|
2094
|
+
readonly maxQuantity: 4;
|
|
2095
|
+
};
|
|
2096
|
+
/** Plain-language state badge for a hosted link (§9: no internal vocabulary). */
|
|
2097
|
+
declare function accessLinkBadge(link: Pick<AccessLinkRecord, 'status' | 'state'>): {
|
|
2098
|
+
text: string;
|
|
2099
|
+
kind: 'active' | 'paused' | 'archived';
|
|
2100
|
+
};
|
|
2101
|
+
/** Only an `active` link can be rotated or revoked; the server agrees (409
|
|
2102
|
+
* `access_link_not_active`), so the buttons are absent rather than failing. */
|
|
2103
|
+
declare function accessLinkIsLive(link: Pick<AccessLinkRecord, 'status' | 'state'>): boolean;
|
|
2104
|
+
/**
|
|
2105
|
+
* The policy an organizer is agreeing to, in one list. Used by BOTH the reveal
|
|
2106
|
+
* (what you just created) and the status card (what is live), so the two can
|
|
2107
|
+
* never drift into describing the same link differently.
|
|
2108
|
+
*/
|
|
2109
|
+
declare function accessLinkPolicyLines(link: AccessLinkRecord): Array<{
|
|
2110
|
+
k: string;
|
|
2111
|
+
v: string;
|
|
2112
|
+
}>;
|
|
2113
|
+
/**
|
|
2114
|
+
* Plain language for a refused hosted-link call.
|
|
2115
|
+
*
|
|
2116
|
+
* The PLATFORM BOUNDS live on the server (60s–180d expiry, 1–10 000 redemptions,
|
|
2117
|
+
* 1–100 seats per buyer, 20 live links per channel) and the server states them
|
|
2118
|
+
* in `message`. We surface that sentence rather than re-encoding the numbers
|
|
2119
|
+
* here, so the client can never disagree with the rule it is reporting.
|
|
2120
|
+
*/
|
|
2121
|
+
declare function accessLinkErrorCopy(err: {
|
|
2122
|
+
code?: string;
|
|
2123
|
+
serverMessage?: string;
|
|
2124
|
+
status?: number;
|
|
2125
|
+
} | null | undefined): string;
|
|
2032
2126
|
/**
|
|
2033
2127
|
* The chart-update refusal `channel_assignment_would_drop` (409) deliberately
|
|
2034
2128
|
* mirrors the Apply skipped buckets, so ONE review component renders both.
|
|
@@ -2143,10 +2237,17 @@ declare class ManageApiError extends Error {
|
|
|
2143
2237
|
* `channel_assignment_conflict` carries the current assignmentVersion.
|
|
2144
2238
|
*/
|
|
2145
2239
|
details?: Record<string, unknown>;
|
|
2240
|
+
/**
|
|
2241
|
+
* The server's own human sentence, when it sent one. `message` is the machine
|
|
2242
|
+
* code (that is what `error` carries), so a UI that wants to state a PLATFORM
|
|
2243
|
+
* RULE — "redemptions must be between 1 and 10 000" — reads this instead of
|
|
2244
|
+
* re-encoding the bound locally and risking disagreement with the server.
|
|
2245
|
+
*/
|
|
2246
|
+
serverMessage?: string;
|
|
2146
2247
|
constructor(status: number, message: string, code?: string, conflicts?: {
|
|
2147
2248
|
label: string;
|
|
2148
2249
|
reason?: string;
|
|
2149
|
-
}[], details?: Record<string, unknown
|
|
2250
|
+
}[], details?: Record<string, unknown>, serverMessage?: string);
|
|
2150
2251
|
}
|
|
2151
2252
|
interface ReportByStatus {
|
|
2152
2253
|
free: number;
|
|
@@ -2437,6 +2538,53 @@ declare class ManageApi {
|
|
|
2437
2538
|
ok: true;
|
|
2438
2539
|
channel: ChannelRecord;
|
|
2439
2540
|
}>;
|
|
2541
|
+
/**
|
|
2542
|
+
* Mint a hosted access link. The 201 is the ONE and ONLY time `url` and
|
|
2543
|
+
* `capability` exist outside the buyer's browser — SeatLayer keeps a hash, so
|
|
2544
|
+
* there is no route, cache, or support escalation that can produce this string
|
|
2545
|
+
* again. Callers must reveal it immediately and then let it go.
|
|
2546
|
+
*
|
|
2547
|
+
* Every omitted field takes the server's default: expiry = when the event
|
|
2548
|
+
* starts, 100 redemptions, 4 seats per buyer, this channel's allocation only.
|
|
2549
|
+
* Platform bounds are enforced server-side and reported as 422 with the rule
|
|
2550
|
+
* spelled out in `ManageApiError.serverMessage`.
|
|
2551
|
+
*
|
|
2552
|
+
* Side effect by design: this also declares the channel's access intent as
|
|
2553
|
+
* `hosted_link`, so the rail stops saying "no buyer access configured".
|
|
2554
|
+
*/
|
|
2555
|
+
createAccessLink(key: string, channelId: string, input?: {
|
|
2556
|
+
label?: string | null;
|
|
2557
|
+
/** Absolute epoch ms. Omit for "when the event starts". */
|
|
2558
|
+
expiresAt?: number;
|
|
2559
|
+
maxRedemptions?: number;
|
|
2560
|
+
maxQuantity?: number;
|
|
2561
|
+
includePublic?: boolean;
|
|
2562
|
+
}): Promise<AccessLinkReveal>;
|
|
2563
|
+
/** Status only — label, expiry, redemptions, per-buyer cap, lineage, and the
|
|
2564
|
+
* live session count. Never the url, never the capability. Needs `:view`. */
|
|
2565
|
+
accessLinks(key: string, channelId: string): Promise<{
|
|
2566
|
+
links: AccessLinkStatusRecord[];
|
|
2567
|
+
}>;
|
|
2568
|
+
/**
|
|
2569
|
+
* Rotate — the ONLY recovery for a link nobody kept. The old URL stops opening
|
|
2570
|
+
* immediately and the response is a fresh one-time reveal.
|
|
2571
|
+
*
|
|
2572
|
+
* `endActiveSessions` is REQUIRED, not defaulted: the organizer must say
|
|
2573
|
+
* whether buyers already inside finish their checkout or lose access now. The
|
|
2574
|
+
* server answers 422 `end_active_sessions_required` if it is omitted, and that
|
|
2575
|
+
* refusal is correct — a UI must not pick either branch on their behalf.
|
|
2576
|
+
*/
|
|
2577
|
+
rotateAccessLink(key: string, channelId: string, linkId: string, endActiveSessions: boolean): Promise<AccessLinkReveal & {
|
|
2578
|
+
previous: AccessLinkRecord;
|
|
2579
|
+
endedSessions: number;
|
|
2580
|
+
}>;
|
|
2581
|
+
/** Revoke. The link stops opening immediately; `endActiveSessions` decides
|
|
2582
|
+
* whether the buyers already inside keep their sessions. */
|
|
2583
|
+
revokeAccessLink(key: string, channelId: string, linkId: string, endActiveSessions?: boolean): Promise<{
|
|
2584
|
+
ok: true;
|
|
2585
|
+
link: AccessLinkRecord;
|
|
2586
|
+
endedSessions: number;
|
|
2587
|
+
}>;
|
|
2440
2588
|
report(key: string): Promise<ReportResult>;
|
|
2441
2589
|
controlRoom(key: string, windowMinutes?: number): Promise<ControlRoomSnapshot>;
|
|
2442
2590
|
log(key: string, opts?: {
|
|
@@ -2918,6 +3066,26 @@ interface ChannelsClient {
|
|
|
2918
3066
|
ok: true;
|
|
2919
3067
|
channel: ChannelRecord;
|
|
2920
3068
|
}>;
|
|
3069
|
+
/** 201 with the ONE-TIME reveal. Every omitted field takes the server default
|
|
3070
|
+
* (expiry = event start, 100 redemptions, 4 seats per buyer). */
|
|
3071
|
+
createAccessLink(key: string, channelId: string, input: {
|
|
3072
|
+
label?: string | null;
|
|
3073
|
+
expiresAt?: number;
|
|
3074
|
+
maxRedemptions?: number;
|
|
3075
|
+
maxQuantity?: number;
|
|
3076
|
+
includePublic?: boolean;
|
|
3077
|
+
}): Promise<AccessLinkReveal>;
|
|
3078
|
+
/** Status only. This response has no url and no capability, by contract. */
|
|
3079
|
+
accessLinks(key: string, channelId: string): Promise<{
|
|
3080
|
+
links: AccessLinkStatusRecord[];
|
|
3081
|
+
}>;
|
|
3082
|
+
/** `endActiveSessions` is required — the server 422s without it, deliberately. */
|
|
3083
|
+
rotateAccessLink(key: string, channelId: string, linkId: string, endActiveSessions: boolean): Promise<AccessLinkReveal>;
|
|
3084
|
+
revokeAccessLink(key: string, channelId: string, linkId: string, endActiveSessions?: boolean): Promise<{
|
|
3085
|
+
ok: true;
|
|
3086
|
+
link: unknown;
|
|
3087
|
+
endedSessions: number;
|
|
3088
|
+
}>;
|
|
2921
3089
|
}
|
|
2922
3090
|
interface ChannelsCapabilities {
|
|
2923
3091
|
view: boolean;
|
|
@@ -2996,6 +3164,15 @@ declare class ChannelsMode {
|
|
|
2996
3164
|
private dialog;
|
|
2997
3165
|
private detent;
|
|
2998
3166
|
private seatListLimit;
|
|
3167
|
+
/**
|
|
3168
|
+
* Hosted-link STATUS for the channel whose detail panel is open. This is the
|
|
3169
|
+
* listing projection — it carries no url and no capability, because no route
|
|
3170
|
+
* returns one. `unsupported` is the honest answer for a worker that predates
|
|
3171
|
+
* M8, exactly like the buyer-preview probe.
|
|
3172
|
+
*/
|
|
3173
|
+
private links;
|
|
3174
|
+
private linksChannelId;
|
|
3175
|
+
private linksState;
|
|
2999
3176
|
private previewAudience;
|
|
3000
3177
|
private previewIncludePublic;
|
|
3001
3178
|
private previewProjection;
|
|
@@ -3079,6 +3256,23 @@ declare class ChannelsMode {
|
|
|
3079
3256
|
private listRailHtml;
|
|
3080
3257
|
private selectionRailHtml;
|
|
3081
3258
|
private detailRailHtml;
|
|
3259
|
+
/**
|
|
3260
|
+
* Read the status projection for the open channel. Never paints — the caller
|
|
3261
|
+
* decides when the rail repaints, so a poll-driven reload does not fight a
|
|
3262
|
+
* user-driven one. A worker without M8 answers 404/405 and gets the honest
|
|
3263
|
+
* "needs a newer server" line rather than an error toast.
|
|
3264
|
+
*/
|
|
3265
|
+
private loadLinks;
|
|
3266
|
+
/**
|
|
3267
|
+
* The hosted-link section of the detail panel.
|
|
3268
|
+
*
|
|
3269
|
+
* STATUS ONLY, by design (comp 06 `hosted`): label, state, expiry,
|
|
3270
|
+
* redemptions, seats per buyer, live sessions. There is no Copy control here
|
|
3271
|
+
* and no field to hang one on — the URL was shown once at creation and cannot
|
|
3272
|
+
* be produced again. Rotation is the recovery path, and it says so.
|
|
3273
|
+
*/
|
|
3274
|
+
private hostedLinksHtml;
|
|
3275
|
+
private linkCardHtml;
|
|
3082
3276
|
private previewRailHtml;
|
|
3083
3277
|
private paintSelection;
|
|
3084
3278
|
private wireRail;
|
|
@@ -3119,6 +3313,43 @@ declare class ChannelsMode {
|
|
|
3119
3313
|
* per-section select actions.
|
|
3120
3314
|
*/
|
|
3121
3315
|
private renderSeatListDialog;
|
|
3316
|
+
private reloadLinks;
|
|
3317
|
+
private linkById;
|
|
3318
|
+
/**
|
|
3319
|
+
* Create. The three policy fields carry the owner's defaults and every one of
|
|
3320
|
+
* them is editable; the PLATFORM bounds (60s–180d, 1–10 000, 1–100, 20 live
|
|
3321
|
+
* links) are the server's to enforce and the server's to explain, so this form
|
|
3322
|
+
* checks only that a number is a number and surfaces the server's sentence for
|
|
3323
|
+
* everything else.
|
|
3324
|
+
*/
|
|
3325
|
+
private renderLinkCreateDialog;
|
|
3326
|
+
private createLink;
|
|
3327
|
+
/**
|
|
3328
|
+
* The ONE-TIME reveal.
|
|
3329
|
+
*
|
|
3330
|
+
* Three things make this unrecoverable rather than merely "not shown twice":
|
|
3331
|
+
*
|
|
3332
|
+
* 1. `url` is a local const. It is never assigned to a field on this class,
|
|
3333
|
+
* never handed to the host, never put in a `DialogState`.
|
|
3334
|
+
* 2. `this.dialog` is cleared FIRST, so `renderDialog()` — the only function
|
|
3335
|
+
* that rebuilds a sheet — has nothing to rebuild this one from.
|
|
3336
|
+
* 3. The string exists in exactly one DOM node inside the scrim. Dismissing
|
|
3337
|
+
* the dialog removes the scrim, and the closure goes with it.
|
|
3338
|
+
*
|
|
3339
|
+
* The server holds only a hash, so even a compromised client cannot ask for it
|
|
3340
|
+
* again. Rotation is the recovery path, and the copy says so.
|
|
3341
|
+
*/
|
|
3342
|
+
private revealLink;
|
|
3343
|
+
/**
|
|
3344
|
+
* Rotate. The organizer must SAY what happens to the buyers already inside —
|
|
3345
|
+
* the confirm stays disabled until one of the two choices is picked, because
|
|
3346
|
+
* the gentle branch and the destructive branch are both real decisions and the
|
|
3347
|
+
* server refuses (422 `end_active_sessions_required`) to guess either.
|
|
3348
|
+
*/
|
|
3349
|
+
private renderLinkRotateDialog;
|
|
3350
|
+
private rotateLink;
|
|
3351
|
+
private renderLinkRevokeDialog;
|
|
3352
|
+
private revokeLink;
|
|
3122
3353
|
private applySheetClasses;
|
|
3123
3354
|
private cycleDetent;
|
|
3124
3355
|
/** Back/Close from the full detent returns to the previous one and keeps the
|
|
@@ -3126,4 +3357,4 @@ declare class ChannelsMode {
|
|
|
3126
3357
|
handleBack(): boolean;
|
|
3127
3358
|
}
|
|
3128
3359
|
|
|
3129
|
-
export { ApiError, type ArchiveBlockedDetails, type AssignmentBuckets, type AssignmentDropDetails, type AssignmentResult, type AttachPickerFrameOptions, type BestAvailableResult, type BucketRow, BuyerAccessContext, type BuyerAccessExpiredEvent, type BuyerAccessRefreshReason, type BuyerAccessToken, type BuyerAccessTokenProvider, BuyerAccessUnavailableError, type BuyerAccessUnavailableEvent, type BuyerAccessUnavailableReason, BuyerRealtimeClient, type BuyerRealtimeOptions, type ChannelAccessIntent, type ChannelAccessSummary, type ChannelAllocationPage, type ChannelAuditEntry, type ChannelAuditPage, type ChannelCounts, type ChannelListResult, type ChannelPreviewProjection, type ChannelRecord, type ChannelSeatStatus, type ChannelState, type ChannelsCapabilities, type ChannelsClient, ChannelsMode, type ChannelsModeHost, type ChannelsSeatView, type CheckoutHandoff, type CheckoutLineItem, type ControlRoomActivityEntry, 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, PUBLIC_CHANNEL_ID, PUBLIC_CHANNEL_NAME, type Projection, type PubApiOptions, type RealtimeSink, type ReportByStatus, type ReportCategoryMeta, type ReportCategoryRow, type ReportResult, type ResumedHoldResult, SeatManager, type SeatManagerActionResult, type SeatManagerActivity, type SeatManagerCapability, type SeatManagerMode, type SeatManagerOptions, type SeatManagerTallies, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedObjectUnavailableEvent, type SelectedSeat, type SelectionSourceRow, type StatusChange, type SubscribeTicket$1 as SubscribeTicket, accessIntentLabel, accessLine, attachPickerFrame, bucketRows, bucketRowsHtml, createBuyerAccessContext, createControllerSink, dropReviewRows, isPublicChannelId, markerLetter, markerOf, mutationCount, needsMoveConfirmation, planAssignment, retryAfterCopy, selectionSources, stateBadge, suggestMarker };
|
|
3360
|
+
export { ACCESS_LINK_DEFAULTS, type AccessLinkRecord, type AccessLinkReveal, type AccessLinkState, type AccessLinkStatus, type AccessLinkStatusRecord, ApiError, type ArchiveBlockedDetails, type AssignmentBuckets, type AssignmentDropDetails, type AssignmentResult, type AttachPickerFrameOptions, type BestAvailableResult, type BucketRow, BuyerAccessContext, type BuyerAccessExpiredEvent, type BuyerAccessRefreshReason, type BuyerAccessToken, type BuyerAccessTokenProvider, BuyerAccessUnavailableError, type BuyerAccessUnavailableEvent, type BuyerAccessUnavailableReason, BuyerRealtimeClient, type BuyerRealtimeOptions, type ChannelAccessIntent, type ChannelAccessSummary, type ChannelAllocationPage, type ChannelAuditEntry, type ChannelAuditPage, type ChannelCounts, type ChannelListResult, type ChannelPreviewProjection, type ChannelRecord, type ChannelSeatStatus, type ChannelState, type ChannelsCapabilities, type ChannelsClient, ChannelsMode, type ChannelsModeHost, type ChannelsSeatView, type CheckoutHandoff, type CheckoutLineItem, type ControlRoomActivityEntry, 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, PUBLIC_CHANNEL_ID, PUBLIC_CHANNEL_NAME, type Projection, type PubApiOptions, type RealtimeSink, type ReportByStatus, type ReportCategoryMeta, type ReportCategoryRow, type ReportResult, type ResumedHoldResult, SeatManager, type SeatManagerActionResult, type SeatManagerActivity, type SeatManagerCapability, type SeatManagerMode, type SeatManagerOptions, type SeatManagerTallies, SeatPicker, type SeatPickerOptions, type SeatPickerTheme, SeatingChart, type SeatingChartOptions, type SelectedObjectUnavailableEvent, type SelectedSeat, type SelectionSourceRow, type StatusChange, type SubscribeTicket$1 as SubscribeTicket, accessIntentLabel, accessLine, accessLinkBadge, accessLinkErrorCopy, accessLinkIsLive, accessLinkPolicyLines, attachPickerFrame, bucketRows, bucketRowsHtml, createBuyerAccessContext, createControllerSink, dropReviewRows, isPublicChannelId, markerLetter, markerOf, mutationCount, needsMoveConfirmation, planAssignment, retryAfterCopy, selectionSources, stateBadge, suggestMarker };
|