brainerce 1.58.0 → 1.58.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/README.md CHANGED
@@ -269,33 +269,33 @@ the credential, no customer token needed.
269
269
 
270
270
  The SDK exports these utility functions for common UI tasks:
271
271
 
272
- | Function | Purpose | Example |
273
- | ---------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
274
- | `formatPrice(amount, { currency?, locale? })` | Format prices for display | `formatPrice("99.99", { currency: 'USD' })` → `$99.99` |
275
- | `getPriceDisplay(amount, currency?, locale?)` | Alias for `formatPrice` | Same as above |
276
- | `getDescriptionContent(product)` | Get product description (HTML or text) | `getDescriptionContent(product)` |
277
- | `isHtmlDescription(product)` | Check if description is HTML | `isHtmlDescription(product)` → `true/false` |
278
- | `getStockStatus(inventory)` | Get human-readable stock status | `getStockStatus(inventory)` → `"In Stock"` |
279
- | `getProductPrice(product)` | Get effective price (handles sales) | `getProductPrice(product)` → `29.99` |
280
- | `getProductPriceInfo(product)` | Get price + sale info + discount % (falls back to `priceMin` when `basePrice=0` on VARIABLE) | `{ price, isOnSale, discountPercent }` |
281
- | `getVariantPrice(variant, basePrice)` | Get variant price with fallback | `getVariantPrice(variant, '29.99')` → `34.99` |
282
- | `getCartTotals(cart, shippingPrice?)` | Calculate cart subtotal/discount/total | `{ subtotal, discount, shipping, total }` |
283
- | `getCartItemName(item)` | Get name from nested cart item (product + variant) | `getCartItemName(item)` → `"Blue T-Shirt - Large"` |
284
- | `getCartItemImage(item)` | Get image URL from cart item | `getCartItemImage(item)` → `"https://..."` |
285
- | `getVariantOptions(variant)` | Get variant attributes as array | `[{ name: "Color", value: "Red" }]` |
286
- | `isCouponApplicableToProduct(coupon, product)` | Check if coupon applies | `isCouponApplicableToProduct(coupon, product)` |
287
- | `isAllowedPaymentUrl(url, options?)` | Validate a payment URL host | `isAllowedPaymentUrl(intent.clientSecret)` → `true` |
288
- | `safePaymentRedirect(url, options?)` | Validate then `window.location.href` | `safePaymentRedirect(intent.clientSecret)` |
289
- | `buildProductJsonLd(product, opts)` | schema.org Product JSON-LD (PDPs only) | See SEO section |
290
- | `buildArticleJsonLd(post, opts)` | schema.org Article JSON-LD for blog posts | See SEO section |
291
- | `buildOrganizationJsonLd(store, opts)` | schema.org Organization for the homepage | See SEO section |
292
- | `buildBreadcrumbJsonLd(items)` | schema.org BreadcrumbList | See SEO section |
293
- | `buildProductFaqJsonLd(product)` | schema.org FAQPage from `product.faq` (null when empty) — render the same pairs as visible text | `const faq = buildProductFaqJsonLd(product)` |
294
- | `jsonLdScriptProps(data)` | XSS-safe `<script type="application/ld+json">` props | `<script {...jsonLdScriptProps(data)} />` |
295
- | `getBlogSitemapEntries(client, opts)` | Paginate published posts into sitemap entries | See SEO section |
296
- | `getProductSitemapEntries(client, opts)` | ALL published products into sitemap entries (no 100-item clamp) | See SEO section |
297
- | `getCategorySitemapEntries(client, opts)` | Category tree into sitemap entries | See SEO section |
298
- | `client.resolveSlugRedirect(type, slug)` | Renamed slug → current slug (301 support in not-found paths) | See SEO section |
272
+ | Function | Purpose | Example |
273
+ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
274
+ | `formatPrice(amount, { currency?, locale? })` | Format prices for display | `formatPrice("99.99", { currency: 'USD' })` → `$99.99` |
275
+ | `getPriceDisplay(amount, currency?, locale?)` | Alias for `formatPrice` | Same as above |
276
+ | `getDescriptionContent(product)` | Get product description (HTML or text) | `getDescriptionContent(product)` |
277
+ | `isHtmlDescription(product)` | Check if description is HTML | `isHtmlDescription(product)` → `true/false` |
278
+ | `getStockStatus(inventory)` | Get human-readable stock status | `getStockStatus(inventory)` → `"In Stock"` |
279
+ | `getProductPrice(product)` | Get effective price (handles sales) | `getProductPrice(product)` → `29.99` |
280
+ | `getProductPriceInfo(product)` | Get price + sale info + discount % (falls back to `priceMin` when `basePrice=0` on VARIABLE) | `{ price, isOnSale, discountPercent }` |
281
+ | `getVariantPrice(variant, basePrice)` | Get variant price with fallback | `getVariantPrice(variant, '29.99')` → `34.99` |
282
+ | `getCartTotals(cart, shippingPrice?)` | Calculate cart subtotal/discount/total | `{ subtotal, discount, shipping, total }` |
283
+ | `getCartItemName(item)` | Get name from nested cart item (product + variant) | `getCartItemName(item)` → `"Blue T-Shirt - Large"` |
284
+ | `getCartItemImage(item)` | Get image URL from cart item | `getCartItemImage(item)` → `"https://..."` |
285
+ | `getVariantOptions(variant)` | Get variant attributes as array | `[{ name: "Color", value: "Red" }]` |
286
+ | `isCouponApplicableToProduct(coupon, product)` | Check if coupon applies | `isCouponApplicableToProduct(coupon, product)` |
287
+ | `isAllowedPaymentUrl(url, options?)` | Validate a payment URL host | `isAllowedPaymentUrl(intent.clientSecret)` → `true` |
288
+ | `safePaymentRedirect(url, options?)` | Validate then `window.location.href` | `safePaymentRedirect(intent.clientSecret)` |
289
+ | `buildProductJsonLd(product, opts)` | schema.org Product JSON-LD (PDPs only) | See SEO section |
290
+ | `buildArticleJsonLd(post, opts)` | schema.org Article JSON-LD for blog posts | See SEO section |
291
+ | `buildOrganizationJsonLd(store, opts)` | schema.org Organization for the homepage | See SEO section |
292
+ | `buildBreadcrumbJsonLd(items)` | schema.org BreadcrumbList | See SEO section |
293
+ | `buildProductFaqJsonLd(product)` | schema.org FAQPage from `product.faq` (null when empty) — render the same pairs as visible text | `const faq = buildProductFaqJsonLd(product)` |
294
+ | `jsonLdScriptProps(data)` | XSS-safe `<script type="application/ld+json">` props | `<script {...jsonLdScriptProps(data)} />` |
295
+ | `getBlogSitemapEntries(client, opts)` | Paginate published posts into sitemap entries | See SEO section |
296
+ | `getProductSitemapEntries(client, opts)` | ALL published products into sitemap entries (no 100-item clamp) | See SEO section |
297
+ | `getCategorySitemapEntries(client, opts)` | Category tree into sitemap entries | See SEO section |
298
+ | `client.resolveSlugRedirect(type, slug)` | Renamed slug → current slug (301 support in not-found paths) | See SEO section |
299
299
 
300
300
  ```typescript
301
301
  import {
@@ -1033,6 +1033,16 @@ text. Suggestions come from Google Places; each resolved address is flagged
1033
1033
  `inZone` against the store's configured shipping zones — a soft signal for a
1034
1034
  warning banner, never a hard block.
1035
1035
 
1036
+ Suggestions are limited to deliverable address types (street addresses, routes,
1037
+ buildings, sub-premises). Businesses, stations and other establishments are
1038
+ never returned — a courier cannot deliver to one. A shopper who types only a
1039
+ landmark name gets an empty list and has to type the street.
1040
+
1041
+ `inZone` resolves a zone's currency-region restriction the same way the checkout
1042
+ does — destination country first, then the `regionId` you pass, then the store's
1043
+ default region — so a `true` here is not contradicted by the rates you fetch
1044
+ afterwards.
1045
+
1036
1046
  ```typescript
1037
1047
  const sessionToken = crypto.randomUUID(); // one per address-entry attempt
1038
1048
 
