{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/retry.ts","../src/http.ts","../src/resources/catalogue.ts","../src/resources/orders.ts","../src/resources/quotes.ts","../src/resources/products.ts","../src/client.ts","../src/builders/order-builder.ts","../src/types/callbacks.ts","../src/webhooks.ts"],"sourcesContent":["export { ProdigiClient } from \"./client.js\";\nexport type { ProdigiClientOptions, Environment } from \"./client.js\";\nexport { OrderBuilder } from \"./builders/order-builder.js\";\nexport {\n  ProdigiError,\n  ProdigiApiError,\n  ProdigiWebhookError,\n} from \"./errors.js\";\nexport { DEFAULT_RETRY_POLICY } from \"./retry.js\";\nexport type { RetryOptions, RetryPolicy } from \"./retry.js\";\nexport { parseCallbackEvent, isCallbackEvent } from \"./webhooks.js\";\nexport * from \"./types/index.js\";\n","/** Base error class for all Prodigi SDK errors. */\nexport class ProdigiError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"ProdigiError\";\n  }\n}\n\n/** Error thrown when the Prodigi API returns a non-OK HTTP response. */\nexport class ProdigiApiError extends ProdigiError {\n  readonly statusCode: number;\n  readonly traceParent: string | null;\n  readonly data: unknown;\n\n  /**\n   * @param message - Human-readable error message from the API.\n   * @param statusCode - HTTP status code of the response.\n   * @param traceParent - Trace parent header for request tracing, if present.\n   * @param data - Raw response body from the API.\n   */\n  constructor(\n    message: string,\n    statusCode: number,\n    traceParent: string | null,\n    data: unknown,\n  ) {\n    super(message);\n    this.name = \"ProdigiApiError\";\n    this.statusCode = statusCode;\n    this.traceParent = traceParent;\n    this.data = data;\n  }\n}\n\n/** Error thrown when an incoming callback payload is not a valid Prodigi event. */\nexport class ProdigiWebhookError extends ProdigiError {\n  /** The payload that failed validation, as received. */\n  readonly payload: unknown;\n\n  /**\n   * @param message - Why the payload was rejected.\n   * @param payload - The rejected payload, for logging.\n   */\n  constructor(message: string, payload: unknown) {\n    super(message);\n    this.name = \"ProdigiWebhookError\";\n    this.payload = payload;\n  }\n}\n","/**\n * Retry policy for transient Prodigi API failures.\n *\n * Every field is optional; unset fields fall back to {@link DEFAULT_RETRY_POLICY}.\n */\nexport interface RetryOptions {\n  /** Total attempts including the first, clamped to at least 1. Default `3`. */\n  maxAttempts?: number;\n  /** Base delay for the first retry, in milliseconds. Default `500`. */\n  initialDelayMs?: number;\n  /** Upper bound on the computed exponential delay, in milliseconds. Default `8000`. */\n  maxDelayMs?: number;\n  /**\n   * Longest `Retry-After` value that will be waited out, in milliseconds.\n   * A longer `Retry-After` aborts the retry and throws. Default `30000`.\n   */\n  maxRetryAfterMs?: number;\n  /** Apply equal jitter to computed delays. Default `true`. */\n  jitter?: boolean;\n  /** Retry when `fetch` itself rejects (DNS failure, socket reset, ...). Default `true`. */\n  retryNetworkErrors?: boolean;\n}\n\n/** A fully resolved {@link RetryOptions} with no unset fields. */\nexport type RetryPolicy = Required<RetryOptions>;\n\n/** Defaults applied when a client is constructed without a `retry` option. */\nexport const DEFAULT_RETRY_POLICY: RetryPolicy = {\n  maxAttempts: 3,\n  initialDelayMs: 500,\n  maxDelayMs: 8_000,\n  maxRetryAfterMs: 30_000,\n  jitter: true,\n  retryNetworkErrors: true,\n};\n\n/**\n * Fill in unset fields from {@link DEFAULT_RETRY_POLICY}.\n * @param options - Partial policy, or `false` to disable retries entirely.\n */\nexport function resolveRetryPolicy(\n  options?: RetryOptions | false,\n): RetryPolicy {\n  if (options === false) {\n    return { ...DEFAULT_RETRY_POLICY, maxAttempts: 1 };\n  }\n\n  return {\n    maxAttempts: Math.max(\n      1,\n      Math.floor(options?.maxAttempts ?? DEFAULT_RETRY_POLICY.maxAttempts),\n    ),\n    initialDelayMs:\n      options?.initialDelayMs ?? DEFAULT_RETRY_POLICY.initialDelayMs,\n    maxDelayMs: options?.maxDelayMs ?? DEFAULT_RETRY_POLICY.maxDelayMs,\n    maxRetryAfterMs:\n      options?.maxRetryAfterMs ?? DEFAULT_RETRY_POLICY.maxRetryAfterMs,\n    jitter: options?.jitter ?? DEFAULT_RETRY_POLICY.jitter,\n    retryNetworkErrors:\n      options?.retryNetworkErrors ?? DEFAULT_RETRY_POLICY.retryNetworkErrors,\n  };\n}\n\n/**\n * Whether a response status is worth retrying.\n *\n * Covers `429 Too Many Requests` and the 5xx range. `501 Not Implemented` is\n * excluded — it is a permanent condition that will never succeed on replay.\n *\n * @param status - HTTP status code.\n */\nexport function isRetryableStatus(status: number): boolean {\n  if (status === 429) return true;\n  if (status === 501) return false;\n  return status >= 500 && status <= 599;\n}\n\n/**\n * Exponential backoff with equal jitter.\n *\n * The undelayed delay doubles per attempt (`initialDelayMs * 2 ** (attempt - 1)`)\n * and is capped at `maxDelayMs`. With jitter enabled the returned delay is drawn\n * from the upper half of that window — `capped / 2 + random() * capped / 2` — which\n * spreads retries out without ever collapsing to zero.\n *\n * @param attempt - 1-based index of the attempt that just failed.\n * @param policy - Resolved retry policy.\n * @param random - Source of randomness in `[0, 1)`. Injectable for tests.\n */\nexport function computeBackoffDelay(\n  attempt: number,\n  policy: RetryPolicy,\n  random: () => number = Math.random,\n): number {\n  const exponential = policy.initialDelayMs * 2 ** (attempt - 1);\n  const capped = Math.min(exponential, policy.maxDelayMs);\n\n  if (!policy.jitter) return capped;\n\n  return Math.round(capped / 2 + random() * (capped / 2));\n}\n\n/**\n * Parse a `Retry-After` header into milliseconds.\n *\n * Accepts both forms allowed by RFC 9110: non-negative delta-seconds, and an\n * HTTP-date. Returns `null` when the header is absent or unparseable.\n *\n * @param value - Raw header value, or `null` when not present.\n * @param nowMs - Current epoch milliseconds, used to resolve the HTTP-date form.\n */\nexport function parseRetryAfter(\n  value: string | null,\n  nowMs: number,\n): number | null {\n  if (value === null) return null;\n\n  const trimmed = value.trim();\n  if (trimmed === \"\") return null;\n\n  if (/^\\d+$/.test(trimmed)) {\n    return Number(trimmed) * 1000;\n  }\n\n  const dateMs = Date.parse(trimmed);\n  if (Number.isNaN(dateMs)) return null;\n\n  return Math.max(0, dateMs - nowMs);\n}\n","import { ProdigiApiError } from \"./errors.js\";\nimport {\n  computeBackoffDelay,\n  isRetryableStatus,\n  parseRetryAfter,\n  resolveRetryPolicy,\n  type RetryOptions,\n  type RetryPolicy,\n} from \"./retry.js\";\n\nexport interface HttpClientOptions {\n  baseUrl: string;\n  apiKey?: string;\n  /** Retry policy for transient failures, or `false` to disable retries. */\n  retry?: RetryOptions | false;\n}\n\nexport interface RequestOptions {\n  /**\n   * Marks a non-idempotent method as safe to replay, e.g. because the payload\n   * carries an idempotency key. Ignored for `GET`, which is always retryable.\n   */\n  idempotent?: boolean;\n}\n\n/** Read a response body once, tolerating empty and non-JSON payloads. */\nasync function readBody(response: Response): Promise<unknown> {\n  const text = await response.text();\n  if (text === \"\") return null;\n\n  try {\n    const parsed: unknown = JSON.parse(text);\n    return parsed;\n  } catch {\n    return text;\n  }\n}\n\n/** Pull an error message out of a parsed error body, falling back to the status. */\nfunction errorMessage(data: unknown, status: number): string {\n  if (\n    typeof data === \"object\" &&\n    data !== null &&\n    \"message\" in data &&\n    typeof (data as Record<string, unknown>).message === \"string\"\n  ) {\n    return (data as Record<string, string>).message;\n  }\n\n  return `API error: ${status}`;\n}\n\n/** Low-level HTTP client for making authenticated requests to the Prodigi API. */\nexport class HttpClient {\n  readonly baseUrl: string;\n  readonly retryPolicy: RetryPolicy;\n  private readonly apiKey: string | undefined;\n\n  constructor(options: HttpClientOptions) {\n    this.baseUrl = options.baseUrl;\n    this.apiKey = options.apiKey;\n    this.retryPolicy = resolveRetryPolicy(options.retry);\n  }\n\n  /**\n   * Send a GET request. Retried automatically on transient failures.\n   * @param path - API endpoint path (e.g. \"/orders\").\n   * @param query - Optional query parameters appended to the URL.\n   */\n  async get<T>(path: string, query?: Record<string, unknown>): Promise<T> {\n    const url = this.buildUrl(path, query);\n    return this.request<T>(url, { method: \"GET\" }, true);\n  }\n\n  /**\n   * Send a POST request.\n   *\n   * Not retried by default — a replayed POST can duplicate a side effect. Pass\n   * `{ idempotent: true }` only when the payload makes replay safe.\n   *\n   * @param path - API endpoint path (e.g. \"/orders\").\n   * @param body - Optional JSON-serializable request body.\n   * @param options - Per-request overrides.\n   */\n  async post<T>(\n    path: string,\n    body?: unknown,\n    options?: RequestOptions,\n  ): Promise<T> {\n    const url = this.buildUrl(path);\n    return this.request<T>(\n      url,\n      {\n        method: \"POST\",\n        body: body !== undefined ? JSON.stringify(body) : undefined,\n      },\n      options?.idempotent === true,\n    );\n  }\n\n  private buildUrl(path: string, query?: Record<string, unknown>): string {\n    const url = new URL(`${this.baseUrl}${path}`);\n\n    if (query) {\n      for (const [key, value] of Object.entries(query)) {\n        if (value === undefined || value === null) continue;\n\n        if (Array.isArray(value)) {\n          for (const item of value) {\n            url.searchParams.append(key, String(item));\n          }\n        } else {\n          url.searchParams.set(key, String(value));\n        }\n      }\n    }\n\n    return url.toString();\n  }\n\n  private async request<T>(\n    url: string,\n    init: RequestInit,\n    retryable: boolean,\n  ): Promise<T> {\n    const headers: Record<string, string> = {\n      \"Content-Type\": \"application/json\",\n    };\n\n    if (this.apiKey) {\n      headers[\"X-API-Key\"] = this.apiKey;\n    }\n\n    const policy = this.retryPolicy;\n    const maxAttempts = retryable ? policy.maxAttempts : 1;\n\n    for (let attempt = 1; ; attempt++) {\n      let response: Response;\n\n      try {\n        response = await globalThis.fetch(url, { ...init, headers });\n      } catch (cause) {\n        if (attempt >= maxAttempts || !policy.retryNetworkErrors) throw cause;\n        await sleep(computeBackoffDelay(attempt, policy));\n        continue;\n      }\n\n      const data = await readBody(response);\n\n      if (response.ok) {\n        return data as T;\n      }\n\n      const delayMs =\n        attempt < maxAttempts && isRetryableStatus(response.status)\n          ? this.retryDelayFor(response, attempt)\n          : null;\n\n      if (delayMs === null) {\n        throw new ProdigiApiError(\n          errorMessage(data, response.status),\n          response.status,\n          response.headers.get(\"traceparent\"),\n          data,\n        );\n      }\n\n      await sleep(delayMs);\n    }\n  }\n\n  /**\n   * Delay before replaying a retryable error response, or `null` to give up.\n   *\n   * A `Retry-After` header wins over the computed backoff, but only up to\n   * `maxRetryAfterMs` — beyond that the caller is better served by an error than\n   * by a silent multi-minute stall.\n   */\n  private retryDelayFor(response: Response, attempt: number): number | null {\n    const retryAfterMs = parseRetryAfter(\n      response.headers.get(\"retry-after\"),\n      Date.now(),\n    );\n\n    if (retryAfterMs === null) {\n      return computeBackoffDelay(attempt, this.retryPolicy);\n    }\n\n    return retryAfterMs > this.retryPolicy.maxRetryAfterMs\n      ? null\n      : retryAfterMs;\n  }\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { HttpClient } from \"../http.js\";\nimport type {\n  CatalogueListResponse,\n  CatalogueProductDetail,\n} from \"../types/index.js\";\n\n/** Resource for browsing the public Prodigi product catalogue (no authentication required). */\nexport class CatalogueResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * List all categories and products in the catalogue.\n   * @returns The full category tree.\n   */\n  async list(): Promise<CatalogueListResponse> {\n    return this.http.get<CatalogueListResponse>(\"/catalogue\");\n  }\n\n  /**\n   * Get detailed product information including SKU variants, sizes, and pricing.\n   * @param slug - The product slug (e.g. \"cold-press-watercolour-paper\").\n   */\n  async get(slug: string): Promise<CatalogueProductDetail> {\n    return this.http.get<CatalogueProductDetail>(`/catalogue/${slug}`);\n  }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type {\n  ActionOutcome,\n  CreateOrderRequest,\n  ListOrdersParams,\n  ListOrdersResponse,\n  OrderActions,\n  OrderOutcome,\n  RecipientActionOutcome,\n  ShippingActionOutcome,\n  UpdateMetadataRequest,\n  UpdateRecipientRequest,\n  UpdateShippingMethodRequest,\n} from \"../types/index.js\";\n\n/** Serialize a date filter, leaving caller-supplied strings untouched. */\nfunction toIsoDate(value: string | Date | undefined): string | undefined {\n  if (value === undefined) return undefined;\n  return value instanceof Date ? value.toISOString() : value;\n}\n\n/** Resource for managing Prodigi print orders. */\nexport class OrdersResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * Submit a new order.\n   *\n   * Retried on transient failures only when `request.idempotencyKey` is set —\n   * without one, replaying the POST could create a duplicate order.\n   *\n   * @param request - Order creation payload.\n   * @returns The created order outcome.\n   */\n  async create(request: CreateOrderRequest): Promise<OrderOutcome> {\n    return this.http.post<OrderOutcome>(\"/orders\", request, {\n      idempotent: request.idempotencyKey !== undefined,\n    });\n  }\n\n  /**\n   * Fetch a single order by ID.\n   * @param orderId - The Prodigi order ID.\n   */\n  async get(orderId: string): Promise<OrderOutcome> {\n    return this.http.get<OrderOutcome>(`/orders/${orderId}`);\n  }\n\n  /**\n   * List orders with optional filtering and pagination.\n   *\n   * Paginate with `top`/`skip`; `hasMore` on the response indicates whether\n   * further pages exist.\n   *\n   * @param params - Optional filters. Omitted filters are not sent.\n   */\n  async list(params?: ListOrdersParams): Promise<ListOrdersResponse> {\n    return this.http.get<ListOrdersResponse>(\"/orders\", {\n      top: params?.top,\n      skip: params?.skip,\n      createdFrom: toIsoDate(params?.createdFrom),\n      createdTo: toIsoDate(params?.createdTo),\n      status: params?.status,\n      orderIds: params?.orderIds,\n      merchantReferences: params?.merchantReferences,\n    });\n  }\n\n  /**\n   * Get available actions for an order.\n   * @param orderId - The Prodigi order ID.\n   */\n  async getActions(orderId: string): Promise<OrderActions> {\n    return this.http.get<OrderActions>(`/orders/${orderId}/actions`);\n  }\n\n  /**\n   * Cancel an order.\n   * @param orderId - The Prodigi order ID.\n   */\n  async cancel(orderId: string): Promise<ActionOutcome> {\n    return this.http.post<ActionOutcome>(`/orders/${orderId}/actions/cancel`);\n  }\n\n  /**\n   * Update the shipping method for an order.\n   * @param orderId - The Prodigi order ID.\n   * @param request - New shipping method details.\n   */\n  async updateShippingMethod(\n    orderId: string,\n    request: UpdateShippingMethodRequest,\n  ): Promise<ShippingActionOutcome> {\n    return this.http.post<ShippingActionOutcome>(\n      `/orders/${orderId}/actions/updateShippingMethod`,\n      request,\n    );\n  }\n\n  /**\n   * Update the recipient for an order.\n   * @param orderId - The Prodigi order ID.\n   * @param request - New recipient details.\n   */\n  async updateRecipient(\n    orderId: string,\n    request: UpdateRecipientRequest,\n  ): Promise<RecipientActionOutcome> {\n    return this.http.post<RecipientActionOutcome>(\n      `/orders/${orderId}/actions/updateRecipient`,\n      request.recipient,\n    );\n  }\n\n  /**\n   * Update metadata on an order.\n   * @param orderId - The Prodigi order ID.\n   * @param request - New metadata key-value pairs.\n   */\n  async updateMetadata(\n    orderId: string,\n    request: UpdateMetadataRequest,\n  ): Promise<ActionOutcome> {\n    return this.http.post<ActionOutcome>(\n      `/orders/${orderId}/actions/updateMetadata`,\n      request,\n    );\n  }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { CreateQuoteRequest, QuoteOutcome } from \"../types/index.js\";\n\n/** Resource for requesting shipping and cost quotes. */\nexport class QuotesResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * Request a quote for a potential order.\n   * @param request - Quote request payload.\n   * @returns The quote outcome with cost and shipping estimates.\n   */\n  async create(request: CreateQuoteRequest): Promise<QuoteOutcome> {\n    return this.http.post<QuoteOutcome>(\"/quotes\", request);\n  }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type {\n  ProductOutcome,\n  SpineRequest,\n  SpineResponse,\n} from \"../types/index.js\";\n\n/** Resource for browsing the Prodigi product catalogue. */\nexport class ProductsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * Get product details by SKU.\n   * @param sku - The product SKU.\n   */\n  async get(sku: string): Promise<ProductOutcome> {\n    return this.http.get<ProductOutcome>(`/products/${sku}`);\n  }\n\n  /**\n   * Calculate spine width for book-type products.\n   * @param request - Spine calculation parameters.\n   */\n  async getSpine(request: SpineRequest): Promise<SpineResponse> {\n    return this.http.post<SpineResponse>(\"/products/spine\", request);\n  }\n}\n","import { HttpClient } from \"./http.js\";\nimport type { RetryOptions } from \"./retry.js\";\nimport { CatalogueResource } from \"./resources/catalogue.js\";\nimport { OrdersResource } from \"./resources/orders.js\";\nimport { QuotesResource } from \"./resources/quotes.js\";\nimport { ProductsResource } from \"./resources/products.js\";\n\nconst SANDBOX_URL = \"https://api.sandbox.prodigi.com/v4.0\";\nconst PRODUCTION_URL = \"https://api.prodigi.com/v4.0\";\nconst CATALOGUE_URL = \"https://product-api-app-live.azurewebsites.net/api\";\n\nexport type Environment = \"sandbox\" | \"production\";\n\nexport interface ProdigiClientOptions {\n  apiKey: string;\n  environment?: Environment;\n  /**\n   * Retry policy for transient failures (429, 5xx, network errors), or `false`\n   * to disable retries. Defaults to 3 attempts with exponential backoff.\n   */\n  retry?: RetryOptions | false;\n}\n\n/**\n * Main client for interacting with the Prodigi API.\n *\n * @example\n * ```ts\n * const client = new ProdigiClient({\n *   apiKey: \"your-api-key\",\n *   environment: \"sandbox\",\n * });\n *\n * const order = await client.orders.create(request);\n * ```\n */\nexport class ProdigiClient {\n  readonly orders: OrdersResource;\n  readonly quotes: QuotesResource;\n  readonly products: ProductsResource;\n  readonly catalogue: CatalogueResource;\n  readonly environment: Environment;\n\n  private readonly apiKey: string;\n\n  /**\n   * @param options - Client configuration including API key and optional environment.\n   */\n  constructor(options: ProdigiClientOptions) {\n    this.apiKey = options.apiKey;\n    this.environment = options.environment ?? \"sandbox\";\n\n    const baseUrl =\n      this.environment === \"production\" ? PRODUCTION_URL : SANDBOX_URL;\n\n    const retry = options.retry;\n    const http = new HttpClient({ baseUrl, apiKey: this.apiKey, retry });\n\n    this.orders = new OrdersResource(http);\n    this.quotes = new QuotesResource(http);\n    this.products = new ProductsResource(http);\n\n    const catalogueHttp = new HttpClient({ baseUrl: CATALOGUE_URL, retry });\n    this.catalogue = new CatalogueResource(catalogueHttp);\n  }\n}\n","import { ProdigiError } from \"../errors.js\";\nimport type {\n  Asset,\n  CreateOrderItem,\n  CreateOrderRequest,\n  Recipient,\n  ShippingMethod,\n} from \"../types/index.js\";\n\n/**\n * Fluent builder for constructing order creation requests.\n *\n * @example\n * ```ts\n * const request = new OrderBuilder()\n *   .shippingMethod(\"Standard\")\n *   .recipient({ name: \"Jane\", address: { ... } })\n *   .addPrint(\"GLOBAL-PHO-4x6\", \"https://example.com/photo.jpg\")\n *   .build();\n * ```\n */\nexport class OrderBuilder {\n  private _shippingMethod?: ShippingMethod;\n  private _recipient?: Recipient;\n  private _items: CreateOrderItem[] = [];\n  private _merchantReference?: string;\n  private _metadata?: Record<string, string>;\n  private _idempotencyKey?: string;\n\n  /** Set the shipping method for the order. */\n  shippingMethod(method: ShippingMethod): this {\n    this._shippingMethod = method;\n    return this;\n  }\n\n  /** Set the recipient for the order. */\n  recipient(recipient: Recipient): this {\n    this._recipient = recipient;\n    return this;\n  }\n\n  /** Set an optional merchant reference for the order. */\n  merchantReference(ref: string): this {\n    this._merchantReference = ref;\n    return this;\n  }\n\n  /** Attach custom metadata key-value pairs to the order. */\n  metadata(metadata: Record<string, string>): this {\n    this._metadata = metadata;\n    return this;\n  }\n\n  /** Set an idempotency key to prevent duplicate orders. */\n  idempotencyKey(key: string): this {\n    this._idempotencyKey = key;\n    return this;\n  }\n\n  /** Add a fully-configured order item. */\n  addItem(item: CreateOrderItem): this {\n    this._items.push(item);\n    return this;\n  }\n\n  /**\n   * Add a print item with a single image asset.\n   * @param sku - Product SKU.\n   * @param imageUrl - URL of the image to print.\n   * @param options - Optional copies and sizing overrides.\n   */\n  addPrint(\n    sku: string,\n    imageUrl: string,\n    options?: { copies?: number; sizing?: CreateOrderItem[\"sizing\"] },\n  ): this {\n    const asset: Asset = { url: imageUrl };\n    this._items.push({\n      sku,\n      copies: options?.copies ?? 1,\n      sizing: options?.sizing ?? \"fillPrintArea\",\n      assets: [asset],\n    });\n    return this;\n  }\n\n  /**\n   * Build the order creation request.\n   * @returns A validated order request payload.\n   * @throws {ProdigiError} If shippingMethod, recipient, or items are missing.\n   */\n  build(): CreateOrderRequest {\n    if (!this._shippingMethod) {\n      throw new ProdigiError(\"shippingMethod is required\");\n    }\n    if (!this._recipient) {\n      throw new ProdigiError(\"recipient is required\");\n    }\n    if (this._items.length === 0) {\n      throw new ProdigiError(\"At least one item is required\");\n    }\n\n    return {\n      shippingMethod: this._shippingMethod,\n      recipient: this._recipient,\n      items: this._items,\n      ...(this._merchantReference && {\n        merchantReference: this._merchantReference,\n      }),\n      ...(this._metadata && { metadata: this._metadata }),\n      ...(this._idempotencyKey && { idempotencyKey: this._idempotencyKey }),\n    };\n  }\n}\n","import type { Order } from \"./orders.js\";\n\n/** Payload of a Prodigi callback: the order at the moment the event was created. */\nexport interface CallbackEventData {\n  order: Order;\n}\n\n/**\n * Raw CloudEvents v1.0 envelope as delivered by Prodigi.\n *\n * @see https://www.prodigi.com/print-api/docs/reference/#callbacks\n */\nexport interface CallbackEvent {\n  /** CloudEvents spec version, e.g. `\"1.0\"`. */\n  specversion: string;\n  /** Reverse-DNS event type with a `#fragment` new value, e.g. `\"com.prodigi.order.status.stage.changed#InProgress\"`. */\n  type: string;\n  /** URI of the environment that produced the event, e.g. `\"https://api.prodigi.com/v4.0/Orders/\"`. */\n  source: string;\n  /** Unique event id, prefixed `evt_`. */\n  id: string;\n  /** RFC 3339 timestamp of when the event was generated. */\n  time: string;\n  /** Always `\"application/json\"`. */\n  datacontenttype: string;\n  /** The object that produced the callback — the order id. */\n  subject: string;\n  data: CallbackEventData;\n}\n\n/**\n * CloudEvents `type` Prodigi sends when an order changes fulfilment stage.\n *\n * Documented verbatim in the Prodigi reference.\n */\nexport const ORDER_STAGE_CHANGED_TYPE =\n  \"com.prodigi.order.status.stage.changed\";\n\n/**\n * CloudEvents `type` prefix for shipment callbacks.\n *\n * Prodigi documents that callbacks fire \"when a shipment is made\" and that the\n * `type` is built from the path to the nested object, but does not publish the\n * literal string. This prefix follows that documented convention; anything that\n * does not match still parses, as an {@link UnknownCallbackEvent}.\n */\nexport const ORDER_SHIPMENT_TYPE_PREFIX = \"com.prodigi.order.shipments\";\n\n/** Fields shared by every parsed callback event. */\nexport interface CallbackEventBase {\n  /** The raw envelope exactly as delivered, for logging or replay. */\n  event: CallbackEvent;\n  /** Unique event id, prefixed `evt_`. */\n  id: string;\n  /** Order id the callback relates to (CloudEvents `subject`). */\n  subject: string;\n  /** RFC 3339 timestamp of when the event was generated. */\n  time: string;\n  /** The order carried by the callback. */\n  order: Order;\n  /** CloudEvents `type` with the `#fragment` stripped. */\n  eventType: string;\n  /** Value after `#` in the CloudEvents `type`, e.g. `\"InProgress\"`. Empty when absent. */\n  changedTo: string;\n}\n\n/**\n * An order moved between fulfilment stages.\n *\n * `changedTo` carries the raw fragment; `order.status.stage` carries the same\n * value already narrowed to {@link OrderStage}.\n */\nexport interface OrderStageChangedEvent extends CallbackEventBase {\n  kind: \"order.status.stage.changed\";\n}\n\n/** A shipment was made against the order. */\nexport interface OrderShipmentEvent extends CallbackEventBase {\n  kind: \"order.shipments.shipment\";\n}\n\n/**\n * A structurally valid callback whose `type` this SDK does not recognise.\n *\n * Newer Prodigi event types land here rather than throwing, so a handler keeps\n * working when Prodigi adds events. Inspect `eventType` and `event` directly.\n */\nexport interface UnknownCallbackEvent extends CallbackEventBase {\n  kind: \"unknown\";\n}\n\n/** Discriminated union of parsed Prodigi callbacks, keyed on `kind`. */\nexport type ProdigiCallbackEvent =\n  | OrderStageChangedEvent\n  | OrderShipmentEvent\n  | UnknownCallbackEvent;\n","import { ProdigiWebhookError } from \"./errors.js\";\nimport {\n  ORDER_SHIPMENT_TYPE_PREFIX,\n  ORDER_STAGE_CHANGED_TYPE,\n  type CallbackEvent,\n  type ProdigiCallbackEvent,\n} from \"./types/callbacks.js\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n  return typeof value === \"string\" && value.length > 0;\n}\n\n/**\n * Structural type guard for a Prodigi callback envelope.\n *\n * Checks the CloudEvents envelope and that `data.order.id` is present. It does\n * not deep-validate the order — Prodigi may add fields at any time.\n *\n * This is a shape check, **not** an authenticity check. See\n * {@link parseCallbackEvent} for why.\n *\n * @param payload - Parsed JSON body of the callback request.\n */\nexport function isCallbackEvent(payload: unknown): payload is CallbackEvent {\n  if (!isRecord(payload)) return false;\n\n  if (!isNonEmptyString(payload.specversion)) return false;\n  if (!isNonEmptyString(payload.type)) return false;\n  if (!isNonEmptyString(payload.source)) return false;\n  if (!isNonEmptyString(payload.id)) return false;\n  if (!isNonEmptyString(payload.time)) return false;\n  if (!isNonEmptyString(payload.datacontenttype)) return false;\n  if (!isNonEmptyString(payload.subject)) return false;\n\n  const data = payload.data;\n  if (!isRecord(data)) return false;\n\n  const order = data.order;\n  if (!isRecord(order)) return false;\n\n  return isNonEmptyString(order.id);\n}\n\n/** Split a CloudEvents `type` into its base type and `#fragment`. */\nfunction splitType(type: string): { eventType: string; changedTo: string } {\n  const index = type.indexOf(\"#\");\n\n  if (index === -1) return { eventType: type, changedTo: \"\" };\n\n  return {\n    eventType: type.slice(0, index),\n    changedTo: type.slice(index + 1),\n  };\n}\n\nfunction parseJson(text: string): unknown {\n  try {\n    const parsed: unknown = JSON.parse(text);\n    return parsed;\n  } catch {\n    throw new ProdigiWebhookError(\"Callback body is not valid JSON\", text);\n  }\n}\n\n/**\n * Validate an incoming Prodigi callback and parse it into a typed event.\n *\n * ## Authenticity\n *\n * Prodigi does **not** sign callbacks. There is no signature header, shared\n * secret, or other authentication mechanism in the v4.0 API, so this function\n * cannot and does not verify that a request genuinely came from Prodigi — it\n * validates shape only. Protect your endpoint by treating the callback URL\n * itself as the secret (a long unguessable path) and, before acting on\n * anything that matters, re-reading the order with\n * `client.orders.get(event.subject)`.\n *\n * @param payload - The request body, either a JSON string or already-parsed JSON.\n * @returns A discriminated union member keyed on `kind`.\n * @throws {ProdigiWebhookError} If the body is not JSON, or not a Prodigi callback envelope.\n *\n * @example\n * ```ts\n * const event = parseCallbackEvent(await request.text());\n *\n * switch (event.kind) {\n *   case \"order.status.stage.changed\":\n *     console.log(event.subject, event.order.status.stage);\n *     break;\n *   case \"order.shipments.shipment\":\n *     console.log(event.order.shipments);\n *     break;\n *   case \"unknown\":\n *     console.log(\"unhandled event\", event.eventType);\n *     break;\n * }\n * ```\n */\nexport function parseCallbackEvent(payload: unknown): ProdigiCallbackEvent {\n  const raw = typeof payload === \"string\" ? parseJson(payload) : payload;\n\n  if (!isCallbackEvent(raw)) {\n    throw new ProdigiWebhookError(\n      \"Payload is not a valid Prodigi callback event\",\n      raw,\n    );\n  }\n\n  const { eventType, changedTo } = splitType(raw.type);\n\n  const base = {\n    event: raw,\n    id: raw.id,\n    subject: raw.subject,\n    time: raw.time,\n    order: raw.data.order,\n    eventType,\n    changedTo,\n  };\n\n  if (eventType === ORDER_STAGE_CHANGED_TYPE) {\n    return { ...base, kind: \"order.status.stage.changed\" };\n  }\n\n  if (eventType.startsWith(ORDER_SHIPMENT_TYPE_PREFIX)) {\n    return { ...base, kind: \"order.shipments.shipment\" };\n  }\n\n  return { ...base, kind: \"unknown\" };\n}\n"],"mappings":"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","names":[]}