@seatlayer/server 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/resources/charts.ts","../src/resources/events.ts","../src/resources/inventory.ts","../src/resources/sessions.ts","../src/resources/webhooks.ts","../src/resources/workspaces.ts","../src/webhooks-verify.ts"],"sourcesContent":["/**\n * SeatLayer server SDK.\n *\n * Secret-key only. This package must never be bundled into a browser — see the\n * session-minting helpers for how browser surfaces get scoped tokens instead.\n */\nimport { HttpClient, type ClientOptions } from './http.js';\nimport { Charts } from './resources/charts.js';\nimport { Events } from './resources/events.js';\nimport { Inventory } from './resources/inventory.js';\nimport { Sessions } from './resources/sessions.js';\nimport { Webhooks } from './resources/webhooks.js';\nimport { Workspaces } from './resources/workspaces.js';\n\nexport class SeatLayer {\n readonly charts: Charts;\n readonly events: Events;\n readonly inventory: Inventory;\n readonly sessions: Sessions;\n readonly webhooks: Webhooks;\n readonly workspaces: Workspaces;\n\n /** `test` or `live`, derived from the key prefix. */\n readonly mode: 'live' | 'test' | 'unknown';\n\n #http: HttpClient;\n\n constructor(options: ClientOptions | string) {\n const resolved: ClientOptions = typeof options === 'string' ? { secretKey: options } : options;\n this.#http = new HttpClient(resolved);\n this.mode = this.#http.mode;\n\n this.charts = new Charts(this.#http);\n this.events = new Events(this.#http);\n this.inventory = new Inventory(this.#http);\n this.sessions = new Sessions(this.#http);\n this.webhooks = new Webhooks(this.#http);\n this.workspaces = new Workspaces(this.#http);\n }\n\n /** Dependency-aware readiness probe. Unauthenticated upstream. */\n ready(): Promise<{ ok: boolean; [key: string]: unknown }> {\n return this.#http.get('/health/ready');\n }\n\n /**\n * Escape hatch for surface this SDK does not wrap yet. Carries the same auth,\n * retry, idempotency and error mapping as everything else.\n */\n request<T>(method: string, path: string, options?: Parameters<HttpClient['request']>[2]): Promise<T> {\n return this.#http.request<T>(method, path, options);\n }\n}\n\nexport { verifyWebhook, WebhookVerificationError, type VerifyWebhookOptions } from './webhooks-verify.js';\nexport {\n SeatLayerError,\n SeatLayerAuthError,\n SeatLayerConflictError,\n SeatLayerConnectionError,\n SeatLayerNotFoundError,\n SeatLayerRateLimitError,\n SeatLayerValidationError,\n type ApiErrorBody,\n} from './errors.js';\nexport type { ClientOptions, RequestOptions } from './http.js';\nexport type * from './types.js';\n\nexport default SeatLayer;\n","/**\n * Typed errors.\n *\n * The API answers failures with `{ error, code?, message? }` and a status. A\n * generated client would surface that as one opaque exception and leave every\n * caller string-matching on `error`. The cases below are the ones an\n * integration actually branches on — a sold-out seat is a business outcome that\n * belongs in an `if`, not in a `catch` that also swallows a bad key.\n */\n\n/** Raw error envelope as the API sends it. */\nexport interface ApiErrorBody {\n error?: string;\n code?: string;\n message?: string;\n [key: string]: unknown;\n}\n\nexport class SeatLayerError extends Error {\n readonly status: number;\n /** Machine-readable code: `body.code ?? body.error`. */\n readonly code: string;\n readonly body: ApiErrorBody;\n /** Correlation id from `X-Request-ID`. Quote it in support requests. */\n readonly requestId: string | null;\n\n constructor(status: number, body: ApiErrorBody, requestId: string | null) {\n const code = body.code ?? body.error ?? 'unknown_error';\n super(body.message ?? `SeatLayer API error ${status} (${code})`);\n this.name = 'SeatLayerError';\n this.status = status;\n this.code = code;\n this.body = body;\n this.requestId = requestId;\n }\n}\n\n/** 401/403 — bad key, revoked key, or a live key used against a test event. */\nexport class SeatLayerAuthError extends SeatLayerError {\n constructor(status: number, body: ApiErrorBody, requestId: string | null) {\n super(status, body, requestId);\n this.name = 'SeatLayerAuthError';\n }\n\n /**\n * True when the key's mode and the event's mode disagree — the most common\n * cause of a \"works locally, 403s in production\" report.\n */\n get isModeMismatch(): boolean {\n return this.code === 'mode_mismatch';\n }\n}\n\nexport class SeatLayerNotFoundError extends SeatLayerError {\n constructor(status: number, body: ApiErrorBody, requestId: string | null) {\n super(status, body, requestId);\n this.name = 'SeatLayerNotFoundError';\n }\n}\n\n/**\n * 409 — the seats moved under you. This is a normal outcome in ticketing, not\n * an exceptional one: two buyers wanted the same seat and one lost.\n */\nexport class SeatLayerConflictError extends SeatLayerError {\n /** Per-object conflicts, when the endpoint reports them. */\n readonly conflicts: Array<{ label: string; status: string }>;\n\n constructor(status: number, body: ApiErrorBody, requestId: string | null) {\n super(status, body, requestId);\n this.name = 'SeatLayerConflictError';\n this.conflicts = Array.isArray(body.conflicts)\n ? (body.conflicts as Array<{ label: string; status: string }>)\n : [];\n }\n\n /** True when best-available could not find enough free inventory. */\n get isSoldOut(): boolean {\n return this.body.reason === 'sold_out' || this.body.reason === 'not_enough_together';\n }\n}\n\n/** 422 — the request was understood and rejected. */\nexport class SeatLayerValidationError extends SeatLayerError {\n constructor(status: number, body: ApiErrorBody, requestId: string | null) {\n super(status, body, requestId);\n this.name = 'SeatLayerValidationError';\n }\n}\n\n/**\n * 429. `retryAfterSeconds` comes from the `Retry-After` header when present and\n * falls back to the JSON field, so callers get a real number either way.\n */\nexport class SeatLayerRateLimitError extends SeatLayerError {\n readonly retryAfterSeconds: number;\n\n constructor(\n status: number,\n body: ApiErrorBody,\n requestId: string | null,\n retryAfterSeconds: number,\n ) {\n super(status, body, requestId);\n this.name = 'SeatLayerRateLimitError';\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\n/** The request never got an answer: DNS, TLS, socket, or an abort. */\nexport class SeatLayerConnectionError extends Error {\n override readonly cause: unknown;\n\n constructor(message: string, cause: unknown) {\n super(message);\n this.name = 'SeatLayerConnectionError';\n this.cause = cause;\n }\n}\n\nexport function errorFromResponse(\n status: number,\n body: ApiErrorBody,\n requestId: string | null,\n retryAfterSeconds: number,\n): SeatLayerError {\n if (status === 401 || status === 403) return new SeatLayerAuthError(status, body, requestId);\n if (status === 404) return new SeatLayerNotFoundError(status, body, requestId);\n if (status === 409) return new SeatLayerConflictError(status, body, requestId);\n if (status === 422) return new SeatLayerValidationError(status, body, requestId);\n if (status === 429) {\n return new SeatLayerRateLimitError(status, body, requestId, retryAfterSeconds);\n }\n return new SeatLayerError(status, body, requestId);\n}\n","/**\n * The transport: auth, idempotency, retry, and error mapping.\n *\n * This is the layer that decides how the SDK behaves when the network or the\n * API misbehaves, which is most of what separates a usable client from a thin\n * `fetch` wrapper.\n */\nimport {\n errorFromResponse,\n SeatLayerConnectionError,\n SeatLayerRateLimitError,\n type ApiErrorBody,\n} from './errors.js';\n\nexport interface ClientOptions {\n /** `sk_live_…` or `sk_test_…`. Never expose this to a browser. */\n secretKey: string;\n /** Override for self-hosted or staging. Defaults to the public API. */\n baseUrl?: string;\n /** Total attempts for retryable failures. Default 3 (two retries). */\n maxRetries?: number;\n /** Per-request timeout in ms. Default 30_000. */\n timeoutMs?: number;\n /** Injectable for tests and for runtimes with a non-global fetch. */\n fetch?: typeof globalThis.fetch;\n}\n\nexport interface RequestOptions {\n query?: Record<string, string | number | boolean | undefined>;\n body?: unknown;\n /**\n * Explicit Idempotency-Key. Omit and mutating requests get a generated one —\n * see `shouldSendIdempotencyKey`.\n */\n idempotencyKey?: string;\n signal?: AbortSignal;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.seatlayer.io';\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** The API's own charset for Idempotency-Key: ^[A-Za-z0-9._:-]{1,128}$ */\nconst IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;\n\nexport function assertValidIdempotencyKey(key: string): void {\n if (!IDEMPOTENCY_KEY_PATTERN.test(key)) {\n throw new TypeError(\n `Invalid Idempotency-Key ${JSON.stringify(key)}: allowed characters are A-Z a-z 0-9 . _ : - and the length must be 1-128.`,\n );\n }\n}\n\n/**\n * Every mutating request carries one. A retried POST that creates a second hold\n * is worse than a failed POST, and the caller cannot tell the difference from\n * the outside — so the SDK, which knows it retried, is the right place to\n * guarantee it. GET is naturally idempotent and needs no key.\n */\nexport function shouldSendIdempotencyKey(method: string): boolean {\n return method !== 'GET' && method !== 'HEAD';\n}\n\n/**\n * Retry only what is safe to retry.\n *\n * 429 and 5xx are transient by definition. A 4xx is the API telling you the\n * request itself is wrong — retrying it just burns rate-limit budget and delays\n * the error the caller needs to see.\n */\nfunction isRetryableStatus(status: number): boolean {\n return status === 429 || status === 408 || (status >= 500 && status < 600);\n}\n\nfunction backoffMs(attempt: number, retryAfterSeconds: number | null): number {\n // Server's instruction wins — it knows when the window actually rolls over.\n if (retryAfterSeconds !== null) return retryAfterSeconds * 1000;\n // Otherwise exponential with full jitter, so a fleet of workers that all got\n // limited at once does not retry in lockstep and re-limit itself.\n const ceiling = Math.min(8_000, 250 * 2 ** attempt);\n return Math.random() * ceiling;\n}\n\nfunction parseRetryAfter(response: Response, body: ApiErrorBody): number {\n const header = response.headers.get('retry-after');\n if (header) {\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds;\n }\n // Fall back to the JSON field for routes that predate the headers.\n const field = body.retryAfterSeconds;\n if (typeof field === 'number' && Number.isFinite(field)) return field;\n return 1;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport class HttpClient {\n readonly baseUrl: string;\n /** Whether this client is pointed at test-mode or live-mode data. */\n readonly mode: 'live' | 'test' | 'unknown';\n\n #secretKey: string;\n #maxRetries: number;\n #timeoutMs: number;\n #fetch: typeof globalThis.fetch;\n\n constructor(options: ClientOptions) {\n if (!options.secretKey) {\n throw new TypeError('A SeatLayer secret key is required.');\n }\n // Caught here rather than as a 401 three network round-trips later. The\n // pk_ case is worth its own message: it is the one people paste by mistake.\n if (options.secretKey.startsWith('pk_')) {\n throw new TypeError(\n 'That is a publishable key. The server SDK needs a secret key (sk_live_… or sk_test_…).',\n );\n }\n if (!options.secretKey.startsWith('sk_')) {\n throw new TypeError('A SeatLayer secret key starts with sk_live_ or sk_test_.');\n }\n\n this.#secretKey = options.secretKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n this.#maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n this.#timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.#fetch = options.fetch ?? globalThis.fetch;\n this.mode = options.secretKey.startsWith('sk_test_')\n ? 'test'\n : options.secretKey.startsWith('sk_live_')\n ? 'live'\n : 'unknown';\n }\n\n async request<T>(method: string, path: string, options: RequestOptions = {}): Promise<T> {\n const url = new URL(this.baseUrl + path);\n for (const [key, value] of Object.entries(options.query ?? {})) {\n if (value !== undefined) url.searchParams.set(key, String(value));\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.#secretKey}`,\n Accept: 'application/json',\n 'User-Agent': '@seatlayer/server',\n };\n if (options.body !== undefined) headers['Content-Type'] = 'application/json';\n\n if (shouldSendIdempotencyKey(method)) {\n const key = options.idempotencyKey ?? crypto.randomUUID();\n assertValidIdempotencyKey(key);\n // Deliberately stable across retries of the same logical call: that is\n // the entire point — the server collapses the duplicates.\n headers['Idempotency-Key'] = key;\n }\n\n let lastError: unknown;\n for (let attempt = 0; attempt < this.#maxRetries; attempt++) {\n const timeout = AbortSignal.timeout(this.#timeoutMs);\n const signal = options.signal\n ? AbortSignal.any([options.signal, timeout])\n : timeout;\n\n let response: Response;\n try {\n response = await this.#fetch(url, {\n method,\n headers,\n signal,\n ...(options.body !== undefined ? { body: JSON.stringify(options.body) } : {}),\n });\n } catch (cause) {\n // A caller-initiated abort is a decision, not a failure to retry.\n if (options.signal?.aborted) throw cause;\n lastError = new SeatLayerConnectionError(\n `Request to ${method} ${path} failed: ${(cause as Error)?.message ?? 'unknown error'}`,\n cause,\n );\n if (attempt < this.#maxRetries - 1) {\n await sleep(backoffMs(attempt, null));\n continue;\n }\n throw lastError;\n }\n\n const requestId = response.headers.get('x-request-id');\n\n if (response.ok) {\n if (response.status === 204) return undefined as T;\n const text = await response.text();\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n const body = (await response.json().catch(() => ({}))) as ApiErrorBody;\n const retryAfter = parseRetryAfter(response, body);\n\n if (isRetryableStatus(response.status) && attempt < this.#maxRetries - 1) {\n await sleep(backoffMs(attempt, response.status === 429 ? retryAfter : null));\n continue;\n }\n\n throw errorFromResponse(response.status, body, requestId, retryAfter);\n }\n\n // Only reachable if maxRetries is 0.\n throw lastError ?? new SeatLayerConnectionError('Request failed with no attempts made.', null);\n }\n\n get<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n post<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, options);\n }\n\n put<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('PUT', path, options);\n }\n\n patch<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, options);\n }\n\n delete<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, options);\n }\n}\n\nexport { SeatLayerRateLimitError };\n","import type { HttpClient } from '../http.js';\nimport type { Chart, ChartMeta } from '../types.js';\n\nexport interface ChartListOptions {\n workspaceId?: string;\n externalRef?: string;\n archived?: boolean;\n /** Page size. Clamped server-side; asking for more is not an error. */\n limit?: number;\n cursor?: string;\n}\n\nexport interface ChartPage {\n charts: ChartMeta[];\n /** Absent once the list is exhausted. */\n nextCursor?: string;\n}\n\n/**\n * Charts are the seat-map definitions events are created from.\n *\n * If your organisers draw their own venues in the embedded Designer, you still\n * need this: `createDesignerSession` requires a chartId that must already\n * exist, so the usual platform flow is copy a template here, then hand the\n * organiser a Designer session for it.\n */\nexport class Charts {\n #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n /**\n * One page of charts. Pass `cursor` from the previous page's `nextCursor`;\n * its absence means the list is exhausted.\n */\n list(options: ChartListOptions = {}): Promise<ChartPage> {\n return this.#http.get('/v1/charts', {\n query: {\n workspaceId: options.workspaceId,\n externalRef: options.externalRef,\n limit: options.limit,\n cursor: options.cursor,\n ...(options.archived ? { archived: '1' } : {}),\n },\n });\n }\n\n /**\n * Every chart, paging transparently.\n *\n * An async iterator rather than an array: the whole point of paginating was\n * to stop loading an unbounded list into memory, and returning `ChartMeta[]`\n * would hand that problem straight back to the caller.\n *\n * for await (const chart of seatlayer.charts.listAll()) { … }\n */\n async *listAll(options: Omit<ChartListOptions, 'cursor'> = {}): AsyncGenerator<ChartMeta> {\n let cursor: string | undefined;\n do {\n const page = await this.list({ ...options, cursor });\n for (const chart of page.charts) yield chart;\n cursor = page.nextCursor;\n } while (cursor);\n }\n\n create(params: {\n name: string;\n doc?: Record<string, unknown>;\n externalRef?: string;\n workspaceId?: string;\n }, options: { idempotencyKey?: string } = {}): Promise<{ meta: ChartMeta }> {\n return this.#http.post('/v1/charts', { body: params, idempotencyKey: options.idempotencyKey });\n }\n\n retrieve(chartId: string): Promise<Chart> {\n return this.#http.get(`/v1/charts/${encodeURIComponent(chartId)}`);\n }\n\n /**\n * Replace a chart document.\n *\n * `expectedUpdatedAt` is required by the API for optimistic concurrency and\n * is not optional here either: without it two concurrent writers silently\n * overwrite each other, and a seat map is exactly the kind of document where\n * that loses work. Read it from `retrieve()` immediately before writing.\n *\n * The Designer is the authoring surface. Reach for this for bulk programmatic\n * edits and migrations, not for drawing.\n */\n update(chartId: string, params: {\n doc: Record<string, unknown>;\n expectedUpdatedAt: number;\n name?: string;\n }): Promise<{ meta: ChartMeta }> {\n return this.#http.put(`/v1/charts/${encodeURIComponent(chartId)}`, { body: params });\n }\n\n delete(chartId: string): Promise<void> {\n return this.#http.delete(`/v1/charts/${encodeURIComponent(chartId)}`);\n }\n\n /** Copy a chart — the usual way to provision a venue from a template. */\n copy(chartId: string, options: { idempotencyKey?: string } = {}): Promise<{ meta: ChartMeta }> {\n return this.#http.post(`/v1/charts/${encodeURIComponent(chartId)}/duplicate`, {\n idempotencyKey: options.idempotencyKey,\n });\n }\n\n archive(chartId: string): Promise<{ meta: ChartMeta }> {\n return this.#http.post(`/v1/charts/${encodeURIComponent(chartId)}/archive`);\n }\n\n unarchive(chartId: string): Promise<{ meta: ChartMeta }> {\n return this.#http.post(`/v1/charts/${encodeURIComponent(chartId)}/unarchive`);\n }\n\n /** Publish the draft. An event can only be created from a published chart. */\n publish(chartId: string): Promise<{ meta: ChartMeta }> {\n return this.#http.post(`/v1/charts/${encodeURIComponent(chartId)}/publish`);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { EventMeta } from '../types.js';\n\nexport interface EventListOptions {\n workspaceId?: string;\n externalRef?: string;\n /** Page size. Clamped server-side; asking for more is not an error. */\n limit?: number;\n cursor?: string;\n /** Include live availability counts. One server round-trip per event. */\n counts?: boolean;\n}\n\nexport interface EventPage {\n events: EventMeta[];\n /** Absent once the list is exhausted. */\n nextCursor?: string;\n}\n\nexport class Events {\n #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n /**\n * One page of events. Pass `cursor` from the previous page's `nextCursor`.\n *\n * Live availability `counts` cost one round-trip per event server-side. They\n * are included by default because most callers want them; pass\n * `counts: false` when paging a whole catalogue, where you almost certainly\n * do not.\n */\n list(options: EventListOptions = {}): Promise<EventPage> {\n return this.#http.get('/v1/events', {\n query: {\n workspaceId: options.workspaceId,\n externalRef: options.externalRef,\n limit: options.limit,\n cursor: options.cursor,\n ...(options.counts === false ? { counts: '0' } : {}),\n },\n });\n }\n\n /**\n * Every event, paging transparently. Defaults to `counts: false` — you are\n * walking the whole list, so per-event availability is rarely what you want\n * and always what it costs.\n *\n * for await (const event of seatlayer.events.listAll()) { … }\n */\n async *listAll(options: Omit<EventListOptions, 'cursor'> = {}): AsyncGenerator<EventMeta> {\n let cursor: string | undefined;\n do {\n const page = await this.list({ counts: false, ...options, cursor });\n for (const event of page.events) yield event;\n cursor = page.nextCursor;\n } while (cursor);\n }\n\n create(params: {\n chartId: string;\n name?: string;\n slug?: string;\n startsAt?: number;\n venue?: string;\n externalRef?: string;\n /** Three-letter override. Defaults to the organisation currency. */\n currency?: string;\n }, options: { idempotencyKey?: string } = {}): Promise<{ meta: EventMeta }> {\n return this.#http.post('/v1/events', { body: params, idempotencyKey: options.idempotencyKey });\n }\n\n retrieve(eventKey: string): Promise<{ meta: EventMeta; counts?: Record<string, number> }> {\n return this.#http.get(`/v1/events/${encodeURIComponent(eventKey)}`);\n }\n\n update(eventKey: string, params: Record<string, unknown>): Promise<{ meta: EventMeta }> {\n return this.#http.patch(`/v1/events/${encodeURIComponent(eventKey)}`, { body: params });\n }\n\n delete(eventKey: string): Promise<void> {\n return this.#http.delete(`/v1/events/${encodeURIComponent(eventKey)}`);\n }\n\n /** Move a live event onto the latest published version of its chart. */\n updateChart(eventKey: string): Promise<unknown> {\n return this.#http.post(`/v1/events/${encodeURIComponent(eventKey)}/update-chart`);\n }\n\n /** Stop buyer sales. Existing holds keep their TTL. */\n close(eventKey: string): Promise<unknown> {\n return this.#http.post(`/v1/events/${encodeURIComponent(eventKey)}/close`);\n }\n\n reopen(eventKey: string): Promise<unknown> {\n return this.#http.post(`/v1/events/${encodeURIComponent(eventKey)}/reopen`);\n }\n\n archive(eventKey: string): Promise<unknown> {\n return this.#http.post(`/v1/events/${encodeURIComponent(eventKey)}/archive`);\n }\n\n /** Read the checkout window (ms) buyers get for this event. */\n retrieveHoldTtl(eventKey: string): Promise<{ holdTtlMs: number }> {\n return this.#http.get(`/v1/events/${encodeURIComponent(eventKey)}/hold-ttl`);\n }\n\n updateHoldTtl(eventKey: string, holdTtlMs: number): Promise<unknown> {\n return this.#http.post(`/v1/events/${encodeURIComponent(eventKey)}/hold-ttl`, {\n body: { holdTtlMs },\n });\n }\n\n retrieveReport(eventKey: string): Promise<unknown> {\n return this.#http.get(`/v1/events/${encodeURIComponent(eventKey)}/report`);\n }\n\n retrieveLog(eventKey: string): Promise<unknown> {\n return this.#http.get(`/v1/events/${encodeURIComponent(eventKey)}/log`);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { BookResult, HoldLineItem, HoldResult } from '../types.js';\n\n/**\n * Holds, booking, blocking, availability.\n *\n * Two complete flows, both first-class:\n *\n * browser holds → `retrieveHold` for authoritative pricing → charge → `book({holdId})`\n * backend books labels directly — box office, phone sales, comps\n *\n * Never price from what the browser tells you. `retrieveHold` is the\n * authoritative answer, which is why it exists as a separate call.\n */\nexport class Inventory {\n #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n #path(eventKey: string, suffix: string): string {\n return `/v1/events/${encodeURIComponent(eventKey)}${suffix}`;\n }\n\n hold(eventKey: string, params: {\n labels?: string[];\n selections?: Array<{ label: string; tierId?: string | null; quantity?: number }>;\n /** Overrides the event's checkout window for this hold. */\n ttlMs?: number;\n replaceHoldId?: string;\n }, options: { idempotencyKey?: string } = {}): Promise<HoldResult> {\n return this.#http.post(this.#path(eventKey, '/hold'), {\n body: params,\n idempotencyKey: options.idempotencyKey,\n });\n }\n\n /**\n * Ask us to pick the best free objects and hold them.\n *\n * The picker is the same one the buyer widget uses, so a phone order and a\n * web order get the same answer for the same inventory. `qty` above the\n * server cap is clamped, not rejected.\n */\n holdBestAvailable(eventKey: string, params: {\n qty: number;\n categoryKey?: string;\n zoneId?: string;\n ttlMs?: number;\n }, options: { idempotencyKey?: string } = {}): Promise<HoldResult> {\n return this.#http.post(this.#path(eventKey, '/best-available'), {\n body: params,\n idempotencyKey: options.idempotencyKey,\n });\n }\n\n /**\n * Pick and book in one call — the box-office shape, where payment is already\n * taken and there is no buyer session to hold against.\n *\n * Prefer this over holdBestAvailable-then-book for that case: a failure\n * between the two calls would strand inventory until the TTL expired.\n */\n bookBestAvailable(eventKey: string, params: {\n qty: number;\n bookingRef: string;\n categoryKey?: string;\n zoneId?: string;\n }, options: { idempotencyKey?: string } = {}): Promise<BookResult> {\n return this.#http.post(this.#path(eventKey, '/best-available-book'), {\n body: params,\n idempotencyKey: options.idempotencyKey,\n });\n }\n\n /**\n * Push an active hold's expiry out by a fresh window before it lapses.\n *\n * Use this rather than release-and-re-hold when an order is taking longer\n * than the checkout window — invoiced sales, a phone order on hold. Releasing\n * first hands the seats to whoever is racing for them in between. The server\n * clamps the window and the DO caps how many times one hold can be renewed;\n * a hold that is gone, expired, or at its cap answers 409 `cannot_extend`.\n */\n extendHold(eventKey: string, params: {\n holdId: string;\n ttlMs?: number;\n }): Promise<HoldResult> {\n return this.#http.post(this.#path(eventKey, '/extend'), { body: params });\n }\n\n /** Authoritative items and prices for a hold. Charge from this, not the browser. */\n retrieveHold(eventKey: string, holdId: string): Promise<{ items: HoldLineItem[]; expiresAt: number; currency: string }> {\n return this.#http.get(this.#path(eventKey, `/holds/${encodeURIComponent(holdId)}`));\n }\n\n /** Free a hold early. Requires both the labels and the hold id. */\n release(eventKey: string, params: { labels: string[]; holdId: string }): Promise<unknown> {\n return this.#http.post(this.#path(eventKey, '/release'), { body: params });\n }\n\n book(eventKey: string, params: {\n /** Book a held selection… */\n holdId?: string;\n /** …or book labels outright, with no prior hold. */\n labels?: string[];\n bookingRef?: string;\n }, options: { idempotencyKey?: string } = {}): Promise<BookResult> {\n return this.#http.post(this.#path(eventKey, '/book'), {\n body: params,\n idempotencyKey: options.idempotencyKey,\n });\n }\n\n boxOfficeBook(eventKey: string, params: {\n labels: string[];\n bookingRef: string;\n }, options: { idempotencyKey?: string } = {}): Promise<BookResult> {\n return this.#http.post(this.#path(eventKey, '/box-book'), {\n body: params,\n idempotencyKey: options.idempotencyKey,\n });\n }\n\n /** Reverse a booking. Requires a key with cancel authority. */\n unbook(eventKey: string, params: { labels: string[] }): Promise<unknown> {\n return this.#http.post(this.#path(eventKey, '/unbook'), { body: params });\n }\n\n /** Hold inventory back from sale (house seats, holds for production). */\n block(eventKey: string, params: { labels: string[] }): Promise<unknown> {\n return this.#http.post(this.#path(eventKey, '/block'), { body: params });\n }\n\n unblock(eventKey: string, params: { labels: string[] }): Promise<unknown> {\n return this.#http.post(this.#path(eventKey, '/unblock'), { body: params });\n }\n\n unblockAll(eventKey: string): Promise<unknown> {\n return this.#http.post(this.#path(eventKey, '/unblock-all'));\n }\n\n retrieveAvailability(eventKey: string): Promise<unknown> {\n return this.#http.get(this.#path(eventKey, '/availability'));\n }\n\n updateAvailability(eventKey: string, params: Record<string, unknown>): Promise<unknown> {\n return this.#http.post(this.#path(eventKey, '/availability'), { body: params });\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { DesignerSession, ManageCapability, ManageSession } from '../types.js';\n\n/**\n * Short-lived, origin-bound browser tokens.\n *\n * The governing rule of this SDK: **it mints tokens, widgets consume them.**\n * Your secret key never reaches a browser. You mint a scoped token here, hand\n * it to your frontend, and our widget uses that.\n */\nexport class Sessions {\n #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n /**\n * Mint a manage-session token for the control room.\n *\n * `capabilities` is required here even though the API defaults it. That\n * default grants all four — including `event:cancel`, which un-books paid\n * inventory. Granting the ability to reverse sales by forgetting an argument\n * is not a default worth inheriting, so this SDK makes you say it.\n *\n * `allowedOrigin` must be an https origin; the token is bound to it.\n */\n // `async` so the guard below rejects rather than throwing synchronously —\n // a sync throw from a promise-returning method escapes `.catch()` and\n // surfaces as an unhandled error in the caller's request handler.\n async createManageSession(eventKey: string, params: {\n allowedOrigin: string;\n capabilities: ManageCapability[];\n /** 300–14400. Defaults to 3600 server-side. */\n expiresInSeconds?: number;\n }): Promise<ManageSession> {\n if (!params.capabilities?.length) {\n throw new TypeError(\n 'capabilities is required: pass the smallest set the page needs, e.g. [\"event:view\"]. '\n + 'Omitting it server-side grants event:cancel, which can reverse paid bookings.',\n );\n }\n return this.#http.post(`/v1/events/${encodeURIComponent(eventKey)}/manage-sessions`, {\n body: params,\n });\n }\n\n /** Revoke a manage token before it expires (staff logout, permission change). */\n revokeManageSession(eventKey: string, sessionId: string): Promise<void> {\n return this.#http.delete(\n `/v1/events/${encodeURIComponent(eventKey)}/manage-sessions/${encodeURIComponent(sessionId)}`,\n );\n }\n\n /**\n * Mint a designer-session token so an organiser can edit a chart inside your\n * own UI. Requires a chartId that already exists — create or copy one first.\n */\n createDesignerSession(params: {\n workspaceId: string;\n chartId: string;\n allowedOrigin: string;\n authority?: 'read-only' | 'edit' | 'publish';\n mode?: 'normal' | 'safe';\n expiresInSeconds?: number;\n }): Promise<DesignerSession> {\n return this.#http.post('/v1/designer/sessions', { body: params });\n }\n\n revokeDesignerSession(sessionId: string): Promise<void> {\n return this.#http.delete(`/v1/designer/sessions/${encodeURIComponent(sessionId)}`);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { Webhook } from '../types.js';\n\nexport class Webhooks {\n #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n list(): Promise<{ webhooks: Webhook[] }> {\n return this.#http.get('/v1/webhooks');\n }\n\n create(params: { url: string; events: string[] }): Promise<{ webhook: Webhook; secret?: string }> {\n return this.#http.post('/v1/webhooks', { body: params });\n }\n\n update(webhookId: string, params: Partial<{ url: string; events: string[]; status: string }>): Promise<{ webhook: Webhook }> {\n return this.#http.patch(`/v1/webhooks/${encodeURIComponent(webhookId)}`, { body: params });\n }\n\n delete(webhookId: string): Promise<void> {\n return this.#http.delete(`/v1/webhooks/${encodeURIComponent(webhookId)}`);\n }\n\n listDeliveries(webhookId: string): Promise<{ deliveries: unknown[] }> {\n return this.#http.get(`/v1/webhooks/${encodeURIComponent(webhookId)}/deliveries`);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { Workspace } from '../types.js';\n\n/**\n * Workspaces isolate one tenant's charts and events from another's. A platform\n * typically provisions one per organiser at signup and disables it on churn.\n */\nexport class Workspaces {\n #http: HttpClient;\n\n constructor(http: HttpClient) {\n this.#http = http;\n }\n\n list(): Promise<{ workspaces: Workspace[] }> {\n return this.#http.get('/v1/workspaces');\n }\n\n create(params: { name: string; externalRef?: string }, options: { idempotencyKey?: string } = {}): Promise<{ workspace: Workspace }> {\n return this.#http.post('/v1/workspaces', { body: params, idempotencyKey: options.idempotencyKey });\n }\n\n retrieve(workspaceId: string): Promise<{ workspace: Workspace }> {\n return this.#http.get(`/v1/workspaces/${encodeURIComponent(workspaceId)}`);\n }\n\n /**\n * Rename, re-reference, or disable a workspace.\n *\n * The organisation's default workspace cannot be disabled — the API answers\n * 409 `default_workspace_required`. Promote another one first.\n */\n update(workspaceId: string, params: Partial<{\n name: string;\n externalRef: string | null;\n status: 'active' | 'disabled';\n isDefault: true;\n }>): Promise<{ workspace: Workspace }> {\n return this.#http.patch(`/v1/workspaces/${encodeURIComponent(workspaceId)}`, { body: params });\n }\n}\n","/**\n * Webhook signature verification.\n *\n * This is the single most security-sensitive thing an integrator writes by\n * hand, and the two classic mistakes are both easy to make and silent:\n *\n * 1. verifying against a re-serialised body (`JSON.stringify(req.body)`),\n * which changes bytes and fails — or worse, is \"fixed\" by skipping\n * verification entirely;\n * 2. comparing signatures with `===`, which leaks the expected value through\n * timing.\n *\n * So the SDK does it, takes the RAW body, and compares in constant time.\n */\nimport { createHmac, timingSafeEqual } from 'node:crypto';\n\nexport interface VerifyWebhookOptions {\n /**\n * The raw request body, exactly as received — a string or Buffer, never a\n * parsed object. Express: `express.raw({ type: 'application/json' })`.\n */\n payload: string | Uint8Array;\n /** The `X-SeatLayer-Signature` header value (`sha256=<hex>`). */\n signature: string | null | undefined;\n /** The signing secret from webhook creation. */\n secret: string;\n}\n\nexport class WebhookVerificationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebhookVerificationError';\n }\n}\n\n/**\n * Verify a delivery and return its parsed payload.\n *\n * Throws `WebhookVerificationError` on any failure — treat that as \"this did\n * not come from SeatLayer\" and respond 400 without processing it.\n *\n * NOTE ON REPLAY: deliveries are currently signed over the body only, with no\n * timestamp header and so no tolerance window. Replay protection is therefore\n * yours to enforce: every event carries an `occurrenceId`, and the correct\n * pattern is to record processed ids and ignore repeats. Do not skip this — a\n * captured delivery stays valid indefinitely.\n */\nexport function verifyWebhook<T = Record<string, unknown>>(options: VerifyWebhookOptions): T {\n const { payload, signature, secret } = options;\n\n if (!secret) throw new WebhookVerificationError('A webhook signing secret is required.');\n if (!signature) {\n throw new WebhookVerificationError('Missing X-SeatLayer-Signature header.');\n }\n\n const [scheme, provided] = signature.split('=');\n if (scheme !== 'sha256' || !provided) {\n throw new WebhookVerificationError(\n `Unsupported signature format ${JSON.stringify(signature)}; expected \"sha256=<hex>\".`,\n );\n }\n\n const body = typeof payload === 'string' ? Buffer.from(payload, 'utf8') : Buffer.from(payload);\n const expected = createHmac('sha256', secret).update(body).digest('hex');\n\n const a = Buffer.from(expected, 'hex');\n const b = Buffer.from(provided, 'hex');\n // timingSafeEqual throws on length mismatch, which would itself leak a bit;\n // check length first and fail the same way either way.\n if (a.length !== b.length || !timingSafeEqual(a, b)) {\n throw new WebhookVerificationError('Webhook signature did not match.');\n }\n\n try {\n return JSON.parse(body.toString('utf8')) as T;\n } catch (cause) {\n throw new WebhookVerificationError(\n `Signature verified but the body is not valid JSON: ${(cause as Error).message}`,\n );\n }\n}\n"],"mappings":"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","names":[]}