/** * @module sdkCatalog * * SDKCatalogClient — typed wrapper for seller product catalog CRUD. * * Server API: POST/GET/PATCH/DELETE /api/sdk/catalog/products[/:ref] * Auth: SDK JWT with scope catalog:read:* / catalog:write:* in * Authorization: Bearer header. * * Pattern: separate class (mirrors SDKPushClient) — SDKChatClient is * already ~2900 lines; catalog is a distinct API surface. * * Product metadata (title, price, currency, imageUrl, productUrl) is * non-sensitive and server-visible — same E2EE-relaxed design as the * existing product card message kind (W9). See: * docs/superpowers/plans/2026-05-13-marketplace-chat-roadmap.md:324 */ import type { ProductMeta } from './types.js'; export type SDKCatalogErrorCode = 'invalid_args' | 'network' | 'aborted' | 'server_4xx' | 'server_5xx' | 'not_found' | 'conflict' | 'validation_error'; export declare class SDKCatalogError extends Error { readonly code: SDKCatalogErrorCode; readonly status: number; readonly cause: Error | Response | unknown; constructor(code: SDKCatalogErrorCode, message: string, cause: Error | Response | unknown, status?: number); } /** A product in the seller's catalog (camelCase SDK surface). */ export interface CatalogProduct { productRef: string; productMeta: ProductMeta; createdAt: string; updatedAt: string; archivedAt: string | null; } /** * #195: Result of GET /api/sdk/catalog/products. The wire envelope is * `{ products, has_more, next_cursor }` (snake_case); this is the mapped * camelCase surface returned to SDK consumers. */ export interface CatalogProductList { products: CatalogProduct[]; hasMore: boolean; nextCursor?: string; } /** * Typed wrapper for the seller product catalog API. * * Usage: * ```ts * import { SDKCatalogClient } from '@oxpulse/chat-sdk'; * * const catalog = new SDKCatalogClient({ * baseUrl: 'https://chat.example.com', * jwt: rawJwt, // NO "Bearer " prefix * }); * * // Create a product * const product = await catalog.createProduct({ * productRef: 'sku-123', * productMeta: { title: 'Widget', price: 19.99, currency: 'USD', imageUrl: '', productUrl: '' }, * }); * * // List all products * const { products, hasMore, nextCursor } = await catalog.listProducts(); * * // Send a product card in chat (using existing SDKChatClient) * chatClient.setProductCard(product.productRef, product.productMeta); * ``` */ export declare class SDKCatalogClient { private readonly jwt; private readonly baseUrl; /** * @param args.jwt Raw SDK JWT with scope catalog:read:* and/or catalog:write:*. * Do NOT include "Bearer " prefix — the wrapper adds it. * @param args.baseUrl Optional URL prefix; default ''. * * @throws {SDKCatalogError} code='invalid_args' if jwt starts with "Bearer ". */ constructor(args: { jwt: string; baseUrl?: string; }); /** * Create a new product in the seller's catalog. * * Idempotent: if a product with the same productRef already exists for * this seller, returns the existing row (200 OK from server). * * @throws {SDKCatalogError} code='validation_error' if product_meta is invalid. * @throws {SDKCatalogError} code='conflict' if product_ref is owned by another seller. * @throws {SDKCatalogError} code='network' / 'server_4xx' / 'server_5xx' on transport errors. */ createProduct(args: { productRef: string; productMeta: ProductMeta; signal?: AbortSignal; }): Promise; /** * List active products in the seller's catalog (newest first), with * cursor-based pagination. * * @param opts.limit Max products to return (server-capped). * @param opts.cursor Opaque cursor from a prior `nextCursor` (next page). * @param opts.signal Optional AbortSignal to cancel the request. * @returns `{ products, hasMore, nextCursor }` — mapped from the snake_case * `{ products, has_more, next_cursor }` envelope. * @throws {SDKCatalogError} code='validation_error' on a malformed cursor (400). * @throws {SDKCatalogError} on transport/auth errors. */ listProducts(opts?: { limit?: number; cursor?: string; signal?: AbortSignal; }): Promise; /** * Get a single product by product_ref. * * @throws {SDKCatalogError} code='not_found' if the product doesn't exist or is archived. */ getProduct(productRef: string, signal?: AbortSignal): Promise; /** * Update product_meta for an existing product. * * @throws {SDKCatalogError} code='not_found' if the product doesn't exist or is archived. * @throws {SDKCatalogError} code='validation_error' if product_meta is invalid. */ updateProduct(productRef: string, args: { productMeta: ProductMeta; signal?: AbortSignal; }): Promise; /** * Soft-delete (archive) a product. Messages referencing this product_ref * still render because they carry a product_meta snapshot. * * @throws {SDKCatalogError} code='not_found' if the product doesn't exist or is already archived. */ deleteProduct(productRef: string, signal?: AbortSignal): Promise; private request; } //# sourceMappingURL=catalog.d.ts.map