@nestuge/sdk 0.1.0 → 0.1.1

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 CHANGED
@@ -77,6 +77,22 @@ var ConnectionError = class extends NestugeError {
77
77
  };
78
78
  var WebhookVerificationError = class extends NestugeError {
79
79
  };
80
+ var detailFromEnvelope = (error) => {
81
+ if (typeof error === "string") return error;
82
+ if (!Array.isArray(error)) return void 0;
83
+ const parts = error.map((issue) => {
84
+ if (typeof issue === "string") return issue;
85
+ if (issue && typeof issue === "object") {
86
+ const { path, message } = issue;
87
+ if (typeof message !== "string") return void 0;
88
+ const segments = Array.isArray(path) ? path.map(String) : [];
89
+ const leaf = segments[segments.length - 1];
90
+ return leaf && !message.includes(leaf) ? `${segments.join(".")}: ${message}` : message;
91
+ }
92
+ return void 0;
93
+ }).filter((part) => Boolean(part));
94
+ return parts.length > 0 ? parts.join("; ") : void 0;
95
+ };
80
96
  var errorFromResponse = ({
81
97
  status,
82
98
  body,
@@ -87,7 +103,7 @@ var errorFromResponse = ({
87
103
  message: typeof envelope.message === "string" ? envelope.message : `Request failed with status ${status}`,
88
104
  status,
89
105
  code: typeof envelope.code === "number" ? envelope.code : void 0,
90
- detail: typeof envelope.error === "string" ? envelope.error : void 0
106
+ detail: detailFromEnvelope(envelope.error)
91
107
  };
92
108
  if (status === 400) return new ValidationError(context);
93
109
  if (status === 401) return new AuthenticationError(context);
@@ -275,8 +291,9 @@ var Products = class {
275
291
  });
276
292
  }
277
293
  /**
278
- * Creates a draft product. Requires `products:write`. Test-mode keys
279
- * validate and return a preview without persisting.
294
+ * Creates a draft product, optionally with content items. Requires
295
+ * `products:write`. Returns the product with its pricing tiers and items.
296
+ * Test-mode keys validate and return a preview without persisting.
280
297
  */
281
298
  create(params) {
282
299
  return this.requestor.request({
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/errors.ts","../src/core/request.ts","../src/core/pagination.ts","../src/resources/customers.ts","../src/resources/events.ts","../src/resources/products.ts","../src/resources/purchases.ts","../src/resources/tickets.ts","../src/resources/transactions.ts","../src/webhooks/signature.ts","../src/resources/webhooks.ts","../src/client.ts"],"sourcesContent":["export { Nestuge, type NestugeConfig } from './client';\nexport { Nestuge as default } from './client';\n\nexport {\n NestugeError,\n ValidationError,\n AuthenticationError,\n PermissionError,\n NotFoundError,\n RateLimitError,\n ServerError,\n ConnectionError,\n WebhookVerificationError,\n} from './core/errors';\n\nexport {\n verifySignature,\n constructEvent,\n SIGNATURE_HEADER,\n type VerifySignatureParams,\n} from './webhooks/signature';\n\nexport type { Mode, Page, ListParams, PingResponse } from './types/shared';\nexport type { Customer, CustomerListParams } from './types/customers';\nexport type {\n Product,\n ProductDetail,\n ProductTier,\n ProductItem,\n Money,\n ProductEventDetails,\n ProductType,\n ProductVisibility,\n ProductEventType,\n CreateProductParams,\n} from './types/products';\nexport type { Purchase } from './types/purchases';\nexport type { Transaction } from './types/transactions';\nexport type { Ticket } from './types/tickets';\nexport type { HubEvent, CreateEventParams } from './types/events';\nexport type {\n WebhookEventType,\n WebhookEndpointStatus,\n WebhookEndpoint,\n WebhookEndpointWithSecret,\n CreateWebhookParams,\n UpdateWebhookParams,\n TestWebhookParams,\n WebhookResourceType,\n WebhookDeliveryStatus,\n WebhookDelivery,\n WebhookEvent,\n} from './types/webhooks';\n","interface ErrorContext {\n message: string;\n /** HTTP status code, when the server responded. */\n status?: number;\n /** The `code` field from the API error envelope. */\n code?: number;\n /** The `error` field from the API error envelope (detail text). */\n detail?: string;\n}\n\n/** Base class for every error thrown by the SDK. */\nexport class NestugeError extends Error {\n readonly status?: number;\n readonly code?: number;\n readonly detail?: string;\n\n constructor(context: ErrorContext) {\n super(context.message);\n this.name = new.target.name;\n this.status = context.status;\n this.code = context.code;\n this.detail = context.detail;\n }\n}\n\n/** 400 — the request body or parameters failed validation. */\nexport class ValidationError extends NestugeError {}\n\n/** 401 — missing, malformed, or revoked API key. */\nexport class AuthenticationError extends NestugeError {}\n\n/** 403 — the API key lacks a required scope for this endpoint. */\nexport class PermissionError extends NestugeError {}\n\n/** 404 — the resource does not exist or belongs to another brand. */\nexport class NotFoundError extends NestugeError {}\n\n/** 429 — rate limit exceeded (120 requests/minute per key). */\nexport class RateLimitError extends NestugeError {\n /** Seconds to wait before retrying, from the `Retry-After` header. */\n readonly retryAfter?: number;\n\n constructor(context: ErrorContext & { retryAfter?: number }) {\n super(context);\n this.retryAfter = context.retryAfter;\n }\n}\n\n/** 5xx — the API failed to process the request. */\nexport class ServerError extends NestugeError {}\n\n/** The request never reached the API (network failure or timeout). */\nexport class ConnectionError extends NestugeError {}\n\n/** Webhook signature verification failed in `constructEvent`. */\nexport class WebhookVerificationError extends NestugeError {}\n\nexport const errorFromResponse = ({\n status,\n body,\n retryAfter,\n}: {\n status: number;\n body: unknown;\n retryAfter?: number;\n}): NestugeError => {\n const envelope = (body ?? {}) as Record<string, unknown>;\n const context: ErrorContext = {\n message:\n typeof envelope.message === 'string'\n ? envelope.message\n : `Request failed with status ${status}`,\n status,\n code: typeof envelope.code === 'number' ? envelope.code : undefined,\n detail: typeof envelope.error === 'string' ? envelope.error : undefined,\n };\n if (status === 400) return new ValidationError(context);\n if (status === 401) return new AuthenticationError(context);\n if (status === 403) return new PermissionError(context);\n if (status === 404) return new NotFoundError(context);\n if (status === 429) return new RateLimitError({ ...context, retryAfter });\n if (status >= 500) return new ServerError(context);\n return new NestugeError(context);\n};\n","import { ConnectionError, RateLimitError, ServerError, errorFromResponse } from './errors';\n\nexport const API_KEY_HEADER = 'x-nestuge-api';\nexport const DEFAULT_BASE_URL = 'https://nestuge.com';\nexport const DEFAULT_TIMEOUT_MS = 30_000;\nexport const DEFAULT_MAX_RETRIES = 2;\n\nconst API_PREFIX = '/api';\nconst MAX_BACKOFF_MS = 8_000;\n\ntype QueryValue = string | number | boolean | undefined;\nexport type FetchLike = (input: string, init: RequestInit) => Promise<Response>;\n\nexport interface RequestorConfig {\n apiKey: string;\n baseUrl: string;\n maxRetries: number;\n timeoutMs: number;\n fetch: FetchLike;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n /** Contract path, e.g. `/v1/customers/{id}` with params already interpolated. */\n path: string;\n /** Shallow object of query params; undefined values are omitted. */\n query?: object;\n body?: unknown;\n}\n\ninterface Envelope {\n data?: unknown;\n message?: string;\n status?: string;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst backoffMs = (attempt: number): number => {\n const base = Math.min(500 * 2 ** attempt, MAX_BACKOFF_MS);\n return base / 2 + Math.random() * (base / 2);\n};\n\nconst shouldRetry = (error: unknown): boolean =>\n error instanceof ConnectionError ||\n error instanceof RateLimitError ||\n error instanceof ServerError;\n\nconst retryDelayMs = (error: unknown, attempt: number): number => {\n if (error instanceof RateLimitError && error.retryAfter !== undefined) {\n return error.retryAfter * 1000;\n }\n return backoffMs(attempt);\n};\n\nexport class Requestor {\n private readonly config: RequestorConfig;\n\n constructor(config: RequestorConfig) {\n this.config = config;\n }\n\n /** Performs a request against the Dev API and returns the unwrapped `data`. */\n async request<T>(options: RequestOptions): Promise<T> {\n let attempt = 0;\n for (;;) {\n try {\n return await this.dispatch<T>(options);\n } catch (error) {\n if (attempt >= this.config.maxRetries || !shouldRetry(error)) throw error;\n await sleep(retryDelayMs(error, attempt));\n attempt += 1;\n }\n }\n }\n\n private buildUrl({ path, query }: RequestOptions): string {\n const url = new URL(`${API_PREFIX}${path}`, this.config.baseUrl);\n for (const [key, value] of Object.entries(query ?? {}) as [string, QueryValue][]) {\n if (value !== undefined) url.searchParams.set(key, String(value));\n }\n return url.toString();\n }\n\n private async dispatch<T>(options: RequestOptions): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n let response: Response;\n try {\n response = await this.config.fetch(this.buildUrl(options), {\n method: options.method,\n headers: {\n [API_KEY_HEADER]: this.config.apiKey,\n ...(options.body !== undefined && { 'Content-Type': 'application/json' }),\n },\n ...(options.body !== undefined && { body: JSON.stringify(options.body) }),\n signal: controller.signal,\n });\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new ConnectionError({\n message: controller.signal.aborted\n ? `Request timed out after ${this.config.timeoutMs}ms`\n : `Request failed: ${reason}`,\n });\n } finally {\n clearTimeout(timer);\n }\n\n const body = await response.json().catch(() => undefined);\n if (!response.ok) {\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfter = retryAfterHeader ? Number(retryAfterHeader) : undefined;\n throw errorFromResponse({\n status: response.status,\n body,\n retryAfter: Number.isFinite(retryAfter) ? retryAfter : undefined,\n });\n }\n return (body as Envelope)?.data as T;\n }\n}\n","import type { Page } from '../types/shared';\n\n/**\n * Turns a page-fetching function into an async generator that yields every\n * item, transparently following `nextCursor` until the list is exhausted.\n */\nexport async function* paginate<T>(\n fetchPage: (cursor: string | undefined) => Promise<Page<T>>,\n): AsyncGenerator<T, void, undefined> {\n let cursor: string | undefined;\n for (;;) {\n const page = await fetchPage(cursor);\n yield* page.items;\n if (!page.hasMore || page.nextCursor === null) return;\n cursor = page.nextCursor;\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { Customer, CustomerListParams } from '../types/customers';\nimport type { Page } from '../types/shared';\n\nexport class Customers {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's hub members, newest first. Requires `customers:read`. */\n list(params: CustomerListParams = {}): Promise<Page<Customer>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/customers',\n query: params,\n });\n }\n\n /** Returns a single hub membership by its membership id. */\n retrieve(id: string): Promise<Customer> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/customers/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every customer, following pagination cursors automatically. */\n iterate(params: Omit<CustomerListParams, 'cursor'> = {}): AsyncGenerator<Customer> {\n return paginate((cursor) => this.list({ ...params, cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { CreateEventParams, HubEvent } from '../types/events';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Events {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's hub community events, newest first. Requires `events:read`. */\n list(params: ListParams = {}): Promise<Page<HubEvent>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/events',\n query: params,\n });\n }\n\n /** Returns a single hub event owned by the brand. */\n retrieve(id: string): Promise<HubEvent> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/events/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Creates a hub event in one of the brand's hubs. Requires `events:write`\n * and the brand to have Google Calendar connected.\n */\n create(params: CreateEventParams): Promise<HubEvent> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/events',\n body: params,\n });\n }\n\n /** Iterates every event, following pagination cursors automatically. */\n iterate(): AsyncGenerator<HubEvent> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type {\n CreateProductParams,\n Product,\n ProductDetail,\n} from '../types/products';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Products {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's products (all types), newest first. Requires `products:read`. */\n list(params: ListParams = {}): Promise<Page<Product>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/products',\n query: params,\n });\n }\n\n /**\n * Returns a single product owned by the brand, including its pricing\n * tiers and content items.\n */\n retrieve(id: string): Promise<ProductDetail> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/products/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Creates a draft product. Requires `products:write`. Test-mode keys\n * validate and return a preview without persisting.\n */\n create(params: CreateProductParams): Promise<Product> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/products',\n body: params,\n });\n }\n\n /** Iterates every product, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Product> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { Purchase } from '../types/purchases';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Purchases {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's purchases/orders, newest first. Requires `purchases:read`. */\n list(params: ListParams = {}): Promise<Page<Purchase>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/purchases',\n query: params,\n });\n }\n\n /** Returns a single purchase/order by id. */\n retrieve(id: string): Promise<Purchase> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/purchases/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every purchase, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Purchase> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import type { Requestor } from '../core/request';\nimport type { Ticket } from '../types/tickets';\n\nexport class Tickets {\n constructor(private readonly requestor: Requestor) {}\n\n /** Returns a single event ticket by ticket id. Requires `purchases:read`. */\n retrieve(id: string): Promise<Ticket> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/tickets/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Checks in an event attendee by ticket id. Requires `purchases:write`.\n * Test-mode keys validate and return the checked-in ticket without persisting.\n */\n checkIn(id: string): Promise<Ticket> {\n return this.requestor.request({\n method: 'POST',\n path: `/v1/tickets/${encodeURIComponent(id)}/checkin`,\n });\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { ListParams, Page } from '../types/shared';\nimport type { Transaction } from '../types/transactions';\n\nexport class Transactions {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's transactions, newest first. Requires `transactions:read`. */\n list(params: ListParams = {}): Promise<Page<Transaction>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/transactions',\n query: params,\n });\n }\n\n /** Returns a single transaction by its reference (`txref`). */\n retrieve(id: string): Promise<Transaction> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/transactions/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every transaction, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Transaction> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { WebhookVerificationError } from '../core/errors';\nimport type { WebhookEvent } from '../types/webhooks';\n\nexport const SIGNATURE_HEADER = 'X-Nestuge-Signature';\nconst SIGNATURE_PREFIX = 'sha256=';\n\n/**\n * Web Crypto is global on Node 19+, Bun, Deno, browsers, and edge runtimes;\n * on Node 18 it lives at node:crypto's `webcrypto`.\n */\nconst getSubtle = async (): Promise<SubtleCrypto> => {\n if (globalThis.crypto?.subtle) return globalThis.crypto.subtle;\n const nodeCrypto = await import('node:crypto');\n return (nodeCrypto.webcrypto as unknown as Crypto).subtle;\n};\n\nconst toHex = (buffer: ArrayBuffer): string =>\n [...new Uint8Array(buffer)].map((b) => b.toString(16).padStart(2, '0')).join('');\n\n/** Comparison time depends only on input length, not on where they differ. */\nconst constantTimeEqual = (a: string, b: string): boolean => {\n if (a.length !== b.length) return false;\n let mismatch = 0;\n for (let i = 0; i < a.length; i += 1) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n};\n\nconst hmacHex = async (payload: string, secret: string): Promise<string> => {\n const subtle = await getSubtle();\n const encoder = new TextEncoder();\n const key = await subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return toHex(await subtle.sign('HMAC', key, encoder.encode(payload)));\n};\n\nexport interface VerifySignatureParams {\n /** The raw, unmodified request body string (not re-serialized JSON). */\n payload: string;\n /** Value of the `X-Nestuge-Signature` header (`sha256=<hex>`). */\n signature: string;\n /** The endpoint's signing secret, returned once by `webhooks.create()`. */\n secret: string;\n}\n\n/** Verifies a webhook signature with a timing-safe HMAC-SHA256 comparison. */\nexport const verifySignature = async ({\n payload,\n signature,\n secret,\n}: VerifySignatureParams): Promise<boolean> => {\n const expected = `${SIGNATURE_PREFIX}${await hmacHex(payload, secret)}`;\n return constantTimeEqual(expected, signature);\n};\n\n/**\n * Verifies the signature and parses the payload into a typed `WebhookEvent`.\n * Throws `WebhookVerificationError` on a bad signature or unparseable body.\n */\nexport const constructEvent = async (\n params: VerifySignatureParams,\n): Promise<WebhookEvent> => {\n if (!params.signature.startsWith(SIGNATURE_PREFIX)) {\n throw new WebhookVerificationError({\n message: `Signature header must start with \"${SIGNATURE_PREFIX}\"`,\n });\n }\n if (!(await verifySignature(params))) {\n throw new WebhookVerificationError({\n message: 'Webhook signature verification failed',\n });\n }\n try {\n return JSON.parse(params.payload) as WebhookEvent;\n } catch {\n throw new WebhookVerificationError({\n message: 'Webhook payload is not valid JSON',\n });\n }\n};\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { ListParams, Page } from '../types/shared';\nimport type {\n CreateWebhookParams,\n TestWebhookParams,\n UpdateWebhookParams,\n WebhookDelivery,\n WebhookEndpoint,\n WebhookEndpointWithSecret,\n WebhookEvent,\n} from '../types/webhooks';\nimport {\n constructEvent,\n verifySignature,\n type VerifySignatureParams,\n} from '../webhooks/signature';\n\n/** All webhook endpoints require the `webhooks:write` scope. */\nexport class Webhooks {\n readonly deliveries: WebhookDeliveries;\n\n constructor(private readonly requestor: Requestor) {\n this.deliveries = new WebhookDeliveries(requestor);\n }\n\n /**\n * Registers an HTTPS endpoint URL. The returned `signingSecret` is shown\n * once in this response and can never be retrieved again.\n */\n create(params: CreateWebhookParams): Promise<WebhookEndpointWithSecret> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/webhooks',\n body: params,\n });\n }\n\n /** Lists the brand's webhook endpoints. */\n list(params: ListParams = {}): Promise<Page<WebhookEndpoint>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/webhooks',\n query: params,\n });\n }\n\n /** Returns a single webhook endpoint. */\n retrieve(id: string): Promise<WebhookEndpoint> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n });\n }\n\n /** Updates a webhook endpoint's URL, events, status, or description. */\n update(id: string, params: UpdateWebhookParams): Promise<WebhookEndpoint> {\n return this.requestor.request({\n method: 'PATCH',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n body: params,\n });\n }\n\n /** Deletes a webhook endpoint. */\n del(id: string): Promise<{ id: string; deleted: boolean }> {\n return this.requestor.request({\n method: 'DELETE',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Synthesizes a sample event and delivers it through the real\n * signed/retried/logged pipeline as a test-mode delivery.\n */\n test(params: TestWebhookParams): Promise<{ created: number }> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/webhooks/test',\n body: params,\n });\n }\n\n /** Iterates every webhook endpoint, following pagination cursors automatically. */\n iterate(): AsyncGenerator<WebhookEndpoint> {\n return paginate((cursor) => this.list({ cursor }));\n }\n\n /**\n * Verifies an incoming webhook's `X-Nestuge-Signature` header with a\n * timing-safe HMAC-SHA256 comparison over the raw request body.\n */\n verifySignature(params: VerifySignatureParams): Promise<boolean> {\n return verifySignature(params);\n }\n\n /**\n * Verifies the signature and returns the parsed, typed event. Throws\n * `WebhookVerificationError` if verification fails.\n */\n constructEvent(params: VerifySignatureParams): Promise<WebhookEvent> {\n return constructEvent(params);\n }\n}\n\nexport class WebhookDeliveries {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists webhook delivery attempts, newest first. */\n list(params: ListParams = {}): Promise<Page<WebhookDelivery>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/webhooks/deliveries',\n query: params,\n });\n }\n\n /** Returns a single delivery record. */\n retrieve(id: string): Promise<WebhookDelivery> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/webhooks/deliveries/${encodeURIComponent(id)}`,\n });\n }\n\n /** Re-queues a delivery as a fresh attempt; the original record is preserved. */\n resend(id: string): Promise<WebhookDelivery> {\n return this.requestor.request({\n method: 'POST',\n path: `/v1/webhooks/deliveries/${encodeURIComponent(id)}/resend`,\n });\n }\n\n /** Iterates every delivery record, following pagination cursors automatically. */\n iterate(): AsyncGenerator<WebhookDelivery> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n Requestor,\n type FetchLike,\n} from './core/request';\nimport { Customers } from './resources/customers';\nimport { Events } from './resources/events';\nimport { Products } from './resources/products';\nimport { Purchases } from './resources/purchases';\nimport { Tickets } from './resources/tickets';\nimport { Transactions } from './resources/transactions';\nimport { Webhooks } from './resources/webhooks';\nimport type { PingResponse } from './types/shared';\n\nexport interface NestugeConfig {\n /** Brand API key (`nk_live_…` or `nk_test_…`) from Settings → Developer. */\n apiKey: string;\n /** API origin. Defaults to `https://nestuge.com`. */\n baseUrl?: string;\n /** Extra retry attempts on 429/5xx/network errors. Defaults to 2. */\n maxRetries?: number;\n /** Per-attempt timeout in milliseconds. Defaults to 30000. */\n timeoutMs?: number;\n /** Custom fetch implementation (testing, proxies). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\nexport class Nestuge {\n readonly customers: Customers;\n readonly products: Products;\n readonly purchases: Purchases;\n readonly transactions: Transactions;\n readonly events: Events;\n readonly tickets: Tickets;\n readonly webhooks: Webhooks;\n\n private readonly requestor: Requestor;\n\n constructor(config: NestugeConfig) {\n if (!config?.apiKey) {\n throw new Error(\n 'Nestuge: an apiKey is required. Create one under Settings → Developer.',\n );\n }\n this.requestor = new Requestor({\n apiKey: config.apiKey,\n baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n fetch:\n config.fetch ??\n ((input, init) => globalThis.fetch(input, init)),\n });\n this.customers = new Customers(this.requestor);\n this.products = new Products(this.requestor);\n this.purchases = new Purchases(this.requestor);\n this.transactions = new Transactions(this.requestor);\n this.events = new Events(this.requestor);\n this.tickets = new Tickets(this.requestor);\n this.webhooks = new Webhooks(this.requestor);\n }\n\n /**\n * Authenticated health check: confirms the key works and returns the\n * resolved brand, key mode, and granted scopes. No scope required.\n */\n ping(): Promise<PingResponse> {\n return this.requestor.request({ method: 'GET', path: '/v1/ping' });\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/errors.ts","../src/core/request.ts","../src/core/pagination.ts","../src/resources/customers.ts","../src/resources/events.ts","../src/resources/products.ts","../src/resources/purchases.ts","../src/resources/tickets.ts","../src/resources/transactions.ts","../src/webhooks/signature.ts","../src/resources/webhooks.ts","../src/client.ts"],"sourcesContent":["export { Nestuge, type NestugeConfig } from './client';\nexport { Nestuge as default } from './client';\n\nexport {\n NestugeError,\n ValidationError,\n AuthenticationError,\n PermissionError,\n NotFoundError,\n RateLimitError,\n ServerError,\n ConnectionError,\n WebhookVerificationError,\n} from './core/errors';\n\nexport {\n verifySignature,\n constructEvent,\n SIGNATURE_HEADER,\n type VerifySignatureParams,\n} from './webhooks/signature';\n\nexport type { Mode, Page, ListParams, PingResponse } from './types/shared';\nexport type { Customer, CustomerListParams } from './types/customers';\nexport type {\n Product,\n ProductDetail,\n ProductTier,\n ProductItem,\n Money,\n ProductEventDetails,\n ProductType,\n ProductVisibility,\n ProductEventType,\n CreateProductParams,\n CreateProductItemParams,\n} from './types/products';\nexport type { Purchase } from './types/purchases';\nexport type { Transaction } from './types/transactions';\nexport type { Ticket } from './types/tickets';\nexport type { HubEvent, CreateEventParams } from './types/events';\nexport type {\n WebhookEventType,\n WebhookEndpointStatus,\n WebhookEndpoint,\n WebhookEndpointWithSecret,\n CreateWebhookParams,\n UpdateWebhookParams,\n TestWebhookParams,\n WebhookResourceType,\n WebhookDeliveryStatus,\n WebhookDelivery,\n WebhookEvent,\n} from './types/webhooks';\n","interface ErrorContext {\n message: string;\n /** HTTP status code, when the server responded. */\n status?: number;\n /** The `code` field from the API error envelope. */\n code?: number;\n /** The `error` field from the API error envelope (detail text). */\n detail?: string;\n}\n\n/** Base class for every error thrown by the SDK. */\nexport class NestugeError extends Error {\n readonly status?: number;\n readonly code?: number;\n readonly detail?: string;\n\n constructor(context: ErrorContext) {\n super(context.message);\n this.name = new.target.name;\n this.status = context.status;\n this.code = context.code;\n this.detail = context.detail;\n }\n}\n\n/** 400 — the request body or parameters failed validation. */\nexport class ValidationError extends NestugeError {}\n\n/** 401 — missing, malformed, or revoked API key. */\nexport class AuthenticationError extends NestugeError {}\n\n/** 403 — the API key lacks a required scope for this endpoint. */\nexport class PermissionError extends NestugeError {}\n\n/** 404 — the resource does not exist or belongs to another brand. */\nexport class NotFoundError extends NestugeError {}\n\n/** 429 — rate limit exceeded (120 requests/minute per key). */\nexport class RateLimitError extends NestugeError {\n /** Seconds to wait before retrying, from the `Retry-After` header. */\n readonly retryAfter?: number;\n\n constructor(context: ErrorContext & { retryAfter?: number }) {\n super(context);\n this.retryAfter = context.retryAfter;\n }\n}\n\n/** 5xx — the API failed to process the request. */\nexport class ServerError extends NestugeError {}\n\n/** The request never reached the API (network failure or timeout). */\nexport class ConnectionError extends NestugeError {}\n\n/** Webhook signature verification failed in `constructEvent`. */\nexport class WebhookVerificationError extends NestugeError {}\n\n/**\n * The envelope's `error` field is either a plain string or an array of\n * validation issues ({ path, message }); flatten either into one readable line.\n */\nconst detailFromEnvelope = (error: unknown): string | undefined => {\n if (typeof error === 'string') return error;\n if (!Array.isArray(error)) return undefined;\n const parts = error\n .map((issue) => {\n if (typeof issue === 'string') return issue;\n if (issue && typeof issue === 'object') {\n const { path, message } = issue as { path?: unknown; message?: unknown };\n if (typeof message !== 'string') return undefined;\n const segments = Array.isArray(path) ? path.map(String) : [];\n const leaf = segments[segments.length - 1];\n // Zod messages usually name the field already — avoid \"x: x must be…\"\n return leaf && !message.includes(leaf)\n ? `${segments.join('.')}: ${message}`\n : message;\n }\n return undefined;\n })\n .filter((part): part is string => Boolean(part));\n return parts.length > 0 ? parts.join('; ') : undefined;\n};\n\nexport const errorFromResponse = ({\n status,\n body,\n retryAfter,\n}: {\n status: number;\n body: unknown;\n retryAfter?: number;\n}): NestugeError => {\n const envelope = (body ?? {}) as Record<string, unknown>;\n const context: ErrorContext = {\n message:\n typeof envelope.message === 'string'\n ? envelope.message\n : `Request failed with status ${status}`,\n status,\n code: typeof envelope.code === 'number' ? envelope.code : undefined,\n detail: detailFromEnvelope(envelope.error),\n };\n if (status === 400) return new ValidationError(context);\n if (status === 401) return new AuthenticationError(context);\n if (status === 403) return new PermissionError(context);\n if (status === 404) return new NotFoundError(context);\n if (status === 429) return new RateLimitError({ ...context, retryAfter });\n if (status >= 500) return new ServerError(context);\n return new NestugeError(context);\n};\n","import { ConnectionError, RateLimitError, ServerError, errorFromResponse } from './errors';\n\nexport const API_KEY_HEADER = 'x-nestuge-api';\nexport const DEFAULT_BASE_URL = 'https://nestuge.com';\nexport const DEFAULT_TIMEOUT_MS = 30_000;\nexport const DEFAULT_MAX_RETRIES = 2;\n\nconst API_PREFIX = '/api';\nconst MAX_BACKOFF_MS = 8_000;\n\ntype QueryValue = string | number | boolean | undefined;\nexport type FetchLike = (input: string, init: RequestInit) => Promise<Response>;\n\nexport interface RequestorConfig {\n apiKey: string;\n baseUrl: string;\n maxRetries: number;\n timeoutMs: number;\n fetch: FetchLike;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n /** Contract path, e.g. `/v1/customers/{id}` with params already interpolated. */\n path: string;\n /** Shallow object of query params; undefined values are omitted. */\n query?: object;\n body?: unknown;\n}\n\ninterface Envelope {\n data?: unknown;\n message?: string;\n status?: string;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst backoffMs = (attempt: number): number => {\n const base = Math.min(500 * 2 ** attempt, MAX_BACKOFF_MS);\n return base / 2 + Math.random() * (base / 2);\n};\n\nconst shouldRetry = (error: unknown): boolean =>\n error instanceof ConnectionError ||\n error instanceof RateLimitError ||\n error instanceof ServerError;\n\nconst retryDelayMs = (error: unknown, attempt: number): number => {\n if (error instanceof RateLimitError && error.retryAfter !== undefined) {\n return error.retryAfter * 1000;\n }\n return backoffMs(attempt);\n};\n\nexport class Requestor {\n private readonly config: RequestorConfig;\n\n constructor(config: RequestorConfig) {\n this.config = config;\n }\n\n /** Performs a request against the Dev API and returns the unwrapped `data`. */\n async request<T>(options: RequestOptions): Promise<T> {\n let attempt = 0;\n for (;;) {\n try {\n return await this.dispatch<T>(options);\n } catch (error) {\n if (attempt >= this.config.maxRetries || !shouldRetry(error)) throw error;\n await sleep(retryDelayMs(error, attempt));\n attempt += 1;\n }\n }\n }\n\n private buildUrl({ path, query }: RequestOptions): string {\n const url = new URL(`${API_PREFIX}${path}`, this.config.baseUrl);\n for (const [key, value] of Object.entries(query ?? {}) as [string, QueryValue][]) {\n if (value !== undefined) url.searchParams.set(key, String(value));\n }\n return url.toString();\n }\n\n private async dispatch<T>(options: RequestOptions): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n let response: Response;\n try {\n response = await this.config.fetch(this.buildUrl(options), {\n method: options.method,\n headers: {\n [API_KEY_HEADER]: this.config.apiKey,\n ...(options.body !== undefined && { 'Content-Type': 'application/json' }),\n },\n ...(options.body !== undefined && { body: JSON.stringify(options.body) }),\n signal: controller.signal,\n });\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new ConnectionError({\n message: controller.signal.aborted\n ? `Request timed out after ${this.config.timeoutMs}ms`\n : `Request failed: ${reason}`,\n });\n } finally {\n clearTimeout(timer);\n }\n\n const body = await response.json().catch(() => undefined);\n if (!response.ok) {\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfter = retryAfterHeader ? Number(retryAfterHeader) : undefined;\n throw errorFromResponse({\n status: response.status,\n body,\n retryAfter: Number.isFinite(retryAfter) ? retryAfter : undefined,\n });\n }\n return (body as Envelope)?.data as T;\n }\n}\n","import type { Page } from '../types/shared';\n\n/**\n * Turns a page-fetching function into an async generator that yields every\n * item, transparently following `nextCursor` until the list is exhausted.\n */\nexport async function* paginate<T>(\n fetchPage: (cursor: string | undefined) => Promise<Page<T>>,\n): AsyncGenerator<T, void, undefined> {\n let cursor: string | undefined;\n for (;;) {\n const page = await fetchPage(cursor);\n yield* page.items;\n if (!page.hasMore || page.nextCursor === null) return;\n cursor = page.nextCursor;\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { Customer, CustomerListParams } from '../types/customers';\nimport type { Page } from '../types/shared';\n\nexport class Customers {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's hub members, newest first. Requires `customers:read`. */\n list(params: CustomerListParams = {}): Promise<Page<Customer>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/customers',\n query: params,\n });\n }\n\n /** Returns a single hub membership by its membership id. */\n retrieve(id: string): Promise<Customer> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/customers/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every customer, following pagination cursors automatically. */\n iterate(params: Omit<CustomerListParams, 'cursor'> = {}): AsyncGenerator<Customer> {\n return paginate((cursor) => this.list({ ...params, cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { CreateEventParams, HubEvent } from '../types/events';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Events {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's hub community events, newest first. Requires `events:read`. */\n list(params: ListParams = {}): Promise<Page<HubEvent>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/events',\n query: params,\n });\n }\n\n /** Returns a single hub event owned by the brand. */\n retrieve(id: string): Promise<HubEvent> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/events/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Creates a hub event in one of the brand's hubs. Requires `events:write`\n * and the brand to have Google Calendar connected.\n */\n create(params: CreateEventParams): Promise<HubEvent> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/events',\n body: params,\n });\n }\n\n /** Iterates every event, following pagination cursors automatically. */\n iterate(): AsyncGenerator<HubEvent> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type {\n CreateProductParams,\n Product,\n ProductDetail,\n} from '../types/products';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Products {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's products (all types), newest first. Requires `products:read`. */\n list(params: ListParams = {}): Promise<Page<Product>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/products',\n query: params,\n });\n }\n\n /**\n * Returns a single product owned by the brand, including its pricing\n * tiers and content items.\n */\n retrieve(id: string): Promise<ProductDetail> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/products/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Creates a draft product, optionally with content items. Requires\n * `products:write`. Returns the product with its pricing tiers and items.\n * Test-mode keys validate and return a preview without persisting.\n */\n create(params: CreateProductParams): Promise<ProductDetail> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/products',\n body: params,\n });\n }\n\n /** Iterates every product, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Product> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { Purchase } from '../types/purchases';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Purchases {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's purchases/orders, newest first. Requires `purchases:read`. */\n list(params: ListParams = {}): Promise<Page<Purchase>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/purchases',\n query: params,\n });\n }\n\n /** Returns a single purchase/order by id. */\n retrieve(id: string): Promise<Purchase> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/purchases/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every purchase, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Purchase> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import type { Requestor } from '../core/request';\nimport type { Ticket } from '../types/tickets';\n\nexport class Tickets {\n constructor(private readonly requestor: Requestor) {}\n\n /** Returns a single event ticket by ticket id. Requires `purchases:read`. */\n retrieve(id: string): Promise<Ticket> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/tickets/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Checks in an event attendee by ticket id. Requires `purchases:write`.\n * Test-mode keys validate and return the checked-in ticket without persisting.\n */\n checkIn(id: string): Promise<Ticket> {\n return this.requestor.request({\n method: 'POST',\n path: `/v1/tickets/${encodeURIComponent(id)}/checkin`,\n });\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { ListParams, Page } from '../types/shared';\nimport type { Transaction } from '../types/transactions';\n\nexport class Transactions {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's transactions, newest first. Requires `transactions:read`. */\n list(params: ListParams = {}): Promise<Page<Transaction>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/transactions',\n query: params,\n });\n }\n\n /** Returns a single transaction by its reference (`txref`). */\n retrieve(id: string): Promise<Transaction> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/transactions/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every transaction, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Transaction> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { WebhookVerificationError } from '../core/errors';\nimport type { WebhookEvent } from '../types/webhooks';\n\nexport const SIGNATURE_HEADER = 'X-Nestuge-Signature';\nconst SIGNATURE_PREFIX = 'sha256=';\n\n/**\n * Web Crypto is global on Node 19+, Bun, Deno, browsers, and edge runtimes;\n * on Node 18 it lives at node:crypto's `webcrypto`.\n */\nconst getSubtle = async (): Promise<SubtleCrypto> => {\n if (globalThis.crypto?.subtle) return globalThis.crypto.subtle;\n const nodeCrypto = await import('node:crypto');\n return (nodeCrypto.webcrypto as unknown as Crypto).subtle;\n};\n\nconst toHex = (buffer: ArrayBuffer): string =>\n [...new Uint8Array(buffer)].map((b) => b.toString(16).padStart(2, '0')).join('');\n\n/** Comparison time depends only on input length, not on where they differ. */\nconst constantTimeEqual = (a: string, b: string): boolean => {\n if (a.length !== b.length) return false;\n let mismatch = 0;\n for (let i = 0; i < a.length; i += 1) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n};\n\nconst hmacHex = async (payload: string, secret: string): Promise<string> => {\n const subtle = await getSubtle();\n const encoder = new TextEncoder();\n const key = await subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return toHex(await subtle.sign('HMAC', key, encoder.encode(payload)));\n};\n\nexport interface VerifySignatureParams {\n /** The raw, unmodified request body string (not re-serialized JSON). */\n payload: string;\n /** Value of the `X-Nestuge-Signature` header (`sha256=<hex>`). */\n signature: string;\n /** The endpoint's signing secret, returned once by `webhooks.create()`. */\n secret: string;\n}\n\n/** Verifies a webhook signature with a timing-safe HMAC-SHA256 comparison. */\nexport const verifySignature = async ({\n payload,\n signature,\n secret,\n}: VerifySignatureParams): Promise<boolean> => {\n const expected = `${SIGNATURE_PREFIX}${await hmacHex(payload, secret)}`;\n return constantTimeEqual(expected, signature);\n};\n\n/**\n * Verifies the signature and parses the payload into a typed `WebhookEvent`.\n * Throws `WebhookVerificationError` on a bad signature or unparseable body.\n */\nexport const constructEvent = async (\n params: VerifySignatureParams,\n): Promise<WebhookEvent> => {\n if (!params.signature.startsWith(SIGNATURE_PREFIX)) {\n throw new WebhookVerificationError({\n message: `Signature header must start with \"${SIGNATURE_PREFIX}\"`,\n });\n }\n if (!(await verifySignature(params))) {\n throw new WebhookVerificationError({\n message: 'Webhook signature verification failed',\n });\n }\n try {\n return JSON.parse(params.payload) as WebhookEvent;\n } catch {\n throw new WebhookVerificationError({\n message: 'Webhook payload is not valid JSON',\n });\n }\n};\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { ListParams, Page } from '../types/shared';\nimport type {\n CreateWebhookParams,\n TestWebhookParams,\n UpdateWebhookParams,\n WebhookDelivery,\n WebhookEndpoint,\n WebhookEndpointWithSecret,\n WebhookEvent,\n} from '../types/webhooks';\nimport {\n constructEvent,\n verifySignature,\n type VerifySignatureParams,\n} from '../webhooks/signature';\n\n/** All webhook endpoints require the `webhooks:write` scope. */\nexport class Webhooks {\n readonly deliveries: WebhookDeliveries;\n\n constructor(private readonly requestor: Requestor) {\n this.deliveries = new WebhookDeliveries(requestor);\n }\n\n /**\n * Registers an HTTPS endpoint URL. The returned `signingSecret` is shown\n * once in this response and can never be retrieved again.\n */\n create(params: CreateWebhookParams): Promise<WebhookEndpointWithSecret> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/webhooks',\n body: params,\n });\n }\n\n /** Lists the brand's webhook endpoints. */\n list(params: ListParams = {}): Promise<Page<WebhookEndpoint>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/webhooks',\n query: params,\n });\n }\n\n /** Returns a single webhook endpoint. */\n retrieve(id: string): Promise<WebhookEndpoint> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n });\n }\n\n /** Updates a webhook endpoint's URL, events, status, or description. */\n update(id: string, params: UpdateWebhookParams): Promise<WebhookEndpoint> {\n return this.requestor.request({\n method: 'PATCH',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n body: params,\n });\n }\n\n /** Deletes a webhook endpoint. */\n del(id: string): Promise<{ id: string; deleted: boolean }> {\n return this.requestor.request({\n method: 'DELETE',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Synthesizes a sample event and delivers it through the real\n * signed/retried/logged pipeline as a test-mode delivery.\n */\n test(params: TestWebhookParams): Promise<{ created: number }> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/webhooks/test',\n body: params,\n });\n }\n\n /** Iterates every webhook endpoint, following pagination cursors automatically. */\n iterate(): AsyncGenerator<WebhookEndpoint> {\n return paginate((cursor) => this.list({ cursor }));\n }\n\n /**\n * Verifies an incoming webhook's `X-Nestuge-Signature` header with a\n * timing-safe HMAC-SHA256 comparison over the raw request body.\n */\n verifySignature(params: VerifySignatureParams): Promise<boolean> {\n return verifySignature(params);\n }\n\n /**\n * Verifies the signature and returns the parsed, typed event. Throws\n * `WebhookVerificationError` if verification fails.\n */\n constructEvent(params: VerifySignatureParams): Promise<WebhookEvent> {\n return constructEvent(params);\n }\n}\n\nexport class WebhookDeliveries {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists webhook delivery attempts, newest first. */\n list(params: ListParams = {}): Promise<Page<WebhookDelivery>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/webhooks/deliveries',\n query: params,\n });\n }\n\n /** Returns a single delivery record. */\n retrieve(id: string): Promise<WebhookDelivery> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/webhooks/deliveries/${encodeURIComponent(id)}`,\n });\n }\n\n /** Re-queues a delivery as a fresh attempt; the original record is preserved. */\n resend(id: string): Promise<WebhookDelivery> {\n return this.requestor.request({\n method: 'POST',\n path: `/v1/webhooks/deliveries/${encodeURIComponent(id)}/resend`,\n });\n }\n\n /** Iterates every delivery record, following pagination cursors automatically. */\n iterate(): AsyncGenerator<WebhookDelivery> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n Requestor,\n type FetchLike,\n} from './core/request';\nimport { Customers } from './resources/customers';\nimport { Events } from './resources/events';\nimport { Products } from './resources/products';\nimport { Purchases } from './resources/purchases';\nimport { Tickets } from './resources/tickets';\nimport { Transactions } from './resources/transactions';\nimport { Webhooks } from './resources/webhooks';\nimport type { PingResponse } from './types/shared';\n\nexport interface NestugeConfig {\n /** Brand API key (`nk_live_…` or `nk_test_…`) from Settings → Developer. */\n apiKey: string;\n /** API origin. Defaults to `https://nestuge.com`. */\n baseUrl?: string;\n /** Extra retry attempts on 429/5xx/network errors. Defaults to 2. */\n maxRetries?: number;\n /** Per-attempt timeout in milliseconds. Defaults to 30000. */\n timeoutMs?: number;\n /** Custom fetch implementation (testing, proxies). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\nexport class Nestuge {\n readonly customers: Customers;\n readonly products: Products;\n readonly purchases: Purchases;\n readonly transactions: Transactions;\n readonly events: Events;\n readonly tickets: Tickets;\n readonly webhooks: Webhooks;\n\n private readonly requestor: Requestor;\n\n constructor(config: NestugeConfig) {\n if (!config?.apiKey) {\n throw new Error(\n 'Nestuge: an apiKey is required. Create one under Settings → Developer.',\n );\n }\n this.requestor = new Requestor({\n apiKey: config.apiKey,\n baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n fetch:\n config.fetch ??\n ((input, init) => globalThis.fetch(input, init)),\n });\n this.customers = new Customers(this.requestor);\n this.products = new Products(this.requestor);\n this.purchases = new Purchases(this.requestor);\n this.transactions = new Transactions(this.requestor);\n this.events = new Events(this.requestor);\n this.tickets = new Tickets(this.requestor);\n this.webhooks = new Webhooks(this.requestor);\n }\n\n /**\n * Authenticated health check: confirms the key works and returns the\n * resolved brand, key mode, and granted scopes. No scope required.\n */\n ping(): Promise<PingResponse> {\n return this.requestor.request({ method: 'GET', path: '/v1/ping' });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACWO,IAAM,eAAN,cAA2B,MAAM;AAAA,EAKtC,YAAY,SAAuB;AACjC,UAAM,QAAQ,OAAO;AACrB,SAAK,OAAO,WAAW;AACvB,SAAK,SAAS,QAAQ;AACtB,SAAK,OAAO,QAAQ;AACpB,SAAK,SAAS,QAAQ;AAAA,EACxB;AACF;AAGO,IAAM,kBAAN,cAA8B,aAAa;AAAC;AAG5C,IAAM,sBAAN,cAAkC,aAAa;AAAC;AAGhD,IAAM,kBAAN,cAA8B,aAAa;AAAC;AAG5C,IAAM,gBAAN,cAA4B,aAAa;AAAC;AAG1C,IAAM,iBAAN,cAA6B,aAAa;AAAA,EAI/C,YAAY,SAAiD;AAC3D,UAAM,OAAO;AACb,SAAK,aAAa,QAAQ;AAAA,EAC5B;AACF;AAGO,IAAM,cAAN,cAA0B,aAAa;AAAC;AAGxC,IAAM,kBAAN,cAA8B,aAAa;AAAC;AAG5C,IAAM,2BAAN,cAAuC,aAAa;AAAC;AAM5D,IAAM,qBAAqB,CAAC,UAAuC;AACjE,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,QAAQ,MACX,IAAI,CAAC,UAAU;AACd,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAI,SAAS,OAAO,UAAU,UAAU;AACtC,YAAM,EAAE,MAAM,QAAQ,IAAI;AAC1B,UAAI,OAAO,YAAY,SAAU,QAAO;AACxC,YAAM,WAAW,MAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,MAAM,IAAI,CAAC;AAC3D,YAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AAEzC,aAAO,QAAQ,CAAC,QAAQ,SAAS,IAAI,IACjC,GAAG,SAAS,KAAK,GAAG,CAAC,KAAK,OAAO,KACjC;AAAA,IACN;AACA,WAAO;AAAA,EACT,CAAC,EACA,OAAO,CAAC,SAAyB,QAAQ,IAAI,CAAC;AACjD,SAAO,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI;AAC/C;AAEO,IAAM,oBAAoB,CAAC;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACF,MAIoB;AAClB,QAAM,WAAY,QAAQ,CAAC;AAC3B,QAAM,UAAwB;AAAA,IAC5B,SACE,OAAO,SAAS,YAAY,WACxB,SAAS,UACT,8BAA8B,MAAM;AAAA,IAC1C;AAAA,IACA,MAAM,OAAO,SAAS,SAAS,WAAW,SAAS,OAAO;AAAA,IAC1D,QAAQ,mBAAmB,SAAS,KAAK;AAAA,EAC3C;AACA,MAAI,WAAW,IAAK,QAAO,IAAI,gBAAgB,OAAO;AACtD,MAAI,WAAW,IAAK,QAAO,IAAI,oBAAoB,OAAO;AAC1D,MAAI,WAAW,IAAK,QAAO,IAAI,gBAAgB,OAAO;AACtD,MAAI,WAAW,IAAK,QAAO,IAAI,cAAc,OAAO;AACpD,MAAI,WAAW,IAAK,QAAO,IAAI,eAAe,EAAE,GAAG,SAAS,WAAW,CAAC;AACxE,MAAI,UAAU,IAAK,QAAO,IAAI,YAAY,OAAO;AACjD,SAAO,IAAI,aAAa,OAAO;AACjC;;;AC3GO,IAAM,iBAAiB;AACvB,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAEnC,IAAM,aAAa;AACnB,IAAM,iBAAiB;AA4BvB,IAAM,QAAQ,CAAC,OAAe,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAE9E,IAAM,YAAY,CAAC,YAA4B;AAC7C,QAAM,OAAO,KAAK,IAAI,MAAM,KAAK,SAAS,cAAc;AACxD,SAAO,OAAO,IAAI,KAAK,OAAO,KAAK,OAAO;AAC5C;AAEA,IAAM,cAAc,CAAC,UACnB,iBAAiB,mBACjB,iBAAiB,kBACjB,iBAAiB;AAEnB,IAAM,eAAe,CAAC,OAAgB,YAA4B;AAChE,MAAI,iBAAiB,kBAAkB,MAAM,eAAe,QAAW;AACrE,WAAO,MAAM,aAAa;AAAA,EAC5B;AACA,SAAO,UAAU,OAAO;AAC1B;AAEO,IAAM,YAAN,MAAgB;AAAA,EAGrB,YAAY,QAAyB;AACnC,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA,EAGA,MAAM,QAAW,SAAqC;AACpD,QAAI,UAAU;AACd,eAAS;AACP,UAAI;AACF,eAAO,MAAM,KAAK,SAAY,OAAO;AAAA,MACvC,SAAS,OAAO;AACd,YAAI,WAAW,KAAK,OAAO,cAAc,CAAC,YAAY,KAAK,EAAG,OAAM;AACpE,cAAM,MAAM,aAAa,OAAO,OAAO,CAAC;AACxC,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,SAAS,EAAE,MAAM,MAAM,GAA2B;AACxD,UAAM,MAAM,IAAI,IAAI,GAAG,UAAU,GAAG,IAAI,IAAI,KAAK,OAAO,OAAO;AAC/D,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,CAAC,CAAC,GAA6B;AAChF,UAAI,UAAU,OAAW,KAAI,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,IAClE;AACA,WAAO,IAAI,SAAS;AAAA,EACtB;AAAA,EAEA,MAAc,SAAY,SAAqC;AAC7D,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,SAAS;AAExE,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,KAAK,OAAO,MAAM,KAAK,SAAS,OAAO,GAAG;AAAA,QACzD,QAAQ,QAAQ;AAAA,QAChB,SAAS;AAAA,UACP,CAAC,cAAc,GAAG,KAAK,OAAO;AAAA,UAC9B,GAAI,QAAQ,SAAS,UAAa,EAAE,gBAAgB,mBAAmB;AAAA,QACzE;AAAA,QACA,GAAI,QAAQ,SAAS,UAAa,EAAE,MAAM,KAAK,UAAU,QAAQ,IAAI,EAAE;AAAA,QACvE,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACpE,YAAM,IAAI,gBAAgB;AAAA,QACxB,SAAS,WAAW,OAAO,UACvB,2BAA2B,KAAK,OAAO,SAAS,OAChD,mBAAmB,MAAM;AAAA,MAC/B,CAAC;AAAA,IACH,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,MAAS;AACxD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,mBAAmB,SAAS,QAAQ,IAAI,aAAa;AAC3D,YAAM,aAAa,mBAAmB,OAAO,gBAAgB,IAAI;AACjE,YAAM,kBAAkB;AAAA,QACtB,QAAQ,SAAS;AAAA,QACjB;AAAA,QACA,YAAY,OAAO,SAAS,UAAU,IAAI,aAAa;AAAA,MACzD,CAAC;AAAA,IACH;AACA,WAAQ,MAAmB;AAAA,EAC7B;AACF;;;ACpHA,gBAAuB,SACrB,WACoC;AACpC,MAAI;AACJ,aAAS;AACP,UAAM,OAAO,MAAM,UAAU,MAAM;AACnC,WAAO,KAAK;AACZ,QAAI,CAAC,KAAK,WAAW,KAAK,eAAe,KAAM;AAC/C,aAAS,KAAK;AAAA,EAChB;AACF;;;ACXO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,WAAsB;AAAtB;AAAA,EAAuB;AAAA;AAAA,EAGpD,KAAK,SAA6B,CAAC,GAA4B;AAC7D,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,IAA+B;AACtC,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,iBAAiB,mBAAmB,EAAE,CAAC;AAAA,IAC/C,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,QAAQ,SAA6C,CAAC,GAA6B;AACjF,WAAO,SAAS,CAAC,WAAW,KAAK,KAAK,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;AAAA,EAC9D;AACF;;;ACxBO,IAAM,SAAN,MAAa;AAAA,EAClB,YAA6B,WAAsB;AAAtB;AAAA,EAAuB;AAAA;AAAA,EAGpD,KAAK,SAAqB,CAAC,GAA4B;AACrD,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,IAA+B;AACtC,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,cAAc,mBAAmB,EAAE,CAAC;AAAA,IAC5C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,QAA8C;AACnD,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,UAAoC;AAClC,WAAO,SAAS,CAAC,WAAW,KAAK,KAAK,EAAE,OAAO,CAAC,CAAC;AAAA,EACnD;AACF;;;AChCO,IAAM,WAAN,MAAe;AAAA,EACpB,YAA6B,WAAsB;AAAtB;AAAA,EAAuB;AAAA;AAAA,EAGpD,KAAK,SAAqB,CAAC,GAA2B;AACpD,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,IAAoC;AAC3C,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,gBAAgB,mBAAmB,EAAE,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,QAAqD;AAC1D,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,UAAmC;AACjC,WAAO,SAAS,CAAC,WAAW,KAAK,KAAK,EAAE,OAAO,CAAC,CAAC;AAAA,EACnD;AACF;;;AC5CO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,WAAsB;AAAtB;AAAA,EAAuB;AAAA;AAAA,EAGpD,KAAK,SAAqB,CAAC,GAA4B;AACrD,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,IAA+B;AACtC,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,iBAAiB,mBAAmB,EAAE,CAAC;AAAA,IAC/C,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,UAAoC;AAClC,WAAO,SAAS,CAAC,WAAW,KAAK,KAAK,EAAE,OAAO,CAAC,CAAC;AAAA,EACnD;AACF;;;AC1BO,IAAM,UAAN,MAAc;AAAA,EACnB,YAA6B,WAAsB;AAAtB;AAAA,EAAuB;AAAA;AAAA,EAGpD,SAAS,IAA6B;AACpC,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,eAAe,mBAAmB,EAAE,CAAC;AAAA,IAC7C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,IAA6B;AACnC,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,eAAe,mBAAmB,EAAE,CAAC;AAAA,IAC7C,CAAC;AAAA,EACH;AACF;;;ACnBO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,WAAsB;AAAtB;AAAA,EAAuB;AAAA;AAAA,EAGpD,KAAK,SAAqB,CAAC,GAA+B;AACxD,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,IAAkC;AACzC,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,oBAAoB,mBAAmB,EAAE,CAAC;AAAA,IAClD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,UAAuC;AACrC,WAAO,SAAS,CAAC,WAAW,KAAK,KAAK,EAAE,OAAO,CAAC,CAAC;AAAA,EACnD;AACF;;;AC1BO,IAAM,mBAAmB;AAChC,IAAM,mBAAmB;AAMzB,IAAM,YAAY,YAAmC;AACnD,MAAI,WAAW,QAAQ,OAAQ,QAAO,WAAW,OAAO;AACxD,QAAM,aAAa,MAAM,OAAO,QAAa;AAC7C,SAAQ,WAAW,UAAgC;AACrD;AAEA,IAAM,QAAQ,CAAC,WACb,CAAC,GAAG,IAAI,WAAW,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAGjF,IAAM,oBAAoB,CAAC,GAAW,MAAuB;AAC3D,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,MAAI,WAAW;AACf,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK,GAAG;AACpC,gBAAY,EAAE,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC;AAAA,EAC9C;AACA,SAAO,aAAa;AACtB;AAEA,IAAM,UAAU,OAAO,SAAiB,WAAoC;AAC1E,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,MAAM,MAAM,OAAO;AAAA,IACvB;AAAA,IACA,QAAQ,OAAO,MAAM;AAAA,IACrB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,IAChC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AACA,SAAO,MAAM,MAAM,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,OAAO,CAAC,CAAC;AACtE;AAYO,IAAM,kBAAkB,OAAO;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AACF,MAA+C;AAC7C,QAAM,WAAW,GAAG,gBAAgB,GAAG,MAAM,QAAQ,SAAS,MAAM,CAAC;AACrE,SAAO,kBAAkB,UAAU,SAAS;AAC9C;AAMO,IAAM,iBAAiB,OAC5B,WAC0B;AAC1B,MAAI,CAAC,OAAO,UAAU,WAAW,gBAAgB,GAAG;AAClD,UAAM,IAAI,yBAAyB;AAAA,MACjC,SAAS,qCAAqC,gBAAgB;AAAA,IAChE,CAAC;AAAA,EACH;AACA,MAAI,CAAE,MAAM,gBAAgB,MAAM,GAAI;AACpC,UAAM,IAAI,yBAAyB;AAAA,MACjC,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACA,MAAI;AACF,WAAO,KAAK,MAAM,OAAO,OAAO;AAAA,EAClC,QAAQ;AACN,UAAM,IAAI,yBAAyB;AAAA,MACjC,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;;;AClEO,IAAM,WAAN,MAAe;AAAA,EAGpB,YAA6B,WAAsB;AAAtB;AAC3B,SAAK,aAAa,IAAI,kBAAkB,SAAS;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,QAAiE;AACtE,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,KAAK,SAAqB,CAAC,GAAmC;AAC5D,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,IAAsC;AAC7C,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,gBAAgB,mBAAmB,EAAE,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,OAAO,IAAY,QAAuD;AACxE,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,gBAAgB,mBAAmB,EAAE,CAAC;AAAA,MAC5C,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,IAAI,IAAuD;AACzD,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,gBAAgB,mBAAmB,EAAE,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,QAAyD;AAC5D,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,UAA2C;AACzC,WAAO,SAAS,CAAC,WAAW,KAAK,KAAK,EAAE,OAAO,CAAC,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,QAAiD;AAC/D,WAAO,gBAAgB,MAAM;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,QAAsD;AACnE,WAAO,eAAe,MAAM;AAAA,EAC9B;AACF;AAEO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAA6B,WAAsB;AAAtB;AAAA,EAAuB;AAAA;AAAA,EAGpD,KAAK,SAAqB,CAAC,GAAmC;AAC5D,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,IAAsC;AAC7C,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,2BAA2B,mBAAmB,EAAE,CAAC;AAAA,IACzD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,OAAO,IAAsC;AAC3C,WAAO,KAAK,UAAU,QAAQ;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM,2BAA2B,mBAAmB,EAAE,CAAC;AAAA,IACzD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,UAA2C;AACzC,WAAO,SAAS,CAAC,WAAW,KAAK,KAAK,EAAE,OAAO,CAAC,CAAC;AAAA,EACnD;AACF;;;AC7GO,IAAM,UAAN,MAAc;AAAA,EAWnB,YAAY,QAAuB;AACjC,QAAI,CAAC,QAAQ,QAAQ;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,SAAK,YAAY,IAAI,UAAU;AAAA,MAC7B,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO,WAAW;AAAA,MAC3B,YAAY,OAAO,cAAc;AAAA,MACjC,WAAW,OAAO,aAAa;AAAA,MAC/B,OACE,OAAO,UACN,CAAC,OAAO,SAAS,WAAW,MAAM,OAAO,IAAI;AAAA,IAClD,CAAC;AACD,SAAK,YAAY,IAAI,UAAU,KAAK,SAAS;AAC7C,SAAK,WAAW,IAAI,SAAS,KAAK,SAAS;AAC3C,SAAK,YAAY,IAAI,UAAU,KAAK,SAAS;AAC7C,SAAK,eAAe,IAAI,aAAa,KAAK,SAAS;AACnD,SAAK,SAAS,IAAI,OAAO,KAAK,SAAS;AACvC,SAAK,UAAU,IAAI,QAAQ,KAAK,SAAS;AACzC,SAAK,WAAW,IAAI,SAAS,KAAK,SAAS;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAA8B;AAC5B,WAAO,KAAK,UAAU,QAAQ,EAAE,QAAQ,OAAO,MAAM,WAAW,CAAC;AAAA,EACnE;AACF;","names":[]}
package/dist/index.d.cts CHANGED
@@ -210,6 +210,19 @@ interface ProductDetail extends Product {
210
210
  type ProductType = 'custom' | 'event' | 'booking';
211
211
  type ProductVisibility = 'public' | 'private' | 'invite-only';
212
212
  type ProductEventType = 'Zoom' | 'Online' | 'In-Person' | 'Google Meet';
213
+ /**
214
+ * Content item attached at creation. `link` shares a URL with buyers after
215
+ * purchase; `custom` is a described deliverable fulfilled outside Nestuge.
216
+ */
217
+ interface CreateProductItemParams {
218
+ type: 'link' | 'custom';
219
+ /** 1–120 characters. */
220
+ title: string;
221
+ /** Max 500 characters. */
222
+ description?: string;
223
+ /** HTTPS URL — required when `type` is `link`. */
224
+ link?: string;
225
+ }
213
226
  interface CreateProductParams {
214
227
  type: ProductType;
215
228
  /** 6–80 characters. */
@@ -242,6 +255,8 @@ interface CreateProductParams {
242
255
  /** IANA timezone, e.g. "Africa/Lagos". */
243
256
  timezone: string;
244
257
  };
258
+ /** Content items delivered to buyers, max 20. */
259
+ items?: CreateProductItemParams[];
245
260
  }
246
261
 
247
262
  declare class Products {
@@ -255,10 +270,11 @@ declare class Products {
255
270
  */
256
271
  retrieve(id: string): Promise<ProductDetail>;
257
272
  /**
258
- * Creates a draft product. Requires `products:write`. Test-mode keys
259
- * validate and return a preview without persisting.
273
+ * Creates a draft product, optionally with content items. Requires
274
+ * `products:write`. Returns the product with its pricing tiers and items.
275
+ * Test-mode keys validate and return a preview without persisting.
260
276
  */
261
- create(params: CreateProductParams): Promise<Product>;
277
+ create(params: CreateProductParams): Promise<ProductDetail>;
262
278
  /** Iterates every product, following pagination cursors automatically. */
263
279
  iterate(): AsyncGenerator<Product>;
264
280
  }
@@ -557,4 +573,4 @@ declare class ConnectionError extends NestugeError {
557
573
  declare class WebhookVerificationError extends NestugeError {
558
574
  }
559
575
 
560
- export { AuthenticationError, ConnectionError, type CreateEventParams, type CreateProductParams, type CreateWebhookParams, type Customer, type CustomerListParams, type HubEvent, type ListParams, type Mode, type Money, Nestuge, type NestugeConfig, NestugeError, NotFoundError, type Page, PermissionError, type PingResponse, type Product, type ProductDetail, type ProductEventDetails, type ProductEventType, type ProductItem, type ProductTier, type ProductType, type ProductVisibility, type Purchase, RateLimitError, SIGNATURE_HEADER, ServerError, type TestWebhookParams, type Ticket, type Transaction, type UpdateWebhookParams, ValidationError, type VerifySignatureParams, type WebhookDelivery, type WebhookDeliveryStatus, type WebhookEndpoint, type WebhookEndpointStatus, type WebhookEndpointWithSecret, type WebhookEvent, type WebhookEventType, type WebhookResourceType, WebhookVerificationError, constructEvent, Nestuge as default, verifySignature };
576
+ export { AuthenticationError, ConnectionError, type CreateEventParams, type CreateProductItemParams, type CreateProductParams, type CreateWebhookParams, type Customer, type CustomerListParams, type HubEvent, type ListParams, type Mode, type Money, Nestuge, type NestugeConfig, NestugeError, NotFoundError, type Page, PermissionError, type PingResponse, type Product, type ProductDetail, type ProductEventDetails, type ProductEventType, type ProductItem, type ProductTier, type ProductType, type ProductVisibility, type Purchase, RateLimitError, SIGNATURE_HEADER, ServerError, type TestWebhookParams, type Ticket, type Transaction, type UpdateWebhookParams, ValidationError, type VerifySignatureParams, type WebhookDelivery, type WebhookDeliveryStatus, type WebhookEndpoint, type WebhookEndpointStatus, type WebhookEndpointWithSecret, type WebhookEvent, type WebhookEventType, type WebhookResourceType, WebhookVerificationError, constructEvent, Nestuge as default, verifySignature };
package/dist/index.d.ts CHANGED
@@ -210,6 +210,19 @@ interface ProductDetail extends Product {
210
210
  type ProductType = 'custom' | 'event' | 'booking';
211
211
  type ProductVisibility = 'public' | 'private' | 'invite-only';
212
212
  type ProductEventType = 'Zoom' | 'Online' | 'In-Person' | 'Google Meet';
213
+ /**
214
+ * Content item attached at creation. `link` shares a URL with buyers after
215
+ * purchase; `custom` is a described deliverable fulfilled outside Nestuge.
216
+ */
217
+ interface CreateProductItemParams {
218
+ type: 'link' | 'custom';
219
+ /** 1–120 characters. */
220
+ title: string;
221
+ /** Max 500 characters. */
222
+ description?: string;
223
+ /** HTTPS URL — required when `type` is `link`. */
224
+ link?: string;
225
+ }
213
226
  interface CreateProductParams {
214
227
  type: ProductType;
215
228
  /** 6–80 characters. */
@@ -242,6 +255,8 @@ interface CreateProductParams {
242
255
  /** IANA timezone, e.g. "Africa/Lagos". */
243
256
  timezone: string;
244
257
  };
258
+ /** Content items delivered to buyers, max 20. */
259
+ items?: CreateProductItemParams[];
245
260
  }
246
261
 
247
262
  declare class Products {
@@ -255,10 +270,11 @@ declare class Products {
255
270
  */
256
271
  retrieve(id: string): Promise<ProductDetail>;
257
272
  /**
258
- * Creates a draft product. Requires `products:write`. Test-mode keys
259
- * validate and return a preview without persisting.
273
+ * Creates a draft product, optionally with content items. Requires
274
+ * `products:write`. Returns the product with its pricing tiers and items.
275
+ * Test-mode keys validate and return a preview without persisting.
260
276
  */
261
- create(params: CreateProductParams): Promise<Product>;
277
+ create(params: CreateProductParams): Promise<ProductDetail>;
262
278
  /** Iterates every product, following pagination cursors automatically. */
263
279
  iterate(): AsyncGenerator<Product>;
264
280
  }
@@ -557,4 +573,4 @@ declare class ConnectionError extends NestugeError {
557
573
  declare class WebhookVerificationError extends NestugeError {
558
574
  }
559
575
 
560
- export { AuthenticationError, ConnectionError, type CreateEventParams, type CreateProductParams, type CreateWebhookParams, type Customer, type CustomerListParams, type HubEvent, type ListParams, type Mode, type Money, Nestuge, type NestugeConfig, NestugeError, NotFoundError, type Page, PermissionError, type PingResponse, type Product, type ProductDetail, type ProductEventDetails, type ProductEventType, type ProductItem, type ProductTier, type ProductType, type ProductVisibility, type Purchase, RateLimitError, SIGNATURE_HEADER, ServerError, type TestWebhookParams, type Ticket, type Transaction, type UpdateWebhookParams, ValidationError, type VerifySignatureParams, type WebhookDelivery, type WebhookDeliveryStatus, type WebhookEndpoint, type WebhookEndpointStatus, type WebhookEndpointWithSecret, type WebhookEvent, type WebhookEventType, type WebhookResourceType, WebhookVerificationError, constructEvent, Nestuge as default, verifySignature };
576
+ export { AuthenticationError, ConnectionError, type CreateEventParams, type CreateProductItemParams, type CreateProductParams, type CreateWebhookParams, type Customer, type CustomerListParams, type HubEvent, type ListParams, type Mode, type Money, Nestuge, type NestugeConfig, NestugeError, NotFoundError, type Page, PermissionError, type PingResponse, type Product, type ProductDetail, type ProductEventDetails, type ProductEventType, type ProductItem, type ProductTier, type ProductType, type ProductVisibility, type Purchase, RateLimitError, SIGNATURE_HEADER, ServerError, type TestWebhookParams, type Ticket, type Transaction, type UpdateWebhookParams, ValidationError, type VerifySignatureParams, type WebhookDelivery, type WebhookDeliveryStatus, type WebhookEndpoint, type WebhookEndpointStatus, type WebhookEndpointWithSecret, type WebhookEvent, type WebhookEventType, type WebhookResourceType, WebhookVerificationError, constructEvent, Nestuge as default, verifySignature };
package/dist/index.js CHANGED
@@ -28,6 +28,22 @@ var ConnectionError = class extends NestugeError {
28
28
  };
29
29
  var WebhookVerificationError = class extends NestugeError {
30
30
  };
31
+ var detailFromEnvelope = (error) => {
32
+ if (typeof error === "string") return error;
33
+ if (!Array.isArray(error)) return void 0;
34
+ const parts = error.map((issue) => {
35
+ if (typeof issue === "string") return issue;
36
+ if (issue && typeof issue === "object") {
37
+ const { path, message } = issue;
38
+ if (typeof message !== "string") return void 0;
39
+ const segments = Array.isArray(path) ? path.map(String) : [];
40
+ const leaf = segments[segments.length - 1];
41
+ return leaf && !message.includes(leaf) ? `${segments.join(".")}: ${message}` : message;
42
+ }
43
+ return void 0;
44
+ }).filter((part) => Boolean(part));
45
+ return parts.length > 0 ? parts.join("; ") : void 0;
46
+ };
31
47
  var errorFromResponse = ({
32
48
  status,
33
49
  body,
@@ -38,7 +54,7 @@ var errorFromResponse = ({
38
54
  message: typeof envelope.message === "string" ? envelope.message : `Request failed with status ${status}`,
39
55
  status,
40
56
  code: typeof envelope.code === "number" ? envelope.code : void 0,
41
- detail: typeof envelope.error === "string" ? envelope.error : void 0
57
+ detail: detailFromEnvelope(envelope.error)
42
58
  };
43
59
  if (status === 400) return new ValidationError(context);
44
60
  if (status === 401) return new AuthenticationError(context);
@@ -226,8 +242,9 @@ var Products = class {
226
242
  });
227
243
  }
228
244
  /**
229
- * Creates a draft product. Requires `products:write`. Test-mode keys
230
- * validate and return a preview without persisting.
245
+ * Creates a draft product, optionally with content items. Requires
246
+ * `products:write`. Returns the product with its pricing tiers and items.
247
+ * Test-mode keys validate and return a preview without persisting.
231
248
  */
232
249
  create(params) {
233
250
  return this.requestor.request({
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/errors.ts","../src/core/request.ts","../src/core/pagination.ts","../src/resources/customers.ts","../src/resources/events.ts","../src/resources/products.ts","../src/resources/purchases.ts","../src/resources/tickets.ts","../src/resources/transactions.ts","../src/webhooks/signature.ts","../src/resources/webhooks.ts","../src/client.ts"],"sourcesContent":["interface ErrorContext {\n message: string;\n /** HTTP status code, when the server responded. */\n status?: number;\n /** The `code` field from the API error envelope. */\n code?: number;\n /** The `error` field from the API error envelope (detail text). */\n detail?: string;\n}\n\n/** Base class for every error thrown by the SDK. */\nexport class NestugeError extends Error {\n readonly status?: number;\n readonly code?: number;\n readonly detail?: string;\n\n constructor(context: ErrorContext) {\n super(context.message);\n this.name = new.target.name;\n this.status = context.status;\n this.code = context.code;\n this.detail = context.detail;\n }\n}\n\n/** 400 — the request body or parameters failed validation. */\nexport class ValidationError extends NestugeError {}\n\n/** 401 — missing, malformed, or revoked API key. */\nexport class AuthenticationError extends NestugeError {}\n\n/** 403 — the API key lacks a required scope for this endpoint. */\nexport class PermissionError extends NestugeError {}\n\n/** 404 — the resource does not exist or belongs to another brand. */\nexport class NotFoundError extends NestugeError {}\n\n/** 429 — rate limit exceeded (120 requests/minute per key). */\nexport class RateLimitError extends NestugeError {\n /** Seconds to wait before retrying, from the `Retry-After` header. */\n readonly retryAfter?: number;\n\n constructor(context: ErrorContext & { retryAfter?: number }) {\n super(context);\n this.retryAfter = context.retryAfter;\n }\n}\n\n/** 5xx — the API failed to process the request. */\nexport class ServerError extends NestugeError {}\n\n/** The request never reached the API (network failure or timeout). */\nexport class ConnectionError extends NestugeError {}\n\n/** Webhook signature verification failed in `constructEvent`. */\nexport class WebhookVerificationError extends NestugeError {}\n\nexport const errorFromResponse = ({\n status,\n body,\n retryAfter,\n}: {\n status: number;\n body: unknown;\n retryAfter?: number;\n}): NestugeError => {\n const envelope = (body ?? {}) as Record<string, unknown>;\n const context: ErrorContext = {\n message:\n typeof envelope.message === 'string'\n ? envelope.message\n : `Request failed with status ${status}`,\n status,\n code: typeof envelope.code === 'number' ? envelope.code : undefined,\n detail: typeof envelope.error === 'string' ? envelope.error : undefined,\n };\n if (status === 400) return new ValidationError(context);\n if (status === 401) return new AuthenticationError(context);\n if (status === 403) return new PermissionError(context);\n if (status === 404) return new NotFoundError(context);\n if (status === 429) return new RateLimitError({ ...context, retryAfter });\n if (status >= 500) return new ServerError(context);\n return new NestugeError(context);\n};\n","import { ConnectionError, RateLimitError, ServerError, errorFromResponse } from './errors';\n\nexport const API_KEY_HEADER = 'x-nestuge-api';\nexport const DEFAULT_BASE_URL = 'https://nestuge.com';\nexport const DEFAULT_TIMEOUT_MS = 30_000;\nexport const DEFAULT_MAX_RETRIES = 2;\n\nconst API_PREFIX = '/api';\nconst MAX_BACKOFF_MS = 8_000;\n\ntype QueryValue = string | number | boolean | undefined;\nexport type FetchLike = (input: string, init: RequestInit) => Promise<Response>;\n\nexport interface RequestorConfig {\n apiKey: string;\n baseUrl: string;\n maxRetries: number;\n timeoutMs: number;\n fetch: FetchLike;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n /** Contract path, e.g. `/v1/customers/{id}` with params already interpolated. */\n path: string;\n /** Shallow object of query params; undefined values are omitted. */\n query?: object;\n body?: unknown;\n}\n\ninterface Envelope {\n data?: unknown;\n message?: string;\n status?: string;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst backoffMs = (attempt: number): number => {\n const base = Math.min(500 * 2 ** attempt, MAX_BACKOFF_MS);\n return base / 2 + Math.random() * (base / 2);\n};\n\nconst shouldRetry = (error: unknown): boolean =>\n error instanceof ConnectionError ||\n error instanceof RateLimitError ||\n error instanceof ServerError;\n\nconst retryDelayMs = (error: unknown, attempt: number): number => {\n if (error instanceof RateLimitError && error.retryAfter !== undefined) {\n return error.retryAfter * 1000;\n }\n return backoffMs(attempt);\n};\n\nexport class Requestor {\n private readonly config: RequestorConfig;\n\n constructor(config: RequestorConfig) {\n this.config = config;\n }\n\n /** Performs a request against the Dev API and returns the unwrapped `data`. */\n async request<T>(options: RequestOptions): Promise<T> {\n let attempt = 0;\n for (;;) {\n try {\n return await this.dispatch<T>(options);\n } catch (error) {\n if (attempt >= this.config.maxRetries || !shouldRetry(error)) throw error;\n await sleep(retryDelayMs(error, attempt));\n attempt += 1;\n }\n }\n }\n\n private buildUrl({ path, query }: RequestOptions): string {\n const url = new URL(`${API_PREFIX}${path}`, this.config.baseUrl);\n for (const [key, value] of Object.entries(query ?? {}) as [string, QueryValue][]) {\n if (value !== undefined) url.searchParams.set(key, String(value));\n }\n return url.toString();\n }\n\n private async dispatch<T>(options: RequestOptions): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n let response: Response;\n try {\n response = await this.config.fetch(this.buildUrl(options), {\n method: options.method,\n headers: {\n [API_KEY_HEADER]: this.config.apiKey,\n ...(options.body !== undefined && { 'Content-Type': 'application/json' }),\n },\n ...(options.body !== undefined && { body: JSON.stringify(options.body) }),\n signal: controller.signal,\n });\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new ConnectionError({\n message: controller.signal.aborted\n ? `Request timed out after ${this.config.timeoutMs}ms`\n : `Request failed: ${reason}`,\n });\n } finally {\n clearTimeout(timer);\n }\n\n const body = await response.json().catch(() => undefined);\n if (!response.ok) {\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfter = retryAfterHeader ? Number(retryAfterHeader) : undefined;\n throw errorFromResponse({\n status: response.status,\n body,\n retryAfter: Number.isFinite(retryAfter) ? retryAfter : undefined,\n });\n }\n return (body as Envelope)?.data as T;\n }\n}\n","import type { Page } from '../types/shared';\n\n/**\n * Turns a page-fetching function into an async generator that yields every\n * item, transparently following `nextCursor` until the list is exhausted.\n */\nexport async function* paginate<T>(\n fetchPage: (cursor: string | undefined) => Promise<Page<T>>,\n): AsyncGenerator<T, void, undefined> {\n let cursor: string | undefined;\n for (;;) {\n const page = await fetchPage(cursor);\n yield* page.items;\n if (!page.hasMore || page.nextCursor === null) return;\n cursor = page.nextCursor;\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { Customer, CustomerListParams } from '../types/customers';\nimport type { Page } from '../types/shared';\n\nexport class Customers {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's hub members, newest first. Requires `customers:read`. */\n list(params: CustomerListParams = {}): Promise<Page<Customer>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/customers',\n query: params,\n });\n }\n\n /** Returns a single hub membership by its membership id. */\n retrieve(id: string): Promise<Customer> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/customers/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every customer, following pagination cursors automatically. */\n iterate(params: Omit<CustomerListParams, 'cursor'> = {}): AsyncGenerator<Customer> {\n return paginate((cursor) => this.list({ ...params, cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { CreateEventParams, HubEvent } from '../types/events';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Events {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's hub community events, newest first. Requires `events:read`. */\n list(params: ListParams = {}): Promise<Page<HubEvent>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/events',\n query: params,\n });\n }\n\n /** Returns a single hub event owned by the brand. */\n retrieve(id: string): Promise<HubEvent> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/events/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Creates a hub event in one of the brand's hubs. Requires `events:write`\n * and the brand to have Google Calendar connected.\n */\n create(params: CreateEventParams): Promise<HubEvent> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/events',\n body: params,\n });\n }\n\n /** Iterates every event, following pagination cursors automatically. */\n iterate(): AsyncGenerator<HubEvent> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type {\n CreateProductParams,\n Product,\n ProductDetail,\n} from '../types/products';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Products {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's products (all types), newest first. Requires `products:read`. */\n list(params: ListParams = {}): Promise<Page<Product>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/products',\n query: params,\n });\n }\n\n /**\n * Returns a single product owned by the brand, including its pricing\n * tiers and content items.\n */\n retrieve(id: string): Promise<ProductDetail> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/products/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Creates a draft product. Requires `products:write`. Test-mode keys\n * validate and return a preview without persisting.\n */\n create(params: CreateProductParams): Promise<Product> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/products',\n body: params,\n });\n }\n\n /** Iterates every product, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Product> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { Purchase } from '../types/purchases';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Purchases {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's purchases/orders, newest first. Requires `purchases:read`. */\n list(params: ListParams = {}): Promise<Page<Purchase>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/purchases',\n query: params,\n });\n }\n\n /** Returns a single purchase/order by id. */\n retrieve(id: string): Promise<Purchase> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/purchases/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every purchase, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Purchase> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import type { Requestor } from '../core/request';\nimport type { Ticket } from '../types/tickets';\n\nexport class Tickets {\n constructor(private readonly requestor: Requestor) {}\n\n /** Returns a single event ticket by ticket id. Requires `purchases:read`. */\n retrieve(id: string): Promise<Ticket> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/tickets/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Checks in an event attendee by ticket id. Requires `purchases:write`.\n * Test-mode keys validate and return the checked-in ticket without persisting.\n */\n checkIn(id: string): Promise<Ticket> {\n return this.requestor.request({\n method: 'POST',\n path: `/v1/tickets/${encodeURIComponent(id)}/checkin`,\n });\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { ListParams, Page } from '../types/shared';\nimport type { Transaction } from '../types/transactions';\n\nexport class Transactions {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's transactions, newest first. Requires `transactions:read`. */\n list(params: ListParams = {}): Promise<Page<Transaction>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/transactions',\n query: params,\n });\n }\n\n /** Returns a single transaction by its reference (`txref`). */\n retrieve(id: string): Promise<Transaction> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/transactions/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every transaction, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Transaction> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { WebhookVerificationError } from '../core/errors';\nimport type { WebhookEvent } from '../types/webhooks';\n\nexport const SIGNATURE_HEADER = 'X-Nestuge-Signature';\nconst SIGNATURE_PREFIX = 'sha256=';\n\n/**\n * Web Crypto is global on Node 19+, Bun, Deno, browsers, and edge runtimes;\n * on Node 18 it lives at node:crypto's `webcrypto`.\n */\nconst getSubtle = async (): Promise<SubtleCrypto> => {\n if (globalThis.crypto?.subtle) return globalThis.crypto.subtle;\n const nodeCrypto = await import('node:crypto');\n return (nodeCrypto.webcrypto as unknown as Crypto).subtle;\n};\n\nconst toHex = (buffer: ArrayBuffer): string =>\n [...new Uint8Array(buffer)].map((b) => b.toString(16).padStart(2, '0')).join('');\n\n/** Comparison time depends only on input length, not on where they differ. */\nconst constantTimeEqual = (a: string, b: string): boolean => {\n if (a.length !== b.length) return false;\n let mismatch = 0;\n for (let i = 0; i < a.length; i += 1) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n};\n\nconst hmacHex = async (payload: string, secret: string): Promise<string> => {\n const subtle = await getSubtle();\n const encoder = new TextEncoder();\n const key = await subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return toHex(await subtle.sign('HMAC', key, encoder.encode(payload)));\n};\n\nexport interface VerifySignatureParams {\n /** The raw, unmodified request body string (not re-serialized JSON). */\n payload: string;\n /** Value of the `X-Nestuge-Signature` header (`sha256=<hex>`). */\n signature: string;\n /** The endpoint's signing secret, returned once by `webhooks.create()`. */\n secret: string;\n}\n\n/** Verifies a webhook signature with a timing-safe HMAC-SHA256 comparison. */\nexport const verifySignature = async ({\n payload,\n signature,\n secret,\n}: VerifySignatureParams): Promise<boolean> => {\n const expected = `${SIGNATURE_PREFIX}${await hmacHex(payload, secret)}`;\n return constantTimeEqual(expected, signature);\n};\n\n/**\n * Verifies the signature and parses the payload into a typed `WebhookEvent`.\n * Throws `WebhookVerificationError` on a bad signature or unparseable body.\n */\nexport const constructEvent = async (\n params: VerifySignatureParams,\n): Promise<WebhookEvent> => {\n if (!params.signature.startsWith(SIGNATURE_PREFIX)) {\n throw new WebhookVerificationError({\n message: `Signature header must start with \"${SIGNATURE_PREFIX}\"`,\n });\n }\n if (!(await verifySignature(params))) {\n throw new WebhookVerificationError({\n message: 'Webhook signature verification failed',\n });\n }\n try {\n return JSON.parse(params.payload) as WebhookEvent;\n } catch {\n throw new WebhookVerificationError({\n message: 'Webhook payload is not valid JSON',\n });\n }\n};\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { ListParams, Page } from '../types/shared';\nimport type {\n CreateWebhookParams,\n TestWebhookParams,\n UpdateWebhookParams,\n WebhookDelivery,\n WebhookEndpoint,\n WebhookEndpointWithSecret,\n WebhookEvent,\n} from '../types/webhooks';\nimport {\n constructEvent,\n verifySignature,\n type VerifySignatureParams,\n} from '../webhooks/signature';\n\n/** All webhook endpoints require the `webhooks:write` scope. */\nexport class Webhooks {\n readonly deliveries: WebhookDeliveries;\n\n constructor(private readonly requestor: Requestor) {\n this.deliveries = new WebhookDeliveries(requestor);\n }\n\n /**\n * Registers an HTTPS endpoint URL. The returned `signingSecret` is shown\n * once in this response and can never be retrieved again.\n */\n create(params: CreateWebhookParams): Promise<WebhookEndpointWithSecret> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/webhooks',\n body: params,\n });\n }\n\n /** Lists the brand's webhook endpoints. */\n list(params: ListParams = {}): Promise<Page<WebhookEndpoint>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/webhooks',\n query: params,\n });\n }\n\n /** Returns a single webhook endpoint. */\n retrieve(id: string): Promise<WebhookEndpoint> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n });\n }\n\n /** Updates a webhook endpoint's URL, events, status, or description. */\n update(id: string, params: UpdateWebhookParams): Promise<WebhookEndpoint> {\n return this.requestor.request({\n method: 'PATCH',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n body: params,\n });\n }\n\n /** Deletes a webhook endpoint. */\n del(id: string): Promise<{ id: string; deleted: boolean }> {\n return this.requestor.request({\n method: 'DELETE',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Synthesizes a sample event and delivers it through the real\n * signed/retried/logged pipeline as a test-mode delivery.\n */\n test(params: TestWebhookParams): Promise<{ created: number }> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/webhooks/test',\n body: params,\n });\n }\n\n /** Iterates every webhook endpoint, following pagination cursors automatically. */\n iterate(): AsyncGenerator<WebhookEndpoint> {\n return paginate((cursor) => this.list({ cursor }));\n }\n\n /**\n * Verifies an incoming webhook's `X-Nestuge-Signature` header with a\n * timing-safe HMAC-SHA256 comparison over the raw request body.\n */\n verifySignature(params: VerifySignatureParams): Promise<boolean> {\n return verifySignature(params);\n }\n\n /**\n * Verifies the signature and returns the parsed, typed event. Throws\n * `WebhookVerificationError` if verification fails.\n */\n constructEvent(params: VerifySignatureParams): Promise<WebhookEvent> {\n return constructEvent(params);\n }\n}\n\nexport class WebhookDeliveries {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists webhook delivery attempts, newest first. */\n list(params: ListParams = {}): Promise<Page<WebhookDelivery>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/webhooks/deliveries',\n query: params,\n });\n }\n\n /** Returns a single delivery record. */\n retrieve(id: string): Promise<WebhookDelivery> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/webhooks/deliveries/${encodeURIComponent(id)}`,\n });\n }\n\n /** Re-queues a delivery as a fresh attempt; the original record is preserved. */\n resend(id: string): Promise<WebhookDelivery> {\n return this.requestor.request({\n method: 'POST',\n path: `/v1/webhooks/deliveries/${encodeURIComponent(id)}/resend`,\n });\n }\n\n /** Iterates every delivery record, following pagination cursors automatically. */\n iterate(): AsyncGenerator<WebhookDelivery> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n Requestor,\n type FetchLike,\n} from './core/request';\nimport { Customers } from './resources/customers';\nimport { Events } from './resources/events';\nimport { Products } from './resources/products';\nimport { Purchases } from './resources/purchases';\nimport { Tickets } from './resources/tickets';\nimport { Transactions } from './resources/transactions';\nimport { Webhooks } from './resources/webhooks';\nimport type { PingResponse } from './types/shared';\n\nexport interface NestugeConfig {\n /** Brand API key (`nk_live_…` or `nk_test_…`) from Settings → Developer. */\n apiKey: string;\n /** API origin. Defaults to `https://nestuge.com`. */\n baseUrl?: string;\n /** Extra retry attempts on 429/5xx/network errors. Defaults to 2. */\n maxRetries?: number;\n /** Per-attempt timeout in milliseconds. Defaults to 30000. */\n timeoutMs?: number;\n /** Custom fetch implementation (testing, proxies). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\nexport class Nestuge {\n readonly customers: Customers;\n readonly products: Products;\n readonly purchases: Purchases;\n readonly transactions: Transactions;\n readonly events: Events;\n readonly tickets: Tickets;\n readonly webhooks: Webhooks;\n\n private readonly requestor: Requestor;\n\n constructor(config: NestugeConfig) {\n if (!config?.apiKey) {\n throw new Error(\n 'Nestuge: an apiKey is required. Create one under Settings → Developer.',\n );\n }\n this.requestor = new Requestor({\n apiKey: config.apiKey,\n baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n fetch:\n config.fetch ??\n ((input, init) => globalThis.fetch(input, init)),\n });\n this.customers = new Customers(this.requestor);\n this.products = new Products(this.requestor);\n this.purchases = new Purchases(this.requestor);\n this.transactions = new Transactions(this.requestor);\n this.events = new Events(this.requestor);\n this.tickets = new Tickets(this.requestor);\n this.webhooks = new Webhooks(this.requestor);\n }\n\n /**\n * Authenticated health check: confirms the key works and returns the\n * resolved brand, key mode, and granted scopes. No scope required.\n */\n ping(): Promise<PingResponse> {\n return this.requestor.request({ method: 'GET', path: '/v1/ping' });\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/core/errors.ts","../src/core/request.ts","../src/core/pagination.ts","../src/resources/customers.ts","../src/resources/events.ts","../src/resources/products.ts","../src/resources/purchases.ts","../src/resources/tickets.ts","../src/resources/transactions.ts","../src/webhooks/signature.ts","../src/resources/webhooks.ts","../src/client.ts"],"sourcesContent":["interface ErrorContext {\n message: string;\n /** HTTP status code, when the server responded. */\n status?: number;\n /** The `code` field from the API error envelope. */\n code?: number;\n /** The `error` field from the API error envelope (detail text). */\n detail?: string;\n}\n\n/** Base class for every error thrown by the SDK. */\nexport class NestugeError extends Error {\n readonly status?: number;\n readonly code?: number;\n readonly detail?: string;\n\n constructor(context: ErrorContext) {\n super(context.message);\n this.name = new.target.name;\n this.status = context.status;\n this.code = context.code;\n this.detail = context.detail;\n }\n}\n\n/** 400 — the request body or parameters failed validation. */\nexport class ValidationError extends NestugeError {}\n\n/** 401 — missing, malformed, or revoked API key. */\nexport class AuthenticationError extends NestugeError {}\n\n/** 403 — the API key lacks a required scope for this endpoint. */\nexport class PermissionError extends NestugeError {}\n\n/** 404 — the resource does not exist or belongs to another brand. */\nexport class NotFoundError extends NestugeError {}\n\n/** 429 — rate limit exceeded (120 requests/minute per key). */\nexport class RateLimitError extends NestugeError {\n /** Seconds to wait before retrying, from the `Retry-After` header. */\n readonly retryAfter?: number;\n\n constructor(context: ErrorContext & { retryAfter?: number }) {\n super(context);\n this.retryAfter = context.retryAfter;\n }\n}\n\n/** 5xx — the API failed to process the request. */\nexport class ServerError extends NestugeError {}\n\n/** The request never reached the API (network failure or timeout). */\nexport class ConnectionError extends NestugeError {}\n\n/** Webhook signature verification failed in `constructEvent`. */\nexport class WebhookVerificationError extends NestugeError {}\n\n/**\n * The envelope's `error` field is either a plain string or an array of\n * validation issues ({ path, message }); flatten either into one readable line.\n */\nconst detailFromEnvelope = (error: unknown): string | undefined => {\n if (typeof error === 'string') return error;\n if (!Array.isArray(error)) return undefined;\n const parts = error\n .map((issue) => {\n if (typeof issue === 'string') return issue;\n if (issue && typeof issue === 'object') {\n const { path, message } = issue as { path?: unknown; message?: unknown };\n if (typeof message !== 'string') return undefined;\n const segments = Array.isArray(path) ? path.map(String) : [];\n const leaf = segments[segments.length - 1];\n // Zod messages usually name the field already — avoid \"x: x must be…\"\n return leaf && !message.includes(leaf)\n ? `${segments.join('.')}: ${message}`\n : message;\n }\n return undefined;\n })\n .filter((part): part is string => Boolean(part));\n return parts.length > 0 ? parts.join('; ') : undefined;\n};\n\nexport const errorFromResponse = ({\n status,\n body,\n retryAfter,\n}: {\n status: number;\n body: unknown;\n retryAfter?: number;\n}): NestugeError => {\n const envelope = (body ?? {}) as Record<string, unknown>;\n const context: ErrorContext = {\n message:\n typeof envelope.message === 'string'\n ? envelope.message\n : `Request failed with status ${status}`,\n status,\n code: typeof envelope.code === 'number' ? envelope.code : undefined,\n detail: detailFromEnvelope(envelope.error),\n };\n if (status === 400) return new ValidationError(context);\n if (status === 401) return new AuthenticationError(context);\n if (status === 403) return new PermissionError(context);\n if (status === 404) return new NotFoundError(context);\n if (status === 429) return new RateLimitError({ ...context, retryAfter });\n if (status >= 500) return new ServerError(context);\n return new NestugeError(context);\n};\n","import { ConnectionError, RateLimitError, ServerError, errorFromResponse } from './errors';\n\nexport const API_KEY_HEADER = 'x-nestuge-api';\nexport const DEFAULT_BASE_URL = 'https://nestuge.com';\nexport const DEFAULT_TIMEOUT_MS = 30_000;\nexport const DEFAULT_MAX_RETRIES = 2;\n\nconst API_PREFIX = '/api';\nconst MAX_BACKOFF_MS = 8_000;\n\ntype QueryValue = string | number | boolean | undefined;\nexport type FetchLike = (input: string, init: RequestInit) => Promise<Response>;\n\nexport interface RequestorConfig {\n apiKey: string;\n baseUrl: string;\n maxRetries: number;\n timeoutMs: number;\n fetch: FetchLike;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n /** Contract path, e.g. `/v1/customers/{id}` with params already interpolated. */\n path: string;\n /** Shallow object of query params; undefined values are omitted. */\n query?: object;\n body?: unknown;\n}\n\ninterface Envelope {\n data?: unknown;\n message?: string;\n status?: string;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst backoffMs = (attempt: number): number => {\n const base = Math.min(500 * 2 ** attempt, MAX_BACKOFF_MS);\n return base / 2 + Math.random() * (base / 2);\n};\n\nconst shouldRetry = (error: unknown): boolean =>\n error instanceof ConnectionError ||\n error instanceof RateLimitError ||\n error instanceof ServerError;\n\nconst retryDelayMs = (error: unknown, attempt: number): number => {\n if (error instanceof RateLimitError && error.retryAfter !== undefined) {\n return error.retryAfter * 1000;\n }\n return backoffMs(attempt);\n};\n\nexport class Requestor {\n private readonly config: RequestorConfig;\n\n constructor(config: RequestorConfig) {\n this.config = config;\n }\n\n /** Performs a request against the Dev API and returns the unwrapped `data`. */\n async request<T>(options: RequestOptions): Promise<T> {\n let attempt = 0;\n for (;;) {\n try {\n return await this.dispatch<T>(options);\n } catch (error) {\n if (attempt >= this.config.maxRetries || !shouldRetry(error)) throw error;\n await sleep(retryDelayMs(error, attempt));\n attempt += 1;\n }\n }\n }\n\n private buildUrl({ path, query }: RequestOptions): string {\n const url = new URL(`${API_PREFIX}${path}`, this.config.baseUrl);\n for (const [key, value] of Object.entries(query ?? {}) as [string, QueryValue][]) {\n if (value !== undefined) url.searchParams.set(key, String(value));\n }\n return url.toString();\n }\n\n private async dispatch<T>(options: RequestOptions): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n let response: Response;\n try {\n response = await this.config.fetch(this.buildUrl(options), {\n method: options.method,\n headers: {\n [API_KEY_HEADER]: this.config.apiKey,\n ...(options.body !== undefined && { 'Content-Type': 'application/json' }),\n },\n ...(options.body !== undefined && { body: JSON.stringify(options.body) }),\n signal: controller.signal,\n });\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new ConnectionError({\n message: controller.signal.aborted\n ? `Request timed out after ${this.config.timeoutMs}ms`\n : `Request failed: ${reason}`,\n });\n } finally {\n clearTimeout(timer);\n }\n\n const body = await response.json().catch(() => undefined);\n if (!response.ok) {\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfter = retryAfterHeader ? Number(retryAfterHeader) : undefined;\n throw errorFromResponse({\n status: response.status,\n body,\n retryAfter: Number.isFinite(retryAfter) ? retryAfter : undefined,\n });\n }\n return (body as Envelope)?.data as T;\n }\n}\n","import type { Page } from '../types/shared';\n\n/**\n * Turns a page-fetching function into an async generator that yields every\n * item, transparently following `nextCursor` until the list is exhausted.\n */\nexport async function* paginate<T>(\n fetchPage: (cursor: string | undefined) => Promise<Page<T>>,\n): AsyncGenerator<T, void, undefined> {\n let cursor: string | undefined;\n for (;;) {\n const page = await fetchPage(cursor);\n yield* page.items;\n if (!page.hasMore || page.nextCursor === null) return;\n cursor = page.nextCursor;\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { Customer, CustomerListParams } from '../types/customers';\nimport type { Page } from '../types/shared';\n\nexport class Customers {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's hub members, newest first. Requires `customers:read`. */\n list(params: CustomerListParams = {}): Promise<Page<Customer>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/customers',\n query: params,\n });\n }\n\n /** Returns a single hub membership by its membership id. */\n retrieve(id: string): Promise<Customer> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/customers/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every customer, following pagination cursors automatically. */\n iterate(params: Omit<CustomerListParams, 'cursor'> = {}): AsyncGenerator<Customer> {\n return paginate((cursor) => this.list({ ...params, cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { CreateEventParams, HubEvent } from '../types/events';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Events {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's hub community events, newest first. Requires `events:read`. */\n list(params: ListParams = {}): Promise<Page<HubEvent>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/events',\n query: params,\n });\n }\n\n /** Returns a single hub event owned by the brand. */\n retrieve(id: string): Promise<HubEvent> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/events/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Creates a hub event in one of the brand's hubs. Requires `events:write`\n * and the brand to have Google Calendar connected.\n */\n create(params: CreateEventParams): Promise<HubEvent> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/events',\n body: params,\n });\n }\n\n /** Iterates every event, following pagination cursors automatically. */\n iterate(): AsyncGenerator<HubEvent> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type {\n CreateProductParams,\n Product,\n ProductDetail,\n} from '../types/products';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Products {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's products (all types), newest first. Requires `products:read`. */\n list(params: ListParams = {}): Promise<Page<Product>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/products',\n query: params,\n });\n }\n\n /**\n * Returns a single product owned by the brand, including its pricing\n * tiers and content items.\n */\n retrieve(id: string): Promise<ProductDetail> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/products/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Creates a draft product, optionally with content items. Requires\n * `products:write`. Returns the product with its pricing tiers and items.\n * Test-mode keys validate and return a preview without persisting.\n */\n create(params: CreateProductParams): Promise<ProductDetail> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/products',\n body: params,\n });\n }\n\n /** Iterates every product, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Product> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { Purchase } from '../types/purchases';\nimport type { ListParams, Page } from '../types/shared';\n\nexport class Purchases {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's purchases/orders, newest first. Requires `purchases:read`. */\n list(params: ListParams = {}): Promise<Page<Purchase>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/purchases',\n query: params,\n });\n }\n\n /** Returns a single purchase/order by id. */\n retrieve(id: string): Promise<Purchase> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/purchases/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every purchase, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Purchase> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import type { Requestor } from '../core/request';\nimport type { Ticket } from '../types/tickets';\n\nexport class Tickets {\n constructor(private readonly requestor: Requestor) {}\n\n /** Returns a single event ticket by ticket id. Requires `purchases:read`. */\n retrieve(id: string): Promise<Ticket> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/tickets/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Checks in an event attendee by ticket id. Requires `purchases:write`.\n * Test-mode keys validate and return the checked-in ticket without persisting.\n */\n checkIn(id: string): Promise<Ticket> {\n return this.requestor.request({\n method: 'POST',\n path: `/v1/tickets/${encodeURIComponent(id)}/checkin`,\n });\n }\n}\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { ListParams, Page } from '../types/shared';\nimport type { Transaction } from '../types/transactions';\n\nexport class Transactions {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists the brand's transactions, newest first. Requires `transactions:read`. */\n list(params: ListParams = {}): Promise<Page<Transaction>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/transactions',\n query: params,\n });\n }\n\n /** Returns a single transaction by its reference (`txref`). */\n retrieve(id: string): Promise<Transaction> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/transactions/${encodeURIComponent(id)}`,\n });\n }\n\n /** Iterates every transaction, following pagination cursors automatically. */\n iterate(): AsyncGenerator<Transaction> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import { WebhookVerificationError } from '../core/errors';\nimport type { WebhookEvent } from '../types/webhooks';\n\nexport const SIGNATURE_HEADER = 'X-Nestuge-Signature';\nconst SIGNATURE_PREFIX = 'sha256=';\n\n/**\n * Web Crypto is global on Node 19+, Bun, Deno, browsers, and edge runtimes;\n * on Node 18 it lives at node:crypto's `webcrypto`.\n */\nconst getSubtle = async (): Promise<SubtleCrypto> => {\n if (globalThis.crypto?.subtle) return globalThis.crypto.subtle;\n const nodeCrypto = await import('node:crypto');\n return (nodeCrypto.webcrypto as unknown as Crypto).subtle;\n};\n\nconst toHex = (buffer: ArrayBuffer): string =>\n [...new Uint8Array(buffer)].map((b) => b.toString(16).padStart(2, '0')).join('');\n\n/** Comparison time depends only on input length, not on where they differ. */\nconst constantTimeEqual = (a: string, b: string): boolean => {\n if (a.length !== b.length) return false;\n let mismatch = 0;\n for (let i = 0; i < a.length; i += 1) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n};\n\nconst hmacHex = async (payload: string, secret: string): Promise<string> => {\n const subtle = await getSubtle();\n const encoder = new TextEncoder();\n const key = await subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return toHex(await subtle.sign('HMAC', key, encoder.encode(payload)));\n};\n\nexport interface VerifySignatureParams {\n /** The raw, unmodified request body string (not re-serialized JSON). */\n payload: string;\n /** Value of the `X-Nestuge-Signature` header (`sha256=<hex>`). */\n signature: string;\n /** The endpoint's signing secret, returned once by `webhooks.create()`. */\n secret: string;\n}\n\n/** Verifies a webhook signature with a timing-safe HMAC-SHA256 comparison. */\nexport const verifySignature = async ({\n payload,\n signature,\n secret,\n}: VerifySignatureParams): Promise<boolean> => {\n const expected = `${SIGNATURE_PREFIX}${await hmacHex(payload, secret)}`;\n return constantTimeEqual(expected, signature);\n};\n\n/**\n * Verifies the signature and parses the payload into a typed `WebhookEvent`.\n * Throws `WebhookVerificationError` on a bad signature or unparseable body.\n */\nexport const constructEvent = async (\n params: VerifySignatureParams,\n): Promise<WebhookEvent> => {\n if (!params.signature.startsWith(SIGNATURE_PREFIX)) {\n throw new WebhookVerificationError({\n message: `Signature header must start with \"${SIGNATURE_PREFIX}\"`,\n });\n }\n if (!(await verifySignature(params))) {\n throw new WebhookVerificationError({\n message: 'Webhook signature verification failed',\n });\n }\n try {\n return JSON.parse(params.payload) as WebhookEvent;\n } catch {\n throw new WebhookVerificationError({\n message: 'Webhook payload is not valid JSON',\n });\n }\n};\n","import { paginate } from '../core/pagination';\nimport type { Requestor } from '../core/request';\nimport type { ListParams, Page } from '../types/shared';\nimport type {\n CreateWebhookParams,\n TestWebhookParams,\n UpdateWebhookParams,\n WebhookDelivery,\n WebhookEndpoint,\n WebhookEndpointWithSecret,\n WebhookEvent,\n} from '../types/webhooks';\nimport {\n constructEvent,\n verifySignature,\n type VerifySignatureParams,\n} from '../webhooks/signature';\n\n/** All webhook endpoints require the `webhooks:write` scope. */\nexport class Webhooks {\n readonly deliveries: WebhookDeliveries;\n\n constructor(private readonly requestor: Requestor) {\n this.deliveries = new WebhookDeliveries(requestor);\n }\n\n /**\n * Registers an HTTPS endpoint URL. The returned `signingSecret` is shown\n * once in this response and can never be retrieved again.\n */\n create(params: CreateWebhookParams): Promise<WebhookEndpointWithSecret> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/webhooks',\n body: params,\n });\n }\n\n /** Lists the brand's webhook endpoints. */\n list(params: ListParams = {}): Promise<Page<WebhookEndpoint>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/webhooks',\n query: params,\n });\n }\n\n /** Returns a single webhook endpoint. */\n retrieve(id: string): Promise<WebhookEndpoint> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n });\n }\n\n /** Updates a webhook endpoint's URL, events, status, or description. */\n update(id: string, params: UpdateWebhookParams): Promise<WebhookEndpoint> {\n return this.requestor.request({\n method: 'PATCH',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n body: params,\n });\n }\n\n /** Deletes a webhook endpoint. */\n del(id: string): Promise<{ id: string; deleted: boolean }> {\n return this.requestor.request({\n method: 'DELETE',\n path: `/v1/webhooks/${encodeURIComponent(id)}`,\n });\n }\n\n /**\n * Synthesizes a sample event and delivers it through the real\n * signed/retried/logged pipeline as a test-mode delivery.\n */\n test(params: TestWebhookParams): Promise<{ created: number }> {\n return this.requestor.request({\n method: 'POST',\n path: '/v1/webhooks/test',\n body: params,\n });\n }\n\n /** Iterates every webhook endpoint, following pagination cursors automatically. */\n iterate(): AsyncGenerator<WebhookEndpoint> {\n return paginate((cursor) => this.list({ cursor }));\n }\n\n /**\n * Verifies an incoming webhook's `X-Nestuge-Signature` header with a\n * timing-safe HMAC-SHA256 comparison over the raw request body.\n */\n verifySignature(params: VerifySignatureParams): Promise<boolean> {\n return verifySignature(params);\n }\n\n /**\n * Verifies the signature and returns the parsed, typed event. Throws\n * `WebhookVerificationError` if verification fails.\n */\n constructEvent(params: VerifySignatureParams): Promise<WebhookEvent> {\n return constructEvent(params);\n }\n}\n\nexport class WebhookDeliveries {\n constructor(private readonly requestor: Requestor) {}\n\n /** Lists webhook delivery attempts, newest first. */\n list(params: ListParams = {}): Promise<Page<WebhookDelivery>> {\n return this.requestor.request({\n method: 'GET',\n path: '/v1/webhooks/deliveries',\n query: params,\n });\n }\n\n /** Returns a single delivery record. */\n retrieve(id: string): Promise<WebhookDelivery> {\n return this.requestor.request({\n method: 'GET',\n path: `/v1/webhooks/deliveries/${encodeURIComponent(id)}`,\n });\n }\n\n /** Re-queues a delivery as a fresh attempt; the original record is preserved. */\n resend(id: string): Promise<WebhookDelivery> {\n return this.requestor.request({\n method: 'POST',\n path: `/v1/webhooks/deliveries/${encodeURIComponent(id)}/resend`,\n });\n }\n\n /** Iterates every delivery record, following pagination cursors automatically. */\n iterate(): AsyncGenerator<WebhookDelivery> {\n return paginate((cursor) => this.list({ cursor }));\n }\n}\n","import {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n Requestor,\n type FetchLike,\n} from './core/request';\nimport { Customers } from './resources/customers';\nimport { Events } from './resources/events';\nimport { Products } from './resources/products';\nimport { Purchases } from './resources/purchases';\nimport { Tickets } from './resources/tickets';\nimport { Transactions } from './resources/transactions';\nimport { Webhooks } from './resources/webhooks';\nimport type { PingResponse } from './types/shared';\n\nexport interface NestugeConfig {\n /** Brand API key (`nk_live_…` or `nk_test_…`) from Settings → Developer. */\n apiKey: string;\n /** API origin. Defaults to `https://nestuge.com`. */\n baseUrl?: string;\n /** Extra retry attempts on 429/5xx/network errors. Defaults to 2. */\n maxRetries?: number;\n /** Per-attempt timeout in milliseconds. Defaults to 30000. */\n timeoutMs?: number;\n /** Custom fetch implementation (testing, proxies). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\nexport class Nestuge {\n readonly customers: Customers;\n readonly products: Products;\n readonly purchases: Purchases;\n readonly transactions: Transactions;\n readonly events: Events;\n readonly tickets: Tickets;\n readonly webhooks: Webhooks;\n\n private readonly requestor: Requestor;\n\n constructor(config: NestugeConfig) {\n if (!config?.apiKey) {\n throw new Error(\n 'Nestuge: an apiKey is required. Create one under Settings → Developer.',\n );\n }\n this.requestor = new Requestor({\n apiKey: config.apiKey,\n baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n fetch:\n config.fetch ??\n ((input, init) => globalThis.fetch(input, init)),\n });\n this.customers = new Customers(this.requestor);\n this.products = new Products(this.requestor);\n this.purchases = new Purchases(this.requestor);\n this.transactions = new Transactions(this.requestor);\n this.events = new Events(this.requestor);\n this.tickets = new Tickets(this.requestor);\n this.webhooks = new Webhooks(this.requestor);\n }\n\n /**\n * Authenticated health check: confirms the key works and returns the\n * resolved brand, key mode, and granted scopes. No scope required.\n */\n ping(): Promise<PingResponse> {\n return this.requestor.request({ method: 'GET', path: '/v1/ping' });\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestuge/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Official TypeScript/JavaScript SDK for the Nestuge Developer API",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,6 +23,13 @@
23
23
  "engines": {
24
24
  "node": ">=18"
25
25
  },
26
+ "scripts": {
27
+ "build": "tsup",
28
+ "typecheck": "tsc --noEmit",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest",
31
+ "prepublishOnly": "pnpm typecheck && pnpm test && pnpm build"
32
+ },
26
33
  "keywords": [
27
34
  "nestuge",
28
35
  "sdk",
@@ -32,18 +39,12 @@
32
39
  ],
33
40
  "repository": {
34
41
  "type": "git",
35
- "url": "https://github.com/nestuge/nestuge-sdk"
42
+ "url": "git+https://github.com/nestuge/nestuge-sdk.git"
36
43
  },
37
44
  "devDependencies": {
38
45
  "@types/node": "^26.1.0",
39
46
  "tsup": "^8.3.5",
40
47
  "typescript": "^5.7.3",
41
48
  "vitest": "^3.0.5"
42
- },
43
- "scripts": {
44
- "build": "tsup",
45
- "typecheck": "tsc --noEmit",
46
- "test": "vitest run",
47
- "test:watch": "vitest"
48
49
  }
49
- }
50
+ }