@@ -4285,6 +4295,118 @@ await client.bulkSaveVariants(variableProduct.id, {
4285
4295
 
4286
4296
  **GTIN vs MPN:** these are two different identifiers, not interchangeable — GTIN (EAN/UPC/ISBN) is a universal barcode; MPN is manufacturer-specific and only meaningful paired with a brand. Provide GTIN when the product has one; otherwise brand + MPN. A product typically needs one or the other, not both.
4287
4297
 
4298
+ ### Bulk Product Creation (catalog import)
4299
+
4300
+ Importing a catalog — a supplier feed, a CSV/Excel export, a store migration —
4301
+ should not be thousands of `createProduct` calls. `bulkCreateProducts` takes an
4302
+ array and returns a **job id**: the work is queued, and the products appear over
4303
+ the following seconds or minutes.
4304
+
4305
+ ```typescript
4306
+ import type {
4307
+ BulkCreateProductsDto,
4308
+ BulkCreateProductsJob,
4309
+ BulkCreateProductsStatus,
4310
+ } from 'brainerce';
4311
+
4312
+ const job: BulkCreateProductsJob = await client.bulkCreateProducts({
4313
+ products: [
4314
+ {
4315
+ name: 'Classic T-Shirt',
4316
+ sku: 'TSH-001',
4317
+ externalId: 'supplier-88213', // your source-system id — makes retries safe
4318
+ basePrice: 29.99,
4319
+ type: 'SIMPLE',
4320
+ categoryNames: ['Apparel'], // auto-created if missing
4321
+ brandNames: ['Acme'],
4322
+ tags: ['summer'],
4323
+ inventory: { total: 100 },
4324
+ },
4325
+ // ...up to 1000 per call
4326
+ ],
4327
+ importId: 'supplier-catalog-2026-08-21', // ties chunks of one import together
4328
+ conflictStrategy: 'skip', // 'skip' (default) | 'error'
4329
+ });
4330
+
4331
+ console.log(job.jobId, job.total); // the import has STARTED, not finished
4332
+ ```
4333
+
4334
+ **This call does not return the created products.** Poll for progress:
4335
+
4336
+ ```typescript
4337
+ let status: BulkCreateProductsStatus = await client.getBulkCreateProductsStatus(job.jobId);
4338
+ while (status.status === 'QUEUED' || status.status === 'RUNNING') {
4339
+ await new Promise((r) => setTimeout(r, 2000));
4340
+ status = await client.getBulkCreateProductsStatus(job.jobId);
4341
+ }
4342
+
4343
+ // succeeded = created. skipped = already existed, NOT created.
4344
+ // "succeeded + skipped" is not the number of products you imported.
4345
+ console.log(status.succeeded, status.skipped, status.failed, status.pending);
4346
+ ```
4347
+
4348
+ `COMPLETED_WITH_ERRORS` means the import finished and some rows failed — there
4349
+ is nothing to re-run. Read the failures instead; each carries the 1-indexed
4350
+ `row` from the array you submitted, so it maps back to the line of the source
4351
+ spreadsheet:
4352
+
4353
+ ```typescript
4354
+ if (status.failed > 0) {
4355
+ const { data, meta } = await client.getBulkCreateProductsErrors(job.jobId, { limit: 100 });
4356
+ for (const e of data) {
4357
+ console.log(`row ${e.row} (${e.sku ?? e.productName}): [${e.code}] ${e.message}`);
4358
+ }
4359
+ // Every failure is stored — nothing is truncated — so walk the pages.
4360
+ console.log(`${meta.total} failures across ${meta.totalPages} pages`);
4361
+ }
4362
+ ```
4363
+
4364
+ **Importing 3,000-50,000 products.** A single request is capped at 1000 rows
4365
+ (500 is the comfortable size) because validating a huge nested array costs real
4366
+ CPU in the request handler. Chunk the catalog and pass the same `importId` on
4367
+ every call, then poll **once** for the whole import:
4368
+
4369
+ ```typescript
4370
+ const importId = `migration-${Date.now()}`;
4371
+ for (const chunk of chunks(allProducts, 500)) {
4372
+ await client.bulkCreateProducts({
4373
+ products: chunk,
4374
+ importId,
4375
+ idempotencyKey: `${importId}-${chunkIndex}`, // re-sending returns the original job
4376
+ });
4377
+ }
4378
+
4379
+ const overall = await client.getBulkCreateProductsImportStatus(importId);
4380
+ console.log(`${overall.processed}/${overall.total}`, overall.status);
4381
+ ```
4382
+
4383
+ `getBulkCreateProductsImportStatus` reports the least-complete state across the
4384
+ chunks and leaves `finishedAt` null until every one has finished, so a partial
4385
+ result can never read as a finished import.
4386
+
4387
+ **Duplicates.** A row whose `sku` or `externalId` already exists in the store is
4388
+ skipped rather than duplicated — so a batch re-sent after a timeout cannot
4389
+ create the catalog twice. This is a database-level check, so it still holds days
4390
+ later and across retries. Rows carrying **neither** a `sku` nor an `externalId`
4391
+ have nothing to match on and will be created again on a re-send; set
4392
+ `externalId` on rows without SKUs. Pass `conflictStrategy: 'error'` when a
4393
+ duplicate means the source file is wrong and you want it reported rather than
4394
+ skipped.
4395
+
4396
+ **One difference from `createProduct`.** If a row's explicit `slug` is already
4397
+ taken, the importer appends a suffix (`t-shirt`, `t-shirt-1`, ...) and imports
4398
+ the row, where `createProduct` returns a 400. Rows colliding with each other
4399
+ inside the same batch are resolved the same way, in submission order. That is
4400
+ deliberate — a spreadsheet with two "T-Shirt" rows should import, not fail — but
4401
+ it means the slug you sent is not always the slug you get. Read it back from
4402
+ the product if you depend on it.
4403
+
4404
+ **Channel sync.** By default (`syncMode: 'coalesced'`) the per-product push to
4405
+ connected sales channels is suppressed during the import and one sync per
4406
+ affected channel is filed at the end — connectors are rate-limited per catalog,
4407
+ and a per-product fan-out would exhaust those limits. Use `syncMode: 'none'` to
4408
+ write to Brainerce only.
4409
+
4288
4410
  ### Taxonomy Management
4289
4411
 
4290
4412
  ```typescript
@@ -6021,6 +6143,8 @@ The widget persists an anonymous session in `localStorage`, restores conversatio
6021
6143
 
6022
6144
  **Add to cart resolution** (never a dead button): the widget first calls your `onAddToCart` option; without one it dispatches a cancelable `brainerce:bot:add-to-cart` `CustomEvent` on `window` (`detail: { productId, variantId, quantity, connectionId }` — call `preventDefault()` after handling it); if nothing handles either, it navigates to the product page. Products too complex for in-chat picking (3+ attribute dimensions or 25+ variants) always navigate. Aside from your own cart handler, the widget is read-only by design — shoppers can never mutate the store through it.
6023
6145
 
6146
+ **Where the bot is allowed to load.** Every widget call — bootstrap, chat, escalation — is validated against the page's `Origin` and the domain configured on the connection, the same rule the rest of the storefront API uses. A **Live** connection accepts only its configured domain (exact host or a subdomain) plus any additional allowed origins it lists; a **Test** connection with no domain accepts any origin, which is what makes `localhost` and preview URLs work; a Test connection _with_ a domain behaves like Live. A blocked origin is **not** an error — the bot simply does not render, indistinguishable from "switched off", so nobody can probe which connection ids exist. Mount client-side: server-rendered calls carry no `Origin` and a Live connection refuses them.
6147
+
6024
6148
  Merchant-side display controls (Studio → Storefront Bot): chat size (compact / full screen / shopper's choice), auto-open, position, and whether shoppers may expand the window (`allowExpand`).
6025
6149
 
6026
6150
  ## Webhooks
package/dist/index.d.mts CHANGED
@@ -1480,6 +1480,16 @@ interface CreateProductDto {
1480
1480
  gtin?: string;
1481
1481
  /** Manufacturer Part Number — used by Google Shopping (with brand) when no GTIN exists. */
1482
1482
  mpn?: string;
1483
+ /**
1484
+ * Your own stable identifier for this product in the SOURCE system (supplier
1485
+ * feed, legacy store, ERP). Unique per store.
1486
+ *
1487
+ * Exists for retry-safety on imports: re-sending a batch after a timeout
1488
+ * matches on this value and skips the product instead of creating a
1489
+ * duplicate. Set it on rows that have no SKU, which would otherwise have
1490
+ * nothing to dedup on.
1491
+ */
1492
+ externalId?: string;
1483
1493
  description?: string;
1484
1494
  basePrice: number;
1485
1495
  salePrice?: number;
@@ -1509,6 +1519,103 @@ interface CreateProductDto {
1509
1519
  /** Unit shared by shippingLengthValue/shippingWidthValue/shippingHeightValue. */
1510
1520
  shippingDimensionUnit?: 'cm' | 'in';
1511
1521
  }
1522
+ /**
1523
+ * Payload for `bulkCreateProducts`.
1524
+ *
1525
+ * Each entry in `products` accepts everything `createProduct` accepts. The call
1526
+ * is QUEUED — it returns a job id, not the created products.
1527
+ */
1528
+ interface BulkCreateProductsDto {
1529
+ /**
1530
+ * The products to create. At most 1000 per request (500 is the comfortable
1531
+ * size). Split a larger catalog across several calls carrying the same
1532
+ * `importId`.
1533
+ *
1534
+ * Rows are validated INDIVIDUALLY on the server: an invalid row is reported
1535
+ * as a row failure in `getBulkCreateProductsErrors`, it does not reject the
1536
+ * batch. So a supplier file with a few bad rows still imports the good ones.
1537
+ */
1538
+ products: CreateProductDto[];
1539
+ /**
1540
+ * Ties several calls together as ONE logical import, so a 50,000-product
1541
+ * catalog sent as 100 requests is polled once via
1542
+ * `getBulkCreateProductsImportStatus` rather than 100 times.
1543
+ */
1544
+ importId?: string;
1545
+ /**
1546
+ * What to do with a row whose `sku` or `externalId` already exists in the
1547
+ * store. `'skip'` (default) counts it under `skipped`; `'error'` records it
1548
+ * as a failure instead.
1549
+ */
1550
+ conflictStrategy?: 'skip' | 'error';
1551
+ /**
1552
+ * Channel sync behaviour. `'coalesced'` (default) suppresses the per-product
1553
+ * connector push and files one sync per affected sales channel once the
1554
+ * import finishes. `'none'` writes to Brainerce only.
1555
+ */
1556
+ syncMode?: 'coalesced' | 'none';
1557
+ /**
1558
+ * Durable dedup key for this batch. Re-sending the same key returns the
1559
+ * ORIGINAL job id instead of importing again. The `Idempotency-Key` header
1560
+ * does the same thing over HTTP; this field is stored in the database rather
1561
+ * than Redis, so it outlives the header's 24h window.
1562
+ */
1563
+ idempotencyKey?: string;
1564
+ }
1565
+ /** What `bulkCreateProducts` returns. The import has been accepted, not finished. */
1566
+ interface BulkCreateProductsJob {
1567
+ jobId: string;
1568
+ importId: string | null;
1569
+ status: BulkCreateProductsStatus['status'];
1570
+ total: number;
1571
+ /** True when an existing job was returned because the idempotency key matched. */
1572
+ replayed: boolean;
1573
+ }
1574
+ /**
1575
+ * Progress of a queued product import.
1576
+ *
1577
+ * `skipped` counts rows that already existed and were NOT created — they are
1578
+ * neither successes nor failures, so `succeeded` alone is the number of
1579
+ * products this import added.
1580
+ */
1581
+ interface BulkCreateProductsStatus {
1582
+ jobId: string;
1583
+ importId: string | null;
1584
+ /**
1585
+ * `COMPLETED_WITH_ERRORS` means every row was attempted and some failed —
1586
+ * nothing to retry wholesale; read the failures with
1587
+ * `getBulkCreateProductsErrors`. `FAILED` means the job itself died and the
1588
+ * batch can be re-sent.
1589
+ */
1590
+ status: 'QUEUED' | 'RUNNING' | 'COMPLETED' | 'COMPLETED_WITH_ERRORS' | 'FAILED' | 'CANCELLED';
1591
+ total: number;
1592
+ processed: number;
1593
+ succeeded: number;
1594
+ failed: number;
1595
+ skipped: number;
1596
+ /** `total - processed`. */
1597
+ pending: number;
1598
+ conflictStrategy: string;
1599
+ syncMode: string;
1600
+ /** Set only when the JOB failed (infrastructure), never for a row failure. */
1601
+ errorMessage: string | null;
1602
+ startedAt: string | null;
1603
+ /** On an aggregate read, stays null until every chunk has finished. */
1604
+ finishedAt: string | null;
1605
+ createdAt: string;
1606
+ /** Present only on an aggregate (importId) read: how many chunks rolled up. */
1607
+ jobCount?: number;
1608
+ }
1609
+ /** One failed row from a product import. */
1610
+ interface BulkCreateProductsError {
1611
+ /** 1-indexed position in the `products` array you submitted. */
1612
+ row: number;
1613
+ sku: string | null;
1614
+ externalId: string | null;
1615
+ productName: string | null;
1616
+ code: 'VALIDATION' | 'DUPLICATE' | 'PLAN_LIMIT' | 'INTERNAL' | string;
1617
+ message: string;
1618
+ }
1512
1619
  interface UpdateProductDto {
1513
1620
  name?: string;
1514
1621
  slug?: string;
@@ -7102,6 +7209,82 @@ declare class BrainerceClient {
7102
7209
  * Create a new product
7103
7210
  */
7104
7211
  createProduct(data: CreateProductDto): Promise<Product>;
7212
+ /**
7213
+ * Create many products in one call.
7214
+ *
7215
+ * QUEUED, not immediate: this returns a job id straight away and the products
7216
+ * appear over the following seconds or minutes. It does NOT return the
7217
+ * created products — poll {@link getBulkCreateProductsStatus} with the
7218
+ * returned `jobId`.
7219
+ *
7220
+ * Every field {@link createProduct} accepts is accepted per row, including
7221
+ * variants, categories, brands, tags, images, translations and tax behaviour.
7222
+ *
7223
+ * At most 1000 products per call (500 is the comfortable size). For a
7224
+ * 3,000-50,000 product catalog, send several calls carrying the same
7225
+ * `importId` and poll {@link getBulkCreateProductsImportStatus} once for the
7226
+ * whole import.
7227
+ *
7228
+ * Retry-safe: a row whose `sku` or `externalId` already exists is skipped
7229
+ * rather than duplicated, so re-sending a batch after a timeout cannot create
7230
+ * the catalog twice. Pass `idempotencyKey` to have an identical re-send
7231
+ * return the original job instead of starting a second import.
7232
+ *
7233
+ * @example
7234
+ * ```typescript
7235
+ * const job = await client.bulkCreateProducts({
7236
+ * products: rows.map((r) => ({
7237
+ * name: r.title,
7238
+ * sku: r.sku,
7239
+ * externalId: r.supplier_id,
7240
+ * basePrice: Number(r.price),
7241
+ * type: 'SIMPLE',
7242
+ * categoryNames: [r.category],
7243
+ * })),
7244
+ * importId: 'supplier-catalog-2026-08-21',
7245
+ * });
7246
+ *
7247
+ * let status = await client.getBulkCreateProductsStatus(job.jobId);
7248
+ * while (status.status === 'QUEUED' || status.status === 'RUNNING') {
7249
+ * await new Promise((r) => setTimeout(r, 2000));
7250
+ * status = await client.getBulkCreateProductsStatus(job.jobId);
7251
+ * }
7252
+ * // `succeeded` is what was created; `skipped` already existed.
7253
+ * console.log(status.succeeded, status.skipped, status.failed);
7254
+ * ```
7255
+ */
7256
+ bulkCreateProducts(data: BulkCreateProductsDto): Promise<BulkCreateProductsJob>;
7257
+ /**
7258
+ * Progress of one queued product import.
7259
+ *
7260
+ * Read the counters literally: `skipped` rows already existed and were NOT
7261
+ * created, so `succeeded` alone is what this import added.
7262
+ *
7263
+ * `COMPLETED_WITH_ERRORS` means the import finished with some rows failing —
7264
+ * that is not something to re-run; read the failures with
7265
+ * {@link getBulkCreateProductsErrors}.
7266
+ */
7267
+ getBulkCreateProductsStatus(jobId: string): Promise<BulkCreateProductsStatus>;
7268
+ /**
7269
+ * Aggregate progress across every batch that shared an `importId`.
7270
+ *
7271
+ * The status is the least-complete state across the chunks, and `finishedAt`
7272
+ * stays null until all of them have finished — so a caller cannot mistake
7273
+ * "the first 500 landed" for "the catalog is imported".
7274
+ */
7275
+ getBulkCreateProductsImportStatus(importId: string): Promise<BulkCreateProductsStatus>;
7276
+ /**
7277
+ * Per-row failures for a product import, paginated.
7278
+ *
7279
+ * Every failure is recorded — nothing is truncated — so walk the pages when
7280
+ * `meta.totalPages > 1`. Each entry carries the 1-indexed `row` from the
7281
+ * array you submitted, so a failure maps back to the line of the source
7282
+ * spreadsheet.
7283
+ */
7284
+ getBulkCreateProductsErrors(jobId: string, options?: {
7285
+ page?: number;
7286
+ limit?: number;
7287
+ }): Promise<PaginatedResponse<BulkCreateProductsError>>;
7105
7288
  /**
7106
7289
  * Update an existing product
7107
7290
  */
@@ -8039,11 +8222,18 @@ declare class BrainerceClient {
8039
8222
  * @param options.redirectUrl - Where to send the browser once OAuth finishes —
8040
8223
  * on success *and* on failure. Validated server-side against the sales
8041
8224
  * channel's trusted origins, so what is accepted depends on the mode:
8042
- * - vibe-coded (`salesChannelId: 'vc_*'`): an absolute URL on the channel's
8043
- * registered `domain` or one of its `allowedOrigins`; in TEST mode, any
8044
- * `localhost`/`127.0.0.1` port. A relative path (`/auth/callback`) also
8045
- * works it is resolved against the channel's `domain` on the way back,
8046
- * so the channel must have one registered.
8225
+ * - vibe-coded (`salesChannelId: 'vc_*'`), **LIVE**: an `https` URL on the
8226
+ * channel's registered `domain`, or on a subdomain of it. Nothing else
8227
+ * `allowedOrigins` grants no OAuth redirect on a LIVE channel, and an
8228
+ * `http://` target is refused even on the registered domain. You
8229
+ * therefore cannot complete social login from `localhost` against a LIVE
8230
+ * channel; use a TEST channel for that.
8231
+ * - vibe-coded, **TEST**: the above, plus an **exact** match (scheme, host
8232
+ * and port) against one of the channel's `allowedOrigins`, plus any
8233
+ * `localhost`/`127.0.0.1`/`[::1]` port.
8234
+ * - Either mode: a relative path (`/auth/callback`) also works — it is
8235
+ * resolved against the channel's `domain` on the way back, so the channel
8236
+ * must have one registered.
8047
8237
  * - storefront (`storeId`): **social login cannot round-trip in this mode.**
8048
8238
  * No channel is bound to the request, so an absolute URL has no
8049
8239
  * trusted-origin list to match (400 at this call) and a relative path has
@@ -11963,4 +12153,4 @@ interface CategorySitemapOptions {
11963
12153
  */
11964
12154
  declare function getCategorySitemapEntries(client: BrainerceClient, opts: CategorySitemapOptions): Promise<SitemapEntry[]>;
11965
12155
 
11966
- export { type AddToCartDto, type AddressDetailsResult, type AddressSuggestion, type AnnouncementContent, type AnnouncementSeverity, type AppliedDiscount, type ApplyCouponDto, type AttachModifierGroupInput, type Attribute, type AttributeOption, type AttributeSource, type BlogPost, type BlogPostListParams, type BlogPostListResponse, type BlogSitemapOptions, type BrainerceApiError, BrainerceClient, type BrainerceClientOptions, BrainerceError, type Brand, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type BusinessHoursWindow, type Cart, type CartAppliedDiscount, type CartBundleOffer, type CartBundlesResponse, type CartIncludeOption, type CartIncludeOptions, type CartItem, type CartItemModifierLine, type CartNudge, type CartRecommendationsResponse, type CartStatus, type CartUpgradeSuggestion, type CartUpgradesResponse, type CartWithIncludes, type Category, type CategoryDetail, type CategoryNode, type CategorySitemapOptions, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutBumpsResponse, type CheckoutCustomFieldDefinition, type CheckoutFieldPricing, type CheckoutFieldVisibility, type CheckoutLineItem, type CheckoutPrefillData, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConfigureOAuthProviderDto as ConfigureOAuthProviderInput, type ConflictStatus, type ConnectorPlatform, type ContactFormFieldType, type ContactFormFieldValidation, type ContactFormPublic, type ContactFormPublicField, type ContactFormSummary, type Content, type ContentDataMap, type ContentStatus, type ContentSummary, type ContentType, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateAttributeDto as CreateAttributeInput, type CreateAttributeOptionDto as CreateAttributeOptionInput, type CreateBrandDto as CreateBrandInput, type CreateCategoryDto as CreateCategoryInput, type CreateCheckoutDto, type CreateContentInput, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateEmailTemplateDto as CreateEmailTemplateInput, type CreateGuestOrderDto, type CreateInquiryInput, type CreateInquiryResponse, type CreateMetafieldDefinitionDto as CreateMetafieldDefinitionInput, type CreateModifierGroupInput, type CreateModifierInput, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateShippingRateDto as CreateShippingRateInput, type CreateShippingZoneDto as CreateShippingZoneInput, type CreateTagDto as CreateTagInput, type CreateTaxRateDto as CreateTaxRateInput, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DateAvailabilityConstraints, type DateFieldParseResult, type DeleteProductResponse, type DiscountBanner, type DiscountRuleType, type DownloadFile, type DraftLineItem, type EditInventoryDto, type EmailDomain, type EmailEventSettings, type EmailEventType, type EmailSettings, type EmailTemplate, type EmailTemplatePreview, type EmailTemplatesResponse, type EmailVerificationResponse, type ExtendReservationResponse, type FaqContent, type FaqItem, type FooterColumn, type FooterContent, type FooterLink, type FooterSocialLink, type FormatPriceOptions, type FormatProductPriceOptions, type FreeAllocationPolicy, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type HeaderContent, type HeaderCta, type HeaderLogo, type HeaderNavItem, type InsufficientStockError, type InventoryInfo, type InventoryReservationStrategy, type InventorySyncStatus, type InventoryTrackingMode, type InvitationStatus, type InviteMemberDto as InviteMemberInput, type InviteStoreMemberDto as InviteStoreMemberInput, type JsonLdOptions, type ListModifierGroupsParams, type LocalCart, type LocalCartItem, type LockedVariant, type LoyaltyNextTierSummary, type LoyaltyReward, type LoyaltyStatus, type LoyaltyTierSummary, type MergeCartsDto, type MetafieldConflict, type MetafieldConflictResolution, type MetafieldDefinition, type MetafieldFilter, type MetafieldFilterValue, type MetafieldFiltersResponse, type MetafieldType, type Modifier, type ModifierGroup, type ModifierSelection, type ModifierSelectionType, type ModifierValidationCode, type ModifierValidationError, type MyProductReview, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProviderConfig, type OAuthProviderType, type OAuthProvidersResponse, type Order, type OrderAddress, type OrderBump, type OrderCustomer, type OrderDownloadLink, type OrderItem, type OrderQueryParams, type OrderStatus, type OrderStatusChange, type PageContent, type PageSeo, type PaginatedResponse, type ParsedDateFieldValue, type PaymentClientSdk, type PaymentConfig, type PaymentIntent, type PaymentProvider, type PaymentProviderConfig, type PaymentProvidersConfig, type PaymentStatus, type PaymentUrlOptions, type PickupLocation, type PlatformCouponCapabilities, type PlatformMetafieldMetadata, type PreviewEmailTemplateDto as PreviewEmailTemplateInput, type Product, type ProductAttributeInput, type ProductAvailability, type ProductCustomizationField, type ProductDiscount, type ProductDiscountBadge, type ProductImage, type ProductMetafield, type ProductMetafieldValue, type ProductModifierGroupAttachment, type ProductQueryParams, type ProductRecommendation, type ProductRecommendationsResponse, type ProductRelationType, type ProductReview, type ProductReviewAdmin, type ProductSitemapOptions, type ProductSuggestion, type ProductVariant, type PublicMetafieldDefinition, type PublishProductResponse, RTL_LOCALES, type RecommendationVariant, type ReconcileInventoryResponse, type RedeemRewardResult, type ReferralInfo, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type ReservationInfo, type ResolveMetafieldConflictDto as ResolveMetafieldConflictInput, type ResolveSyncConflictDto as ResolveSyncConflictInput, type RichTextContent, SDK_VERSION, type SearchSuggestions, type SelectPickupLocationDto, type SelectShippingMethodDto, type SendInvoiceDto, type SessionCartRef, type SetBillingAddressDto, type SetCheckoutCustomFieldsDto, type SetCheckoutCustomerDto, type SetDefinitionProductsDto as SetDefinitionProductsInput, type SetMetafieldPlatformsDto as SetMetafieldPlatformsInput, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingDestinations, type ShippingLine, type ShippingRate, type ShippingRateConfig, type ShippingRateType, type ShippingSummaryEntry, type ShippingZone, type ShippingZoneQueryParams, type SitemapEntry, type StockAvailabilityRequest, type StockAvailabilityResponse, type StockAvailabilityResult, type StoreInfo, type StoreInvitation, type StoreInvitationDetails, type StoreMember, type StorePermission, type StoreRole, type StoreTeamResponse, type StoreTracking, type SubmitProductReviewInput, type SupportedLocaleObject, type SyncConflict, type SyncConflictResolution, type SyncJob, type Tag, type TaxBreakdown, type TaxBreakdownItem, type TaxRate, type TaxonomyQueryParams, type TeamInvitation, type TeamInvitationsResponse, type TeamMember, type TeamMembersResponse, type TeamRole, type TrackingEventItem, type TrackingEventName, type TrackingEventPayload, type UpdateAddressDto, type UpdateAttachmentInput, type UpdateAttributeDto as UpdateAttributeInput, type UpdateAttributeOptionDto as UpdateAttributeOptionInput, type UpdateBrandDto as UpdateBrandInput, type UpdateCartItemDto, type UpdateCategoryDto as UpdateCategoryInput, type UpdateContentInput, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateEmailSettingsDto as UpdateEmailSettingsInput, type UpdateEmailTemplateDto as UpdateEmailTemplateInput, type UpdateInventoryDto, type UpdateMemberRoleDto as UpdateMemberRoleInput, type UpdateMetafieldDefinitionDto as UpdateMetafieldDefinitionInput, type UpdateModifierGroupInput, type UpdateModifierInput, type UpdateOAuthProviderDto as UpdateOAuthProviderInput, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateShippingRateDto as UpdateShippingRateInput, type UpdateShippingZoneDto as UpdateShippingZoneInput, type UpdateStoreMemberDto as UpdateStoreMemberInput, type UpdateTagDto as UpdateTagInput, type UpdateTaxRateDto as UpdateTaxRateInput, type UpdateVariantDto, type UpdateVariantInventoryDto, type UpsertProductMetafieldDto as UpsertProductMetafieldInput, type UserStore, type UserStorePermissions, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WaitForOrderOptions, type WaitForOrderResult, type WebhookEvent, type WebhookEventType, type WriteProductReviewInput, buildArticleJsonLd, buildBreadcrumbJsonLd, buildCollectionPageJsonLd, buildOrganizationJsonLd, buildProductFaqJsonLd, buildProductJsonLd, buildWebsiteJsonLd, computeAvailableSlots, createWebhookHandler, deriveSeoDescription, enableDevGuards, formatMoney, formatPrice, formatProductPrice, formatVariantPrice, getBlogSitemapEntries, getBusinessHoursForDate, getCartItemImage, getCartItemName, getCartTotals, getCategorySitemapEntries, getDescriptionContent, getDirectionForLocale, formatPrice as getPriceDisplay, getProductCustomizationFields, getProductMetafield, getProductMetafieldValue, getProductMetafieldsByType, getProductPrice, getProductPriceInfo, getProductSitemapEntries, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCalendarDateAllowed, isCouponApplicableToProduct, isDateValueAllowed, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseDateFieldValue, parseWebhookEvent, resolveStoreLocalParts, safePaymentRedirect, stripHtml, validateDateAvailabilityConfig, verifyWebhook };
12156
+ export { type AddToCartDto, type AddressDetailsResult, type AddressSuggestion, type AnnouncementContent, type AnnouncementSeverity, type AppliedDiscount, type ApplyCouponDto, type AttachModifierGroupInput, type Attribute, type AttributeOption, type AttributeSource, type BlogPost, type BlogPostListParams, type BlogPostListResponse, type BlogSitemapOptions, type BrainerceApiError, BrainerceClient, type BrainerceClientOptions, BrainerceError, type Brand, type BulkCreateProductsDto, type BulkCreateProductsError, type BulkCreateProductsJob, type BulkCreateProductsStatus, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type BusinessHoursWindow, type Cart, type CartAppliedDiscount, type CartBundleOffer, type CartBundlesResponse, type CartIncludeOption, type CartIncludeOptions, type CartItem, type CartItemModifierLine, type CartNudge, type CartRecommendationsResponse, type CartStatus, type CartUpgradeSuggestion, type CartUpgradesResponse, type CartWithIncludes, type Category, type CategoryDetail, type CategoryNode, type CategorySitemapOptions, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutBumpsResponse, type CheckoutCustomFieldDefinition, type CheckoutFieldPricing, type CheckoutFieldVisibility, type CheckoutLineItem, type CheckoutPrefillData, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConfigureOAuthProviderDto as ConfigureOAuthProviderInput, type ConflictStatus, type ConnectorPlatform, type ContactFormFieldType, type ContactFormFieldValidation, type ContactFormPublic, type ContactFormPublicField, type ContactFormSummary, type Content, type ContentDataMap, type ContentStatus, type ContentSummary, type ContentType, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateAttributeDto as CreateAttributeInput, type CreateAttributeOptionDto as CreateAttributeOptionInput, type CreateBrandDto as CreateBrandInput, type CreateCategoryDto as CreateCategoryInput, type CreateCheckoutDto, type CreateContentInput, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateEmailTemplateDto as CreateEmailTemplateInput, type CreateGuestOrderDto, type CreateInquiryInput, type CreateInquiryResponse, type CreateMetafieldDefinitionDto as CreateMetafieldDefinitionInput, type CreateModifierGroupInput, type CreateModifierInput, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateShippingRateDto as CreateShippingRateInput, type CreateShippingZoneDto as CreateShippingZoneInput, type CreateTagDto as CreateTagInput, type CreateTaxRateDto as CreateTaxRateInput, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DateAvailabilityConstraints, type DateFieldParseResult, type DeleteProductResponse, type DiscountBanner, type DiscountRuleType, type DownloadFile, type DraftLineItem, type EditInventoryDto, type EmailDomain, type EmailEventSettings, type EmailEventType, type EmailSettings, type EmailTemplate, type EmailTemplatePreview, type EmailTemplatesResponse, type EmailVerificationResponse, type ExtendReservationResponse, type FaqContent, type FaqItem, type FooterColumn, type FooterContent, type FooterLink, type FooterSocialLink, type FormatPriceOptions, type FormatProductPriceOptions, type FreeAllocationPolicy, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type HeaderContent, type HeaderCta, type HeaderLogo, type HeaderNavItem, type InsufficientStockError, type InventoryInfo, type InventoryReservationStrategy, type InventorySyncStatus, type InventoryTrackingMode, type InvitationStatus, type InviteMemberDto as InviteMemberInput, type InviteStoreMemberDto as InviteStoreMemberInput, type JsonLdOptions, type ListModifierGroupsParams, type LocalCart, type LocalCartItem, type LockedVariant, type LoyaltyNextTierSummary, type LoyaltyReward, type LoyaltyStatus, type LoyaltyTierSummary, type MergeCartsDto, type MetafieldConflict, type MetafieldConflictResolution, type MetafieldDefinition, type MetafieldFilter, type MetafieldFilterValue, type MetafieldFiltersResponse, type MetafieldType, type Modifier, type ModifierGroup, type ModifierSelection, type ModifierSelectionType, type ModifierValidationCode, type ModifierValidationError, type MyProductReview, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProviderConfig, type OAuthProviderType, type OAuthProvidersResponse, type Order, type OrderAddress, type OrderBump, type OrderCustomer, type OrderDownloadLink, type OrderItem, type OrderQueryParams, type OrderStatus, type OrderStatusChange, type PageContent, type PageSeo, type PaginatedResponse, type ParsedDateFieldValue, type PaymentClientSdk, type PaymentConfig, type PaymentIntent, type PaymentProvider, type PaymentProviderConfig, type PaymentProvidersConfig, type PaymentStatus, type PaymentUrlOptions, type PickupLocation, type PlatformCouponCapabilities, type PlatformMetafieldMetadata, type PreviewEmailTemplateDto as PreviewEmailTemplateInput, type Product, type ProductAttributeInput, type ProductAvailability, type ProductCustomizationField, type ProductDiscount, type ProductDiscountBadge, type ProductImage, type ProductMetafield, type ProductMetafieldValue, type ProductModifierGroupAttachment, type ProductQueryParams, type ProductRecommendation, type ProductRecommendationsResponse, type ProductRelationType, type ProductReview, type ProductReviewAdmin, type ProductSitemapOptions, type ProductSuggestion, type ProductVariant, type PublicMetafieldDefinition, type PublishProductResponse, RTL_LOCALES, type RecommendationVariant, type ReconcileInventoryResponse, type RedeemRewardResult, type ReferralInfo, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type ReservationInfo, type ResolveMetafieldConflictDto as ResolveMetafieldConflictInput, type ResolveSyncConflictDto as ResolveSyncConflictInput, type RichTextContent, SDK_VERSION, type SearchSuggestions, type SelectPickupLocationDto, type SelectShippingMethodDto, type SendInvoiceDto, type SessionCartRef, type SetBillingAddressDto, type SetCheckoutCustomFieldsDto, type SetCheckoutCustomerDto, type SetDefinitionProductsDto as SetDefinitionProductsInput, type SetMetafieldPlatformsDto as SetMetafieldPlatformsInput, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingDestinations, type ShippingLine, type ShippingRate, type ShippingRateConfig, type ShippingRateType, type ShippingSummaryEntry, type ShippingZone, type ShippingZoneQueryParams, type SitemapEntry, type StockAvailabilityRequest, type StockAvailabilityResponse, type StockAvailabilityResult, type StoreInfo, type StoreInvitation, type StoreInvitationDetails, type StoreMember, type StorePermission, type StoreRole, type StoreTeamResponse, type StoreTracking, type SubmitProductReviewInput, type SupportedLocaleObject, type SyncConflict, type SyncConflictResolution, type SyncJob, type Tag, type TaxBreakdown, type TaxBreakdownItem, type TaxRate, type TaxonomyQueryParams, type TeamInvitation, type TeamInvitationsResponse, type TeamMember, type TeamMembersResponse, type TeamRole, type TrackingEventItem, type TrackingEventName, type TrackingEventPayload, type UpdateAddressDto, type UpdateAttachmentInput, type UpdateAttributeDto as UpdateAttributeInput, type UpdateAttributeOptionDto as UpdateAttributeOptionInput, type UpdateBrandDto as UpdateBrandInput, type UpdateCartItemDto, type UpdateCategoryDto as UpdateCategoryInput, type UpdateContentInput, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateEmailSettingsDto as UpdateEmailSettingsInput, type UpdateEmailTemplateDto as UpdateEmailTemplateInput, type UpdateInventoryDto, type UpdateMemberRoleDto as UpdateMemberRoleInput, type UpdateMetafieldDefinitionDto as UpdateMetafieldDefinitionInput, type UpdateModifierGroupInput, type UpdateModifierInput, type UpdateOAuthProviderDto as UpdateOAuthProviderInput, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateShippingRateDto as UpdateShippingRateInput, type UpdateShippingZoneDto as UpdateShippingZoneInput, type UpdateStoreMemberDto as UpdateStoreMemberInput, type UpdateTagDto as UpdateTagInput, type UpdateTaxRateDto as UpdateTaxRateInput, type UpdateVariantDto, type UpdateVariantInventoryDto, type UpsertProductMetafieldDto as UpsertProductMetafieldInput, type UserStore, type UserStorePermissions, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WaitForOrderOptions, type WaitForOrderResult, type WebhookEvent, type WebhookEventType, type WriteProductReviewInput, buildArticleJsonLd, buildBreadcrumbJsonLd, buildCollectionPageJsonLd, buildOrganizationJsonLd, buildProductFaqJsonLd, buildProductJsonLd, buildWebsiteJsonLd, computeAvailableSlots, createWebhookHandler, deriveSeoDescription, enableDevGuards, formatMoney, formatPrice, formatProductPrice, formatVariantPrice, getBlogSitemapEntries, getBusinessHoursForDate, getCartItemImage, getCartItemName, getCartTotals, getCategorySitemapEntries, getDescriptionContent, getDirectionForLocale, formatPrice as getPriceDisplay, getProductCustomizationFields, getProductMetafield, getProductMetafieldValue, getProductMetafieldsByType, getProductPrice, getProductPriceInfo, getProductSitemapEntries, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCalendarDateAllowed, isCouponApplicableToProduct, isDateValueAllowed, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseDateFieldValue, parseWebhookEvent, resolveStoreLocalParts, safePaymentRedirect, stripHtml, validateDateAvailabilityConfig, verifyWebhook };
package/dist/index.d.ts CHANGED
@@ -1480,6 +1480,16 @@ interface CreateProductDto {
1480
1480
  gtin?: string;
1481
1481
  /** Manufacturer Part Number — used by Google Shopping (with brand) when no GTIN exists. */
1482
1482
  mpn?: string;
1483
+ /**
1484
+ * Your own stable identifier for this product in the SOURCE system (supplier
1485
+ * feed, legacy store, ERP). Unique per store.
1486
+ *
1487
+ * Exists for retry-safety on imports: re-sending a batch after a timeout
1488
+ * matches on this value and skips the product instead of creating a
1489
+ * duplicate. Set it on rows that have no SKU, which would otherwise have
1490
+ * nothing to dedup on.
1491
+ */
1492
+ externalId?: string;
1483
1493
  description?: string;
1484
1494
  basePrice: number;
1485
1495
  salePrice?: number;
@@ -1509,6 +1519,103 @@ interface CreateProductDto {
1509
1519
  /** Unit shared by shippingLengthValue/shippingWidthValue/shippingHeightValue. */
1510
1520
  shippingDimensionUnit?: 'cm' | 'in';
1511
1521
  }
1522
+ /**
1523
+ * Payload for `bulkCreateProducts`.
1524
+ *
1525
+ * Each entry in `products` accepts everything `createProduct` accepts. The call
1526
+ * is QUEUED — it returns a job id, not the created products.
1527
+ */
1528
+ interface BulkCreateProductsDto {
1529
+ /**
1530
+ * The products to create. At most 1000 per request (500 is the comfortable
1531
+ * size). Split a larger catalog across several calls carrying the same
1532
+ * `importId`.
1533
+ *
1534
+ * Rows are validated INDIVIDUALLY on the server: an invalid row is reported
1535
+ * as a row failure in `getBulkCreateProductsErrors`, it does not reject the
1536
+ * batch. So a supplier file with a few bad rows still imports the good ones.
1537
+ */
1538
+ products: CreateProductDto[];
1539
+ /**
1540
+ * Ties several calls together as ONE logical import, so a 50,000-product
1541
+ * catalog sent as 100 requests is polled once via
1542
+ * `getBulkCreateProductsImportStatus` rather than 100 times.
1543
+ */
1544
+ importId?: string;
1545
+ /**
1546
+ * What to do with a row whose `sku` or `externalId` already exists in the
1547
+ * store. `'skip'` (default) counts it under `skipped`; `'error'` records it
1548
+ * as a failure instead.
1549
+ */
1550
+ conflictStrategy?: 'skip' | 'error';
1551
+ /**
1552
+ * Channel sync behaviour. `'coalesced'` (default) suppresses the per-product
1553
+ * connector push and files one sync per affected sales channel once the
1554
+ * import finishes. `'none'` writes to Brainerce only.
1555
+ */
1556
+ syncMode?: 'coalesced' | 'none';
1557
+ /**
1558
+ * Durable dedup key for this batch. Re-sending the same key returns the
1559
+ * ORIGINAL job id instead of importing again. The `Idempotency-Key` header
1560
+ * does the same thing over HTTP; this field is stored in the database rather
1561
+ * than Redis, so it outlives the header's 24h window.
1562
+ */
1563
+ idempotencyKey?: string;
1564
+ }
1565
+ /** What `bulkCreateProducts` returns. The import has been accepted, not finished. */
1566
+ interface BulkCreateProductsJob {
1567
+ jobId: string;
1568
+ importId: string | null;
1569
+ status: BulkCreateProductsStatus['status'];
1570
+ total: number;
1571
+ /** True when an existing job was returned because the idempotency key matched. */
1572
+ replayed: boolean;
1573
+ }
1574
+ /**
1575
+ * Progress of a queued product import.
1576
+ *
1577
+ * `skipped` counts rows that already existed and were NOT created — they are
1578
+ * neither successes nor failures, so `succeeded` alone is the number of
1579
+ * products this import added.
1580
+ */
1581
+ interface BulkCreateProductsStatus {
1582
+ jobId: string;
1583
+ importId: string | null;
1584
+ /**
1585
+ * `COMPLETED_WITH_ERRORS` means every row was attempted and some failed —
1586
+ * nothing to retry wholesale; read the failures with
1587
+ * `getBulkCreateProductsErrors`. `FAILED` means the job itself died and the
1588
+ * batch can be re-sent.
1589
+ */
1590
+ status: 'QUEUED' | 'RUNNING' | 'COMPLETED' | 'COMPLETED_WITH_ERRORS' | 'FAILED' | 'CANCELLED';
1591
+ total: number;
1592
+ processed: number;
1593
+ succeeded: number;
1594
+ failed: number;
1595
+ skipped: number;
1596
+ /** `total - processed`. */
1597
+ pending: number;
1598
+ conflictStrategy: string;
1599
+ syncMode: string;
1600
+ /** Set only when the JOB failed (infrastructure), never for a row failure. */
1601
+ errorMessage: string | null;
1602
+ startedAt: string | null;
1603
+ /** On an aggregate read, stays null until every chunk has finished. */
1604
+ finishedAt: string | null;
1605
+ createdAt: string;
1606
+ /** Present only on an aggregate (importId) read: how many chunks rolled up. */
1607
+ jobCount?: number;
1608
+ }
1609
+ /** One failed row from a product import. */
1610
+ interface BulkCreateProductsError {
1611
+ /** 1-indexed position in the `products` array you submitted. */
1612
+ row: number;
1613
+ sku: string | null;
1614
+ externalId: string | null;
1615
+ productName: string | null;
1616
+ code: 'VALIDATION' | 'DUPLICATE' | 'PLAN_LIMIT' | 'INTERNAL' | string;
1617
+ message: string;
1618
+ }
1512
1619
  interface UpdateProductDto {
1513
1620
  name?: string;
1514
1621
  slug?: string;
@@ -7102,6 +7209,82 @@ declare class BrainerceClient {
7102
7209
  * Create a new product
7103
7210
  */
7104
7211
  createProduct(data: CreateProductDto): Promise<Product>;
7212
+ /**
7213
+ * Create many products in one call.
7214
+ *
7215
+ * QUEUED, not immediate: this returns a job id straight away and the products
7216
+ * appear over the following seconds or minutes. It does NOT return the
7217
+ * created products — poll {@link getBulkCreateProductsStatus} with the
7218
+ * returned `jobId`.
7219
+ *
7220
+ * Every field {@link createProduct} accepts is accepted per row, including
7221
+ * variants, categories, brands, tags, images, translations and tax behaviour.
7222
+ *
7223
+ * At most 1000 products per call (500 is the comfortable size). For a
7224
+ * 3,000-50,000 product catalog, send several calls carrying the same
7225
+ * `importId` and poll {@link getBulkCreateProductsImportStatus} once for the
7226
+ * whole import.
7227
+ *
7228
+ * Retry-safe: a row whose `sku` or `externalId` already exists is skipped
7229
+ * rather than duplicated, so re-sending a batch after a timeout cannot create
7230
+ * the catalog twice. Pass `idempotencyKey` to have an identical re-send
7231
+ * return the original job instead of starting a second import.
7232
+ *
7233
+ * @example
7234
+ * ```typescript
7235
+ * const job = await client.bulkCreateProducts({
7236
+ * products: rows.map((r) => ({
7237
+ * name: r.title,
7238
+ * sku: r.sku,
7239
+ * externalId: r.supplier_id,
7240
+ * basePrice: Number(r.price),
7241
+ * type: 'SIMPLE',
7242
+ * categoryNames: [r.category],
7243
+ * })),
7244
+ * importId: 'supplier-catalog-2026-08-21',
7245
+ * });
7246
+ *
7247
+ * let status = await client.getBulkCreateProductsStatus(job.jobId);
7248
+ * while (status.status === 'QUEUED' || status.status === 'RUNNING') {
7249
+ * await new Promise((r) => setTimeout(r, 2000));
7250
+ * status = await client.getBulkCreateProductsStatus(job.jobId);
7251
+ * }
7252
+ * // `succeeded` is what was created; `skipped` already existed.
7253
+ * console.log(status.succeeded, status.skipped, status.failed);
7254
+ * ```
7255
+ */
7256
+ bulkCreateProducts(data: BulkCreateProductsDto): Promise<BulkCreateProductsJob>;
7257
+ /**
7258
+ * Progress of one queued product import.
7259
+ *
7260
+ * Read the counters literally: `skipped` rows already existed and were NOT
7261
+ * created, so `succeeded` alone is what this import added.
7262
+ *
7263
+ * `COMPLETED_WITH_ERRORS` means the import finished with some rows failing —
7264
+ * that is not something to re-run; read the failures with
7265
+ * {@link getBulkCreateProductsErrors}.
7266
+ */
7267
+ getBulkCreateProductsStatus(jobId: string): Promise<BulkCreateProductsStatus>;
7268
+ /**
7269
+ * Aggregate progress across every batch that shared an `importId`.
7270
+ *
7271
+ * The status is the least-complete state across the chunks, and `finishedAt`
7272
+ * stays null until all of them have finished — so a caller cannot mistake
7273
+ * "the first 500 landed" for "the catalog is imported".
7274
+ */
7275
+ getBulkCreateProductsImportStatus(importId: string): Promise<BulkCreateProductsStatus>;
7276
+ /**
7277
+ * Per-row failures for a product import, paginated.
7278
+ *
7279
+ * Every failure is recorded — nothing is truncated — so walk the pages when
7280
+ * `meta.totalPages > 1`. Each entry carries the 1-indexed `row` from the
7281
+ * array you submitted, so a failure maps back to the line of the source
7282
+ * spreadsheet.
7283
+ */
7284
+ getBulkCreateProductsErrors(jobId: string, options?: {
7285
+ page?: number;
7286
+ limit?: number;
7287
+ }): Promise<PaginatedResponse<BulkCreateProductsError>>;
7105
7288
  /**
7106
7289
  * Update an existing product
7107
7290
  */
@@ -8039,11 +8222,18 @@ declare class BrainerceClient {
8039
8222
  * @param options.redirectUrl - Where to send the browser once OAuth finishes —
8040
8223
  * on success *and* on failure. Validated server-side against the sales
8041
8224
  * channel's trusted origins, so what is accepted depends on the mode:
8042
- * - vibe-coded (`salesChannelId: 'vc_*'`): an absolute URL on the channel's
8043
- * registered `domain` or one of its `allowedOrigins`; in TEST mode, any
8044
- * `localhost`/`127.0.0.1` port. A relative path (`/auth/callback`) also
8045
- * works it is resolved against the channel's `domain` on the way back,
8046
- * so the channel must have one registered.
8225
+ * - vibe-coded (`salesChannelId: 'vc_*'`), **LIVE**: an `https` URL on the
8226
+ * channel's registered `domain`, or on a subdomain of it. Nothing else
8227
+ * `allowedOrigins` grants no OAuth redirect on a LIVE channel, and an
8228
+ * `http://` target is refused even on the registered domain. You
8229
+ * therefore cannot complete social login from `localhost` against a LIVE
8230
+ * channel; use a TEST channel for that.
8231
+ * - vibe-coded, **TEST**: the above, plus an **exact** match (scheme, host
8232
+ * and port) against one of the channel's `allowedOrigins`, plus any
8233
+ * `localhost`/`127.0.0.1`/`[::1]` port.
8234
+ * - Either mode: a relative path (`/auth/callback`) also works — it is
8235
+ * resolved against the channel's `domain` on the way back, so the channel
8236
+ * must have one registered.
8047
8237
  * - storefront (`storeId`): **social login cannot round-trip in this mode.**
8048
8238
  * No channel is bound to the request, so an absolute URL has no
8049
8239
  * trusted-origin list to match (400 at this call) and a relative path has
@@ -11963,4 +12153,4 @@ interface CategorySitemapOptions {
11963
12153
  */
11964
12154
  declare function getCategorySitemapEntries(client: BrainerceClient, opts: CategorySitemapOptions): Promise<SitemapEntry[]>;
11965
12155
 
11966
- export { type AddToCartDto, type AddressDetailsResult, type AddressSuggestion, type AnnouncementContent, type AnnouncementSeverity, type AppliedDiscount, type ApplyCouponDto, type AttachModifierGroupInput, type Attribute, type AttributeOption, type AttributeSource, type BlogPost, type BlogPostListParams, type BlogPostListResponse, type BlogSitemapOptions, type BrainerceApiError, BrainerceClient, type BrainerceClientOptions, BrainerceError, type Brand, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type BusinessHoursWindow, type Cart, type CartAppliedDiscount, type CartBundleOffer, type CartBundlesResponse, type CartIncludeOption, type CartIncludeOptions, type CartItem, type CartItemModifierLine, type CartNudge, type CartRecommendationsResponse, type CartStatus, type CartUpgradeSuggestion, type CartUpgradesResponse, type CartWithIncludes, type Category, type CategoryDetail, type CategoryNode, type CategorySitemapOptions, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutBumpsResponse, type CheckoutCustomFieldDefinition, type CheckoutFieldPricing, type CheckoutFieldVisibility, type CheckoutLineItem, type CheckoutPrefillData, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConfigureOAuthProviderDto as ConfigureOAuthProviderInput, type ConflictStatus, type ConnectorPlatform, type ContactFormFieldType, type ContactFormFieldValidation, type ContactFormPublic, type ContactFormPublicField, type ContactFormSummary, type Content, type ContentDataMap, type ContentStatus, type ContentSummary, type ContentType, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateAttributeDto as CreateAttributeInput, type CreateAttributeOptionDto as CreateAttributeOptionInput, type CreateBrandDto as CreateBrandInput, type CreateCategoryDto as CreateCategoryInput, type CreateCheckoutDto, type CreateContentInput, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateEmailTemplateDto as CreateEmailTemplateInput, type CreateGuestOrderDto, type CreateInquiryInput, type CreateInquiryResponse, type CreateMetafieldDefinitionDto as CreateMetafieldDefinitionInput, type CreateModifierGroupInput, type CreateModifierInput, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateShippingRateDto as CreateShippingRateInput, type CreateShippingZoneDto as CreateShippingZoneInput, type CreateTagDto as CreateTagInput, type CreateTaxRateDto as CreateTaxRateInput, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DateAvailabilityConstraints, type DateFieldParseResult, type DeleteProductResponse, type DiscountBanner, type DiscountRuleType, type DownloadFile, type DraftLineItem, type EditInventoryDto, type EmailDomain, type EmailEventSettings, type EmailEventType, type EmailSettings, type EmailTemplate, type EmailTemplatePreview, type EmailTemplatesResponse, type EmailVerificationResponse, type ExtendReservationResponse, type FaqContent, type FaqItem, type FooterColumn, type FooterContent, type FooterLink, type FooterSocialLink, type FormatPriceOptions, type FormatProductPriceOptions, type FreeAllocationPolicy, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type HeaderContent, type HeaderCta, type HeaderLogo, type HeaderNavItem, type InsufficientStockError, type InventoryInfo, type InventoryReservationStrategy, type InventorySyncStatus, type InventoryTrackingMode, type InvitationStatus, type InviteMemberDto as InviteMemberInput, type InviteStoreMemberDto as InviteStoreMemberInput, type JsonLdOptions, type ListModifierGroupsParams, type LocalCart, type LocalCartItem, type LockedVariant, type LoyaltyNextTierSummary, type LoyaltyReward, type LoyaltyStatus, type LoyaltyTierSummary, type MergeCartsDto, type MetafieldConflict, type MetafieldConflictResolution, type MetafieldDefinition, type MetafieldFilter, type MetafieldFilterValue, type MetafieldFiltersResponse, type MetafieldType, type Modifier, type ModifierGroup, type ModifierSelection, type ModifierSelectionType, type ModifierValidationCode, type ModifierValidationError, type MyProductReview, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProviderConfig, type OAuthProviderType, type OAuthProvidersResponse, type Order, type OrderAddress, type OrderBump, type OrderCustomer, type OrderDownloadLink, type OrderItem, type OrderQueryParams, type OrderStatus, type OrderStatusChange, type PageContent, type PageSeo, type PaginatedResponse, type ParsedDateFieldValue, type PaymentClientSdk, type PaymentConfig, type PaymentIntent, type PaymentProvider, type PaymentProviderConfig, type PaymentProvidersConfig, type PaymentStatus, type PaymentUrlOptions, type PickupLocation, type PlatformCouponCapabilities, type PlatformMetafieldMetadata, type PreviewEmailTemplateDto as PreviewEmailTemplateInput, type Product, type ProductAttributeInput, type ProductAvailability, type ProductCustomizationField, type ProductDiscount, type ProductDiscountBadge, type ProductImage, type ProductMetafield, type ProductMetafieldValue, type ProductModifierGroupAttachment, type ProductQueryParams, type ProductRecommendation, type ProductRecommendationsResponse, type ProductRelationType, type ProductReview, type ProductReviewAdmin, type ProductSitemapOptions, type ProductSuggestion, type ProductVariant, type PublicMetafieldDefinition, type PublishProductResponse, RTL_LOCALES, type RecommendationVariant, type ReconcileInventoryResponse, type RedeemRewardResult, type ReferralInfo, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type ReservationInfo, type ResolveMetafieldConflictDto as ResolveMetafieldConflictInput, type ResolveSyncConflictDto as ResolveSyncConflictInput, type RichTextContent, SDK_VERSION, type SearchSuggestions, type SelectPickupLocationDto, type SelectShippingMethodDto, type SendInvoiceDto, type SessionCartRef, type SetBillingAddressDto, type SetCheckoutCustomFieldsDto, type SetCheckoutCustomerDto, type SetDefinitionProductsDto as SetDefinitionProductsInput, type SetMetafieldPlatformsDto as SetMetafieldPlatformsInput, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingDestinations, type ShippingLine, type ShippingRate, type ShippingRateConfig, type ShippingRateType, type ShippingSummaryEntry, type ShippingZone, type ShippingZoneQueryParams, type SitemapEntry, type StockAvailabilityRequest, type StockAvailabilityResponse, type StockAvailabilityResult, type StoreInfo, type StoreInvitation, type StoreInvitationDetails, type StoreMember, type StorePermission, type StoreRole, type StoreTeamResponse, type StoreTracking, type SubmitProductReviewInput, type SupportedLocaleObject, type SyncConflict, type SyncConflictResolution, type SyncJob, type Tag, type TaxBreakdown, type TaxBreakdownItem, type TaxRate, type TaxonomyQueryParams, type TeamInvitation, type TeamInvitationsResponse, type TeamMember, type TeamMembersResponse, type TeamRole, type TrackingEventItem, type TrackingEventName, type TrackingEventPayload, type UpdateAddressDto, type UpdateAttachmentInput, type UpdateAttributeDto as UpdateAttributeInput, type UpdateAttributeOptionDto as UpdateAttributeOptionInput, type UpdateBrandDto as UpdateBrandInput, type UpdateCartItemDto, type UpdateCategoryDto as UpdateCategoryInput, type UpdateContentInput, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateEmailSettingsDto as UpdateEmailSettingsInput, type UpdateEmailTemplateDto as UpdateEmailTemplateInput, type UpdateInventoryDto, type UpdateMemberRoleDto as UpdateMemberRoleInput, type UpdateMetafieldDefinitionDto as UpdateMetafieldDefinitionInput, type UpdateModifierGroupInput, type UpdateModifierInput, type UpdateOAuthProviderDto as UpdateOAuthProviderInput, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateShippingRateDto as UpdateShippingRateInput, type UpdateShippingZoneDto as UpdateShippingZoneInput, type UpdateStoreMemberDto as UpdateStoreMemberInput, type UpdateTagDto as UpdateTagInput, type UpdateTaxRateDto as UpdateTaxRateInput, type UpdateVariantDto, type UpdateVariantInventoryDto, type UpsertProductMetafieldDto as UpsertProductMetafieldInput, type UserStore, type UserStorePermissions, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WaitForOrderOptions, type WaitForOrderResult, type WebhookEvent, type WebhookEventType, type WriteProductReviewInput, buildArticleJsonLd, buildBreadcrumbJsonLd, buildCollectionPageJsonLd, buildOrganizationJsonLd, buildProductFaqJsonLd, buildProductJsonLd, buildWebsiteJsonLd, computeAvailableSlots, createWebhookHandler, deriveSeoDescription, enableDevGuards, formatMoney, formatPrice, formatProductPrice, formatVariantPrice, getBlogSitemapEntries, getBusinessHoursForDate, getCartItemImage, getCartItemName, getCartTotals, getCategorySitemapEntries, getDescriptionContent, getDirectionForLocale, formatPrice as getPriceDisplay, getProductCustomizationFields, getProductMetafield, getProductMetafieldValue, getProductMetafieldsByType, getProductPrice, getProductPriceInfo, getProductSitemapEntries, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCalendarDateAllowed, isCouponApplicableToProduct, isDateValueAllowed, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseDateFieldValue, parseWebhookEvent, resolveStoreLocalParts, safePaymentRedirect, stripHtml, validateDateAvailabilityConfig, verifyWebhook };
12156
+ export { type AddToCartDto, type AddressDetailsResult, type AddressSuggestion, type AnnouncementContent, type AnnouncementSeverity, type AppliedDiscount, type ApplyCouponDto, type AttachModifierGroupInput, type Attribute, type AttributeOption, type AttributeSource, type BlogPost, type BlogPostListParams, type BlogPostListResponse, type BlogSitemapOptions, type BrainerceApiError, BrainerceClient, type BrainerceClientOptions, BrainerceError, type Brand, type BulkCreateProductsDto, type BulkCreateProductsError, type BulkCreateProductsJob, type BulkCreateProductsStatus, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type BusinessHoursWindow, type Cart, type CartAppliedDiscount, type CartBundleOffer, type CartBundlesResponse, type CartIncludeOption, type CartIncludeOptions, type CartItem, type CartItemModifierLine, type CartNudge, type CartRecommendationsResponse, type CartStatus, type CartUpgradeSuggestion, type CartUpgradesResponse, type CartWithIncludes, type Category, type CategoryDetail, type CategoryNode, type CategorySitemapOptions, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutBumpsResponse, type CheckoutCustomFieldDefinition, type CheckoutFieldPricing, type CheckoutFieldVisibility, type CheckoutLineItem, type CheckoutPrefillData, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConfigureOAuthProviderDto as ConfigureOAuthProviderInput, type ConflictStatus, type ConnectorPlatform, type ContactFormFieldType, type ContactFormFieldValidation, type ContactFormPublic, type ContactFormPublicField, type ContactFormSummary, type Content, type ContentDataMap, type ContentStatus, type ContentSummary, type ContentType, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateAttributeDto as CreateAttributeInput, type CreateAttributeOptionDto as CreateAttributeOptionInput, type CreateBrandDto as CreateBrandInput, type CreateCategoryDto as CreateCategoryInput, type CreateCheckoutDto, type CreateContentInput, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateEmailTemplateDto as CreateEmailTemplateInput, type CreateGuestOrderDto, type CreateInquiryInput, type CreateInquiryResponse, type CreateMetafieldDefinitionDto as CreateMetafieldDefinitionInput, type CreateModifierGroupInput, type CreateModifierInput, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateShippingRateDto as CreateShippingRateInput, type CreateShippingZoneDto as CreateShippingZoneInput, type CreateTagDto as CreateTagInput, type CreateTaxRateDto as CreateTaxRateInput, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DateAvailabilityConstraints, type DateFieldParseResult, type DeleteProductResponse, type DiscountBanner, type DiscountRuleType, type DownloadFile, type DraftLineItem, type EditInventoryDto, type EmailDomain, type EmailEventSettings, type EmailEventType, type EmailSettings, type EmailTemplate, type EmailTemplatePreview, type EmailTemplatesResponse, type EmailVerificationResponse, type ExtendReservationResponse, type FaqContent, type FaqItem, type FooterColumn, type FooterContent, type FooterLink, type FooterSocialLink, type FormatPriceOptions, type FormatProductPriceOptions, type FreeAllocationPolicy, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type HeaderContent, type HeaderCta, type HeaderLogo, type HeaderNavItem, type InsufficientStockError, type InventoryInfo, type InventoryReservationStrategy, type InventorySyncStatus, type InventoryTrackingMode, type InvitationStatus, type InviteMemberDto as InviteMemberInput, type InviteStoreMemberDto as InviteStoreMemberInput, type JsonLdOptions, type ListModifierGroupsParams, type LocalCart, type LocalCartItem, type LockedVariant, type LoyaltyNextTierSummary, type LoyaltyReward, type LoyaltyStatus, type LoyaltyTierSummary, type MergeCartsDto, type MetafieldConflict, type MetafieldConflictResolution, type MetafieldDefinition, type MetafieldFilter, type MetafieldFilterValue, type MetafieldFiltersResponse, type MetafieldType, type Modifier, type ModifierGroup, type ModifierSelection, type ModifierSelectionType, type ModifierValidationCode, type ModifierValidationError, type MyProductReview, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProviderConfig, type OAuthProviderType, type OAuthProvidersResponse, type Order, type OrderAddress, type OrderBump, type OrderCustomer, type OrderDownloadLink, type OrderItem, type OrderQueryParams, type OrderStatus, type OrderStatusChange, type PageContent, type PageSeo, type PaginatedResponse, type ParsedDateFieldValue, type PaymentClientSdk, type PaymentConfig, type PaymentIntent, type PaymentProvider, type PaymentProviderConfig, type PaymentProvidersConfig, type PaymentStatus, type PaymentUrlOptions, type PickupLocation, type PlatformCouponCapabilities, type PlatformMetafieldMetadata, type PreviewEmailTemplateDto as PreviewEmailTemplateInput, type Product, type ProductAttributeInput, type ProductAvailability, type ProductCustomizationField, type ProductDiscount, type ProductDiscountBadge, type ProductImage, type ProductMetafield, type ProductMetafieldValue, type ProductModifierGroupAttachment, type ProductQueryParams, type ProductRecommendation, type ProductRecommendationsResponse, type ProductRelationType, type ProductReview, type ProductReviewAdmin, type ProductSitemapOptions, type ProductSuggestion, type ProductVariant, type PublicMetafieldDefinition, type PublishProductResponse, RTL_LOCALES, type RecommendationVariant, type ReconcileInventoryResponse, type RedeemRewardResult, type ReferralInfo, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type ReservationInfo, type ResolveMetafieldConflictDto as ResolveMetafieldConflictInput, type ResolveSyncConflictDto as ResolveSyncConflictInput, type RichTextContent, SDK_VERSION, type SearchSuggestions, type SelectPickupLocationDto, type SelectShippingMethodDto, type SendInvoiceDto, type SessionCartRef, type SetBillingAddressDto, type SetCheckoutCustomFieldsDto, type SetCheckoutCustomerDto, type SetDefinitionProductsDto as SetDefinitionProductsInput, type SetMetafieldPlatformsDto as SetMetafieldPlatformsInput, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingDestinations, type ShippingLine, type ShippingRate, type ShippingRateConfig, type ShippingRateType, type ShippingSummaryEntry, type ShippingZone, type ShippingZoneQueryParams, type SitemapEntry, type StockAvailabilityRequest, type StockAvailabilityResponse, type StockAvailabilityResult, type StoreInfo, type StoreInvitation, type StoreInvitationDetails, type StoreMember, type StorePermission, type StoreRole, type StoreTeamResponse, type StoreTracking, type SubmitProductReviewInput, type SupportedLocaleObject, type SyncConflict, type SyncConflictResolution, type SyncJob, type Tag, type TaxBreakdown, type TaxBreakdownItem, type TaxRate, type TaxonomyQueryParams, type TeamInvitation, type TeamInvitationsResponse, type TeamMember, type TeamMembersResponse, type TeamRole, type TrackingEventItem, type TrackingEventName, type TrackingEventPayload, type UpdateAddressDto, type UpdateAttachmentInput, type UpdateAttributeDto as UpdateAttributeInput, type UpdateAttributeOptionDto as UpdateAttributeOptionInput, type UpdateBrandDto as UpdateBrandInput, type UpdateCartItemDto, type UpdateCategoryDto as UpdateCategoryInput, type UpdateContentInput, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateEmailSettingsDto as UpdateEmailSettingsInput, type UpdateEmailTemplateDto as UpdateEmailTemplateInput, type UpdateInventoryDto, type UpdateMemberRoleDto as UpdateMemberRoleInput, type UpdateMetafieldDefinitionDto as UpdateMetafieldDefinitionInput, type UpdateModifierGroupInput, type UpdateModifierInput, type UpdateOAuthProviderDto as UpdateOAuthProviderInput, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateShippingRateDto as UpdateShippingRateInput, type UpdateShippingZoneDto as UpdateShippingZoneInput, type UpdateStoreMemberDto as UpdateStoreMemberInput, type UpdateTagDto as UpdateTagInput, type UpdateTaxRateDto as UpdateTaxRateInput, type UpdateVariantDto, type UpdateVariantInventoryDto, type UpsertProductMetafieldDto as UpsertProductMetafieldInput, type UserStore, type UserStorePermissions, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WaitForOrderOptions, type WaitForOrderResult, type WebhookEvent, type WebhookEventType, type WriteProductReviewInput, buildArticleJsonLd, buildBreadcrumbJsonLd, buildCollectionPageJsonLd, buildOrganizationJsonLd, buildProductFaqJsonLd, buildProductJsonLd, buildWebsiteJsonLd, computeAvailableSlots, createWebhookHandler, deriveSeoDescription, enableDevGuards, formatMoney, formatPrice, formatProductPrice, formatVariantPrice, getBlogSitemapEntries, getBusinessHoursForDate, getCartItemImage, getCartItemName, getCartTotals, getCategorySitemapEntries, getDescriptionContent, getDirectionForLocale, formatPrice as getPriceDisplay, getProductCustomizationFields, getProductMetafield, getProductMetafieldValue, getProductMetafieldsByType, getProductPrice, getProductPriceInfo, getProductSitemapEntries, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCalendarDateAllowed, isCouponApplicableToProduct, isDateValueAllowed, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseDateFieldValue, parseWebhookEvent, resolveStoreLocalParts, safePaymentRedirect, stripHtml, validateDateAvailabilityConfig, verifyWebhook };
package/dist/index.js CHANGED
@@ -1999,6 +1999,98 @@ var _BrainerceClient = class _BrainerceClient {
1999
1999
  async createProduct(data) {
2000
2000
  return this.request("POST", "/api/v1/products", data);
2001
2001
  }
2002
+ /**
2003
+ * Create many products in one call.
2004
+ *
2005
+ * QUEUED, not immediate: this returns a job id straight away and the products
2006
+ * appear over the following seconds or minutes. It does NOT return the
2007
+ * created products — poll {@link getBulkCreateProductsStatus} with the
2008
+ * returned `jobId`.
2009
+ *
2010
+ * Every field {@link createProduct} accepts is accepted per row, including
2011
+ * variants, categories, brands, tags, images, translations and tax behaviour.
2012
+ *
2013
+ * At most 1000 products per call (500 is the comfortable size). For a
2014
+ * 3,000-50,000 product catalog, send several calls carrying the same
2015
+ * `importId` and poll {@link getBulkCreateProductsImportStatus} once for the
2016
+ * whole import.
2017
+ *
2018
+ * Retry-safe: a row whose `sku` or `externalId` already exists is skipped
2019
+ * rather than duplicated, so re-sending a batch after a timeout cannot create
2020
+ * the catalog twice. Pass `idempotencyKey` to have an identical re-send
2021
+ * return the original job instead of starting a second import.
2022
+ *
2023
+ * @example
2024
+ * ```typescript
2025
+ * const job = await client.bulkCreateProducts({
2026
+ * products: rows.map((r) => ({
2027
+ * name: r.title,
2028
+ * sku: r.sku,
2029
+ * externalId: r.supplier_id,
2030
+ * basePrice: Number(r.price),
2031
+ * type: 'SIMPLE',
2032
+ * categoryNames: [r.category],
2033
+ * })),
2034
+ * importId: 'supplier-catalog-2026-08-21',
2035
+ * });
2036
+ *
2037
+ * let status = await client.getBulkCreateProductsStatus(job.jobId);
2038
+ * while (status.status === 'QUEUED' || status.status === 'RUNNING') {
2039
+ * await new Promise((r) => setTimeout(r, 2000));
2040
+ * status = await client.getBulkCreateProductsStatus(job.jobId);
2041
+ * }
2042
+ * // `succeeded` is what was created; `skipped` already existed.
2043
+ * console.log(status.succeeded, status.skipped, status.failed);
2044
+ * ```
2045
+ */
2046
+ async bulkCreateProducts(data) {
2047
+ return this.request("POST", "/api/v1/products/bulk", data);
2048
+ }
2049
+ /**
2050
+ * Progress of one queued product import.
2051
+ *
2052
+ * Read the counters literally: `skipped` rows already existed and were NOT
2053
+ * created, so `succeeded` alone is what this import added.
2054
+ *
2055
+ * `COMPLETED_WITH_ERRORS` means the import finished with some rows failing —
2056
+ * that is not something to re-run; read the failures with
2057
+ * {@link getBulkCreateProductsErrors}.
2058
+ */
2059
+ async getBulkCreateProductsStatus(jobId) {
2060
+ return this.request(
2061
+ "GET",
2062
+ `/api/v1/products/bulk/${encodePathSegment(jobId)}`
2063
+ );
2064
+ }
2065
+ /**
2066
+ * Aggregate progress across every batch that shared an `importId`.
2067
+ *
2068
+ * The status is the least-complete state across the chunks, and `finishedAt`
2069
+ * stays null until all of them have finished — so a caller cannot mistake
2070
+ * "the first 500 landed" for "the catalog is imported".
2071
+ */
2072
+ async getBulkCreateProductsImportStatus(importId) {
2073
+ return this.request(
2074
+ "GET",
2075
+ `/api/v1/products/bulk/import/${encodePathSegment(importId)}`
2076
+ );
2077
+ }
2078
+ /**
2079
+ * Per-row failures for a product import, paginated.
2080
+ *
2081
+ * Every failure is recorded — nothing is truncated — so walk the pages when
2082
+ * `meta.totalPages > 1`. Each entry carries the 1-indexed `row` from the
2083
+ * array you submitted, so a failure maps back to the line of the source
2084
+ * spreadsheet.
2085
+ */
2086
+ async getBulkCreateProductsErrors(jobId, options) {
2087
+ return this.request(
2088
+ "GET",
2089
+ `/api/v1/products/bulk/${encodePathSegment(jobId)}/errors`,
2090
+ void 0,
2091
+ { page: options?.page, limit: options?.limit }
2092
+ );
2093
+ }
2002
2094
  /**
2003
2095
  * Update an existing product
2004
2096
  */
@@ -3265,11 +3357,18 @@ var _BrainerceClient = class _BrainerceClient {
3265
3357
  * @param options.redirectUrl - Where to send the browser once OAuth finishes —
3266
3358
  * on success *and* on failure. Validated server-side against the sales
3267
3359
  * channel's trusted origins, so what is accepted depends on the mode:
3268
- * - vibe-coded (`salesChannelId: 'vc_*'`): an absolute URL on the channel's
3269
- * registered `domain` or one of its `allowedOrigins`; in TEST mode, any
3270
- * `localhost`/`127.0.0.1` port. A relative path (`/auth/callback`) also
3271
- * works it is resolved against the channel's `domain` on the way back,
3272
- * so the channel must have one registered.
3360
+ * - vibe-coded (`salesChannelId: 'vc_*'`), **LIVE**: an `https` URL on the
3361
+ * channel's registered `domain`, or on a subdomain of it. Nothing else
3362
+ * `allowedOrigins` grants no OAuth redirect on a LIVE channel, and an
3363
+ * `http://` target is refused even on the registered domain. You
3364
+ * therefore cannot complete social login from `localhost` against a LIVE
3365
+ * channel; use a TEST channel for that.
3366
+ * - vibe-coded, **TEST**: the above, plus an **exact** match (scheme, host
3367
+ * and port) against one of the channel's `allowedOrigins`, plus any
3368
+ * `localhost`/`127.0.0.1`/`[::1]` port.
3369
+ * - Either mode: a relative path (`/auth/callback`) also works — it is
3370
+ * resolved against the channel's `domain` on the way back, so the channel
3371
+ * must have one registered.
3273
3372
  * - storefront (`storeId`): **social login cannot round-trip in this mode.**
3274
3373
  * No channel is bound to the request, so an absolute URL has no
3275
3374
  * trusted-origin list to match (400 at this call) and a relative path has
package/dist/index.mjs CHANGED
@@ -1911,6 +1911,98 @@ var _BrainerceClient = class _BrainerceClient {
1911
1911
  async createProduct(data) {
1912
1912
  return this.request("POST", "/api/v1/products", data);
1913
1913
  }
1914
+ /**
1915
+ * Create many products in one call.
1916
+ *
1917
+ * QUEUED, not immediate: this returns a job id straight away and the products
1918
+ * appear over the following seconds or minutes. It does NOT return the
1919
+ * created products — poll {@link getBulkCreateProductsStatus} with the
1920
+ * returned `jobId`.
1921
+ *
1922
+ * Every field {@link createProduct} accepts is accepted per row, including
1923
+ * variants, categories, brands, tags, images, translations and tax behaviour.
1924
+ *
1925
+ * At most 1000 products per call (500 is the comfortable size). For a
1926
+ * 3,000-50,000 product catalog, send several calls carrying the same
1927
+ * `importId` and poll {@link getBulkCreateProductsImportStatus} once for the
1928
+ * whole import.
1929
+ *
1930
+ * Retry-safe: a row whose `sku` or `externalId` already exists is skipped
1931
+ * rather than duplicated, so re-sending a batch after a timeout cannot create
1932
+ * the catalog twice. Pass `idempotencyKey` to have an identical re-send
1933
+ * return the original job instead of starting a second import.
1934
+ *
1935
+ * @example
1936
+ * ```typescript
1937
+ * const job = await client.bulkCreateProducts({
1938
+ * products: rows.map((r) => ({
1939
+ * name: r.title,
1940
+ * sku: r.sku,
1941
+ * externalId: r.supplier_id,
1942
+ * basePrice: Number(r.price),
1943
+ * type: 'SIMPLE',
1944
+ * categoryNames: [r.category],
1945
+ * })),
1946
+ * importId: 'supplier-catalog-2026-08-21',
1947
+ * });
1948
+ *
1949
+ * let status = await client.getBulkCreateProductsStatus(job.jobId);
1950
+ * while (status.status === 'QUEUED' || status.status === 'RUNNING') {
1951
+ * await new Promise((r) => setTimeout(r, 2000));
1952
+ * status = await client.getBulkCreateProductsStatus(job.jobId);
1953
+ * }
1954
+ * // `succeeded` is what was created; `skipped` already existed.
1955
+ * console.log(status.succeeded, status.skipped, status.failed);
1956
+ * ```
1957
+ */
1958
+ async bulkCreateProducts(data) {
1959
+ return this.request("POST", "/api/v1/products/bulk", data);
1960
+ }
1961
+ /**
1962
+ * Progress of one queued product import.
1963
+ *
1964
+ * Read the counters literally: `skipped` rows already existed and were NOT
1965
+ * created, so `succeeded` alone is what this import added.
1966
+ *
1967
+ * `COMPLETED_WITH_ERRORS` means the import finished with some rows failing —
1968
+ * that is not something to re-run; read the failures with
1969
+ * {@link getBulkCreateProductsErrors}.
1970
+ */
1971
+ async getBulkCreateProductsStatus(jobId) {
1972
+ return this.request(
1973
+ "GET",
1974
+ `/api/v1/products/bulk/${encodePathSegment(jobId)}`
1975
+ );
1976
+ }
1977
+ /**
1978
+ * Aggregate progress across every batch that shared an `importId`.
1979
+ *
1980
+ * The status is the least-complete state across the chunks, and `finishedAt`
1981
+ * stays null until all of them have finished — so a caller cannot mistake
1982
+ * "the first 500 landed" for "the catalog is imported".
1983
+ */
1984
+ async getBulkCreateProductsImportStatus(importId) {
1985
+ return this.request(
1986
+ "GET",
1987
+ `/api/v1/products/bulk/import/${encodePathSegment(importId)}`
1988
+ );
1989
+ }
1990
+ /**
1991
+ * Per-row failures for a product import, paginated.
1992
+ *
1993
+ * Every failure is recorded — nothing is truncated — so walk the pages when
1994
+ * `meta.totalPages > 1`. Each entry carries the 1-indexed `row` from the
1995
+ * array you submitted, so a failure maps back to the line of the source
1996
+ * spreadsheet.
1997
+ */
1998
+ async getBulkCreateProductsErrors(jobId, options) {
1999
+ return this.request(
2000
+ "GET",
2001
+ `/api/v1/products/bulk/${encodePathSegment(jobId)}/errors`,
2002
+ void 0,
2003
+ { page: options?.page, limit: options?.limit }
2004
+ );
2005
+ }
1914
2006
  /**
1915
2007
  * Update an existing product
1916
2008
  */
@@ -3177,11 +3269,18 @@ var _BrainerceClient = class _BrainerceClient {
3177
3269
  * @param options.redirectUrl - Where to send the browser once OAuth finishes —
3178
3270
  * on success *and* on failure. Validated server-side against the sales
3179
3271
  * channel's trusted origins, so what is accepted depends on the mode:
3180
- * - vibe-coded (`salesChannelId: 'vc_*'`): an absolute URL on the channel's
3181
- * registered `domain` or one of its `allowedOrigins`; in TEST mode, any
3182
- * `localhost`/`127.0.0.1` port. A relative path (`/auth/callback`) also
3183
- * works it is resolved against the channel's `domain` on the way back,
3184
- * so the channel must have one registered.
3272
+ * - vibe-coded (`salesChannelId: 'vc_*'`), **LIVE**: an `https` URL on the
3273
+ * channel's registered `domain`, or on a subdomain of it. Nothing else
3274
+ * `allowedOrigins` grants no OAuth redirect on a LIVE channel, and an
3275
+ * `http://` target is refused even on the registered domain. You
3276
+ * therefore cannot complete social login from `localhost` against a LIVE
3277
+ * channel; use a TEST channel for that.
3278
+ * - vibe-coded, **TEST**: the above, plus an **exact** match (scheme, host
3279
+ * and port) against one of the channel's `allowedOrigins`, plus any
3280
+ * `localhost`/`127.0.0.1`/`[::1]` port.
3281
+ * - Either mode: a relative path (`/auth/callback`) also works — it is
3282
+ * resolved against the channel's `domain` on the way back, so the channel
3283
+ * must have one registered.
3185
3284
  * - storefront (`storeId`): **social login cannot round-trip in this mode.**
3186
3285
  * No channel is bound to the request, so an absolute URL has no
3187
3286
  * trusted-origin list to match (400 at this call) and a relative path has
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainerce",
3
- "version": "1.58.0",
3
+ "version": "1.58.1",
4
4
  "description": "Official SDK for building e-commerce storefronts with Brainerce Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",