brainerce 1.55.0 → 1.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -292,6 +292,9 @@ The SDK exports these utility functions for common UI tasks:
292
292
  | `buildBreadcrumbJsonLd(items)` | schema.org BreadcrumbList | See SEO section |
293
293
  | `jsonLdScriptProps(data)` | XSS-safe `<script type="application/ld+json">` props | `<script {...jsonLdScriptProps(data)} />` |
294
294
  | `getBlogSitemapEntries(client, opts)` | Paginate published posts into sitemap entries | See SEO section |
295
+ | `getProductSitemapEntries(client, opts)` | ALL published products into sitemap entries (no 100-item clamp) | See SEO section |
296
+ | `getCategorySitemapEntries(client, opts)` | Category tree into sitemap entries | See SEO section |
297
+ | `client.resolveSlugRedirect(type, slug)` | Renamed slug → current slug (301 support in not-found paths) | See SEO section |
295
298
 
296
299
  ```typescript
297
300
  import {
@@ -481,9 +484,9 @@ return <div dangerouslySetInnerHTML={{ __html: safeHtml }} className="prose" />;
481
484
 
482
485
  **SEO Autopilot writes here too**: the platform's SEO Autopilot publishes AI-written articles into this same blog automatically — render whatever `getPosts()` returns, and see the SEO section below for the required discoverability pieces.
483
486
 
484
- ### SEO — JSON-LD builders, sitemap helper, IndexNow key, llms.txt
487
+ ### SEO — JSON-LD builders, sitemap helpers, IndexNow key, llms.txt + agents.md
485
488
 
486
- The SDK ships schema.org builders that encode Google's structured-data rules (aggregateRating gated on `reviewCount > 0`, AggregateOffer for VARIABLE products, XSS-safe serialization). `buildProductJsonLd`'s Offer also always includes `itemCondition` (hardcoded `NewCondition` — first-party new-goods catalog), `priceValidUntil` when the product has an active sale-price window (`salePriceEndsAt`), and `shippingDetails` when you pass `shipping` (real flat-rate/free zones from `storeInfo.shipping` — omitted entirely, never fabricated, if you don't pass it). Prefer these builders over hand-rolled JSON-LD:
489
+ The SDK ships schema.org builders that encode Google's structured-data rules (aggregateRating gated on `reviewCount > 0` with explicit `bestRating`/`worstRating`, AggregateOffer with `offerCount` for VARIABLE products, XSS-safe serialization, and the full availability mapping — `InStock` from the backend's pre-computed `inventory.inStock`, `BackOrder` for purchasable-while-out-of-stock products, `OutOfStock` otherwise). `buildProductJsonLd`'s Offer also always includes `itemCondition` (hardcoded `NewCondition` — first-party new-goods catalog), `priceValidUntil` when the product has an active sale-price window (`salePriceEndsAt`), and `shippingDetails` when you pass `shipping` (real flat-rate/free zones from `storeInfo.shipping` — omitted entirely, never fabricated, if you don't pass it). Prefer these builders over hand-rolled JSON-LD:
487
490
 
488
491
  ```tsx
489
492
  import {
@@ -511,23 +514,43 @@ import {
511
514
  }))} />
512
515
  ```
513
516
 
514
- **Blog entries in sitemap.xml** (required autopilot articles missing from the sitemap never get crawled):
517
+ **Product + category + blog entries in sitemap.xml** (required). ⚠️ Products **must** use `getProductSitemapEntries` the public listing API clamps `limit` to 100, so a naive `getProducts({ limit: 1000 })` sitemap silently truncates at 100 products. The helper uses a dedicated lightweight endpoint (slug + updatedAt + localeSlugs, up to 5000 in one call) and falls back to pagination on older backends:
515
518
 
516
519
  ```ts
517
520
  // app/sitemap.ts
518
- import { getBlogSitemapEntries } from 'brainerce';
521
+ import {
522
+ getProductSitemapEntries,
523
+ getCategorySitemapEntries,
524
+ getBlogSitemapEntries,
525
+ } from 'brainerce';
519
526
 
520
- const blogPages = await getBlogSitemapEntries(client, {
527
+ const productPages = await getProductSitemapEntries(client, {
521
528
  siteUrl: baseUrl,
522
529
  locales: supportedLocales, // optional (multi-locale stores)
523
530
  defaultLocale,
524
531
  }).catch(() => []);
525
- return [...staticPages, ...productPages, ...blogPages];
532
+ const categoryPages = await getCategorySitemapEntries(client, {
533
+ siteUrl: baseUrl,
534
+ locales: supportedLocales,
535
+ defaultLocale,
536
+ }).catch(() => []);
537
+ const blogPages = await getBlogSitemapEntries(client, {
538
+ siteUrl: baseUrl,
539
+ locales: supportedLocales,
540
+ defaultLocale,
541
+ }).catch(() => []);
542
+ return [...staticPages, ...productPages, ...categoryPages, ...blogPages];
526
543
  ```
527
544
 
545
+ **robots.txt** (required): allow the AI search crawlers by name (`OAI-SearchBot`, `ChatGPT-User`, `Claude-SearchBot`, `Claude-User`, `PerplexityBot`, `Perplexity-User`, `Bingbot`, `Applebot`, `Amazonbot`) — they power ChatGPT/Claude/Perplexity/Copilot shopping answers and respect robots.txt. Keep `/api/`, `/auth/`, `/checkout/`, `/account/` disallowed.
546
+
528
547
  **IndexNow key file** (required): the platform pings IndexNow when posts publish; search engines verify by fetching `GET /indexnow-key.txt`. Serve `getStoreInfo().seo.indexNowKey` as `text/plain`, 404 while `null`. The key is **not a secret** (public by protocol design).
529
548
 
530
- **llms.txt** (recommended): a plain-text site summary (store name, key pages, recent article links) for AI answer engines at `GET /llms.txt`.
549
+ **llms.txt + agents.md** (required): `/llms.txt` is a plain-text site summary (store name, categories, key pages, recent article links) for AI answer engines; `/agents.md` is the agent-facing guide (machine surfaces, key URLs, currency, how buying works). Multi-locale stores: keep these dotted routes (plus `indexnow-key.txt`) at the app ROOT — locale middleware matchers skip dotted paths, so a locale-nested copy serves the homepage HTML instead.
550
+
551
+ **Site verification** : when `getStoreInfo().seo.googleSiteVerification` is set, render `<meta name="google-site-verification" content={token} />` in the root layout head (Search Console verification + Merchant Center website claim).
552
+
553
+ **Renamed slugs 301 instead of 404** (required): the platform records every product/blog slug rename. In the not-found path of the product and blog pages call `client.resolveSlugRedirect('product' | 'blog', slug)` — on a hit, `permanentRedirect()` to the returned `currentSlug`; `null` means a genuine 404 (never throws, safe to call unconditionally). Rename chains collapse to one hop.
531
554
 
532
555
  ---
533
556
 
@@ -4718,6 +4741,46 @@ target vibe-coded connection both belong to the same account. Cross-account
4718
4741
  calls fail with `404 Not Found` (the connection ID is treated as if it doesn't
4719
4742
  exist for that account).
4720
4743
 
4744
+ #### Customers and sales channels
4745
+
4746
+ Customers use the same publish/unpublish shape, with one important difference:
4747
+ **you almost never have to call it.** A customer is attached to a channel
4748
+ automatically the moment they are seen on it — when they register, sign in
4749
+ (including via OAuth), or complete a checkout there.
4750
+
4751
+ There is one customer record per store, shared by every channel
4752
+ (`@@unique(storeId, email)`), so the same person shopping two of your
4753
+ storefronts stays one customer with two channel rows — never a duplicate.
4754
+
4755
+ ```typescript
4756
+ // Attach / detach by hand — for migrations and corrections only
4757
+ await client.publishCustomerToSalesChannel('cust_id', 'vc_conn_id');
4758
+ await client.unpublishCustomerFromSalesChannel('cust_id', 'vc_conn_id');
4759
+
4760
+ // Read both facts off any customer get/by-email response
4761
+ const customer = await client.getCustomer('cust_id');
4762
+ customer.channelPublishes;
4763
+ // [{ salesChannel: { id, name, connectionId }, firstSeenAt, lastSeenAt }, ...]
4764
+ customer.acquisitionSalesChannel; // first-touch channel, or null if unknown
4765
+
4766
+ // Set / correct the first-touch channel ('' clears it back to unknown)
4767
+ await client.updateCustomer('cust_id', { acquisitionSalesChannelId: 'vc_conn_id' });
4768
+ ```
4769
+
4770
+ Two things to keep straight:
4771
+
4772
+ - **`channelPublishes`** = every channel they are active in. Grows over time.
4773
+ - **`acquisitionSalesChannel`** = the FIRST channel they ever arrived through.
4774
+ Written once and then never touched by the platform again, so it stays a
4775
+ reliable answer to "which storefront is bringing me customers". `null` is a
4776
+ normal value: customers created through the API, imported from a file, or
4777
+ arriving via a `storeId`-mode storefront have no observed origin.
4778
+
4779
+ `unpublishCustomerFromSalesChannel` is a **correction, not a block.** It does
4780
+ not prevent that person from buying on that storefront, and the row comes back
4781
+ the next time they sign in or order there. There is no API to bar a customer
4782
+ from a sales channel.
4783
+
4721
4784
  ### Store Team Management
4722
4785
 
4723
4786
  Each store has its own team with roles (`OWNER`, `MANAGER`, `STAFF`, `VIEWER`) and granular permissions.
package/dist/index.d.mts CHANGED
@@ -229,14 +229,24 @@ interface StoreInfo {
229
229
  /** Multi-language / i18n settings */
230
230
  i18n?: I18nSettings;
231
231
  /**
232
- * SEO Autopilot fields (sales-channel mode only).
232
+ * SEO fields (sales-channel mode only).
233
+ *
233
234
  * `indexNowKey`: serve this verbatim at `GET /indexnow-key.txt`
234
235
  * (`text/plain`) so the platform can ping IndexNow when blog posts publish.
235
236
  * Not a secret — the key file is public by protocol design. `null` until
236
237
  * the store's SEO Autopilot generates one; return 404 while null.
238
+ *
239
+ * `googleSiteVerification`: the merchant's Google site-verification token
240
+ * (the `content` value of the `google-site-verification` meta tag), set in
241
+ * the dashboard under the sales channel's settings. When present, render
242
+ * `<meta name="google-site-verification" content={token} />` in the root
243
+ * layout `<head>` — it is what lets the merchant verify the storefront in
244
+ * Google Search Console and claim it in Merchant Center. Public by design
245
+ * (the token appears in page source on every verified site).
237
246
  */
238
247
  seo?: {
239
248
  indexNowKey: string | null;
249
+ googleSiteVerification?: string | null;
240
250
  };
241
251
  /**
242
252
  * Real merchant-configured shipping rates (sales-channel mode only) —
@@ -1998,9 +2008,40 @@ interface Customer {
1998
2008
  externalId: string;
1999
2009
  }>;
2000
2010
  addresses: CustomerAddress[];
2011
+ /**
2012
+ * FIRST-TOUCH sales channel — the storefront this customer originally arrived
2013
+ * through. `null`/absent is a normal state, not an error: customers created in
2014
+ * the dashboard, imported from a file, arriving via a `storeId`-mode
2015
+ * storefront, or predating channel attribution have no value here.
2016
+ *
2017
+ * Different from `platformConnections` (their ids on Shopify/WooCommerce) and
2018
+ * from `channelPublishes` below (where they are active now).
2019
+ */
2020
+ acquisitionSalesChannel?: CustomerSalesChannelRef | null;
2021
+ /**
2022
+ * Every sales channel this customer is active in — one entry per channel they
2023
+ * registered, signed in, checked out or ordered on, plus any a merchant
2024
+ * attached by hand. A customer belongs to exactly one store but can be active
2025
+ * in any number of that store's channels. `[]` = none known yet.
2026
+ */
2027
+ channelPublishes?: CustomerChannelPublish[];
2001
2028
  createdAt: string;
2002
2029
  updatedAt: string;
2003
2030
  }
2031
+ interface CustomerSalesChannelRef {
2032
+ /** Internal SalesChannel id (cuid). */
2033
+ id: string;
2034
+ name: string;
2035
+ /** Public `vc_*` connection id — the one your storefront initialises with. */
2036
+ connectionId: string;
2037
+ }
2038
+ interface CustomerChannelPublish {
2039
+ salesChannel: CustomerSalesChannelRef;
2040
+ /** First time this customer was seen on this channel. */
2041
+ firstSeenAt: string;
2042
+ /** Most recent time this customer was seen on this channel. */
2043
+ lastSeenAt: string;
2044
+ }
2004
2045
  /**
2005
2046
  * Display-only summary of a vaulted payment method.
2006
2047
  *
@@ -2091,6 +2132,14 @@ interface CreateCustomerDto {
2091
2132
  tags?: string[];
2092
2133
  /** Free-form merchant-set segment (e.g. "wholesale", "vip"), max 50 chars. */
2093
2134
  role?: string;
2135
+ /**
2136
+ * Explicit FIRST-TOUCH channel (internal SalesChannel id or public `vc_*`).
2137
+ * Creating a customer through the API is not itself a channel sighting, so
2138
+ * omitting this leaves the customer's origin unknown — set it only when you
2139
+ * actually know where the person came from (a migration, a phone order for a
2140
+ * specific storefront). Which channels they SHOP on is separate.
2141
+ */
2142
+ acquisitionSalesChannelId?: string;
2094
2143
  metadata?: Record<string, unknown>;
2095
2144
  }
2096
2145
  interface UpdateCustomerDto {
@@ -2102,6 +2151,15 @@ interface UpdateCustomerDto {
2102
2151
  tags?: string[];
2103
2152
  /** Free-form merchant-set segment. Pass '' to clear it. */
2104
2153
  role?: string;
2154
+ /**
2155
+ * Override the FIRST-TOUCH channel. Normally stamped automatically when the
2156
+ * customer registers, signs in with OAuth, or checks out — this is the
2157
+ * correction path for customers created through the API/dashboard or imported
2158
+ * from a file, where no channel was ever observed. Accepts an internal
2159
+ * SalesChannel id or a public `vc_*` connectionId; `''` clears it back to
2160
+ * unknown. Does NOT change which channels they are active in.
2161
+ */
2162
+ acquisitionSalesChannelId?: string;
2105
2163
  metadata?: Record<string, unknown>;
2106
2164
  }
2107
2165
  interface CustomerQueryParams {
@@ -2111,6 +2169,17 @@ interface CustomerQueryParams {
2111
2169
  hasAccount?: boolean;
2112
2170
  /** Filter by merchant-set customer role/segment (exact match, case-insensitive). */
2113
2171
  role?: string;
2172
+ /**
2173
+ * Only customers ACTIVE IN this channel (they registered, signed in, checked
2174
+ * out or ordered there, or a merchant attached them). Accepts an internal
2175
+ * SalesChannel id or a public `vc_*` connectionId.
2176
+ */
2177
+ salesChannelId?: string;
2178
+ /**
2179
+ * Only customers whose FIRST TOUCH was this channel, regardless of where they
2180
+ * have been active since. Customers with no attribution match nothing here.
2181
+ */
2182
+ acquisitionSalesChannelId?: string;
2114
2183
  sortBy?: 'createdAt' | 'email' | 'firstName' | 'lastName' | 'lastOrderAt';
2115
2184
  sortOrder?: 'asc' | 'desc';
2116
2185
  }
@@ -6817,6 +6886,41 @@ declare class BrainerceClient {
6817
6886
  * ```
6818
6887
  */
6819
6888
  getProducts(params?: ProductQueryParams): Promise<PaginatedResponse<Product>>;
6889
+ /**
6890
+ * Lightweight product rows for sitemap generation: `slug`, `updatedAt`, and
6891
+ * per-locale `localeSlugs` only — up to `limit` (max 5000) in ONE request,
6892
+ * with none of the 100-per-page clamp the full listing applies.
6893
+ *
6894
+ * Sales-channel (`salesChannelId`) mode only; other modes throw so
6895
+ * {@link getProductSitemapEntries} (sitemap.ts) can catch and fall back to
6896
+ * paginating `getProducts`. Prefer that helper over calling this directly.
6897
+ */
6898
+ getSitemapProducts(limit?: number): Promise<Array<{
6899
+ id: string;
6900
+ slug: string | null;
6901
+ updatedAt: string;
6902
+ localeSlugs: Record<string, string> | null;
6903
+ }>>;
6904
+ /**
6905
+ * Resolve an old (renamed) slug to the entity's CURRENT slug, so the
6906
+ * storefront can issue a permanent (301/308) redirect instead of a 404.
6907
+ *
6908
+ * Call this in the catch/not-found path of a product or blog page:
6909
+ * the platform records every slug rename, so a URL that stopped matching
6910
+ * usually has a redirect. Returns `null` when there is no redirect (real
6911
+ * 404) or outside sales-channel mode — always fall through to notFound().
6912
+ *
6913
+ * @example
6914
+ * ```typescript
6915
+ * // app/products/[slug]/page.tsx — in the catch path:
6916
+ * const redirect = await client.resolveSlugRedirect('product', slug);
6917
+ * if (redirect) permanentRedirect(`/products/${redirect.currentSlug}`);
6918
+ * notFound();
6919
+ * ```
6920
+ */
6921
+ resolveSlugRedirect(entityType: 'product' | 'blog', slug: string): Promise<{
6922
+ currentSlug: string;
6923
+ } | null>;
6820
6924
  /**
6821
6925
  * Get a single product by ID
6822
6926
  * Works in vibe-coded, storefront (public), and admin mode
@@ -10918,6 +11022,33 @@ declare class BrainerceClient {
10918
11022
  unpublishProductFromSalesChannel(productId: string, salesChannelId: string): Promise<{
10919
11023
  success: boolean;
10920
11024
  }>;
11025
+ /**
11026
+ * Attach a customer to a sales channel (admin mode) — marks them as active in
11027
+ * that storefront. Accepts the sales-channel record ID or its public `vc_*`
11028
+ * connection ID.
11029
+ *
11030
+ * Rarely needed: the platform records a channel by itself whenever the
11031
+ * customer registers, signs in or checks out on it. Use this for migrations
11032
+ * from another system and for fixing up records you created yourself. A
11033
+ * customer belongs to one store but can be active in any number of its
11034
+ * channels, so calling this for several channels is normal and expected.
11035
+ *
11036
+ * This does not change where the customer CAME FROM — for that, pass
11037
+ * `acquisitionSalesChannelId` to {@link updateCustomer}.
11038
+ */
11039
+ publishCustomerToSalesChannel(customerId: string, salesChannelId: string): Promise<{
11040
+ success: boolean;
11041
+ }>;
11042
+ /**
11043
+ * Detach a customer from a sales channel (admin mode).
11044
+ *
11045
+ * A correction, NOT a block — it does not stop that person from buying on
11046
+ * that storefront, and the channel is recorded again the next time they sign
11047
+ * in or order there. There is no way to bar a customer from a channel.
11048
+ */
11049
+ unpublishCustomerFromSalesChannel(customerId: string, salesChannelId: string): Promise<{
11050
+ success: boolean;
11051
+ }>;
10921
11052
  /**
10922
11053
  * Publish a coupon to a sales channel (admin mode) — makes it redeemable on
10923
11054
  * that vibe-coded storefront. Accepts the sales-channel record ID or its
@@ -11725,6 +11856,34 @@ interface BlogSitemapOptions {
11725
11856
  * only returns PUBLISHED posts, so no status filtering is needed.
11726
11857
  */
11727
11858
  declare function getBlogSitemapEntries(client: BrainerceClient, opts: BlogSitemapOptions): Promise<SitemapEntry[]>;
11859
+ interface ProductSitemapOptions {
11860
+ /** Canonical site origin, e.g. "https://shop.com" (no trailing slash). */
11861
+ siteUrl: string;
11862
+ /** Product route prefix. Default '/products'. */
11863
+ basePath?: string;
11864
+ /**
11865
+ * Locales to emit locale-prefixed entries for. The default locale is emitted
11866
+ * unprefixed; every other locale as `/{locale}{basePath}/{localeSlug}`,
11867
+ * using the product's per-locale slug (`localeSlugs`) when one exists.
11868
+ */
11869
+ locales?: string[];
11870
+ defaultLocale?: string;
11871
+ /** Page size for the pagination fallback (max 100). Default 100. */
11872
+ pageSize?: number;
11873
+ /** Safety cap on total products. Default 5000. */
11874
+ maxEntries?: number;
11875
+ }
11876
+ /**
11877
+ * Every published product as sitemap entries — the REQUIRED way to build the
11878
+ * products section of `app/sitemap.ts`.
11879
+ *
11880
+ * Do NOT call `getProducts({ limit: 1000 })` for sitemaps: the public API
11881
+ * clamps `limit` to 100, so any store with more than 100 products silently
11882
+ * ships a truncated sitemap. This helper uses the dedicated lightweight
11883
+ * sitemap endpoint (slug + updatedAt only, up to 5000 in one call) and falls
11884
+ * back to paginating the full listing on older backends.
11885
+ */
11886
+ declare function getProductSitemapEntries(client: BrainerceClient, opts: ProductSitemapOptions): Promise<SitemapEntry[]>;
11728
11887
  interface CategorySitemapOptions {
11729
11888
  /** Canonical site origin, e.g. "https://shop.com" (no trailing slash). */
11730
11889
  siteUrl: string;
@@ -11742,4 +11901,4 @@ interface CategorySitemapOptions {
11742
11901
  */
11743
11902
  declare function getCategorySitemapEntries(client: BrainerceClient, opts: CategorySitemapOptions): Promise<SitemapEntry[]>;
11744
11903
 
11745
- 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 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, 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, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCalendarDateAllowed, isCouponApplicableToProduct, isDateValueAllowed, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseDateFieldValue, parseWebhookEvent, resolveStoreLocalParts, safePaymentRedirect, stripHtml, validateDateAvailabilityConfig, verifyWebhook };
11904
+ 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, 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
@@ -229,14 +229,24 @@ interface StoreInfo {
229
229
  /** Multi-language / i18n settings */
230
230
  i18n?: I18nSettings;
231
231
  /**
232
- * SEO Autopilot fields (sales-channel mode only).
232
+ * SEO fields (sales-channel mode only).
233
+ *
233
234
  * `indexNowKey`: serve this verbatim at `GET /indexnow-key.txt`
234
235
  * (`text/plain`) so the platform can ping IndexNow when blog posts publish.
235
236
  * Not a secret — the key file is public by protocol design. `null` until
236
237
  * the store's SEO Autopilot generates one; return 404 while null.
238
+ *
239
+ * `googleSiteVerification`: the merchant's Google site-verification token
240
+ * (the `content` value of the `google-site-verification` meta tag), set in
241
+ * the dashboard under the sales channel's settings. When present, render
242
+ * `<meta name="google-site-verification" content={token} />` in the root
243
+ * layout `<head>` — it is what lets the merchant verify the storefront in
244
+ * Google Search Console and claim it in Merchant Center. Public by design
245
+ * (the token appears in page source on every verified site).
237
246
  */
238
247
  seo?: {
239
248
  indexNowKey: string | null;
249
+ googleSiteVerification?: string | null;
240
250
  };
241
251
  /**
242
252
  * Real merchant-configured shipping rates (sales-channel mode only) —
@@ -1998,9 +2008,40 @@ interface Customer {
1998
2008
  externalId: string;
1999
2009
  }>;
2000
2010
  addresses: CustomerAddress[];
2011
+ /**
2012
+ * FIRST-TOUCH sales channel — the storefront this customer originally arrived
2013
+ * through. `null`/absent is a normal state, not an error: customers created in
2014
+ * the dashboard, imported from a file, arriving via a `storeId`-mode
2015
+ * storefront, or predating channel attribution have no value here.
2016
+ *
2017
+ * Different from `platformConnections` (their ids on Shopify/WooCommerce) and
2018
+ * from `channelPublishes` below (where they are active now).
2019
+ */
2020
+ acquisitionSalesChannel?: CustomerSalesChannelRef | null;
2021
+ /**
2022
+ * Every sales channel this customer is active in — one entry per channel they
2023
+ * registered, signed in, checked out or ordered on, plus any a merchant
2024
+ * attached by hand. A customer belongs to exactly one store but can be active
2025
+ * in any number of that store's channels. `[]` = none known yet.
2026
+ */
2027
+ channelPublishes?: CustomerChannelPublish[];
2001
2028
  createdAt: string;
2002
2029
  updatedAt: string;
2003
2030
  }
2031
+ interface CustomerSalesChannelRef {
2032
+ /** Internal SalesChannel id (cuid). */
2033
+ id: string;
2034
+ name: string;
2035
+ /** Public `vc_*` connection id — the one your storefront initialises with. */
2036
+ connectionId: string;
2037
+ }
2038
+ interface CustomerChannelPublish {
2039
+ salesChannel: CustomerSalesChannelRef;
2040
+ /** First time this customer was seen on this channel. */
2041
+ firstSeenAt: string;
2042
+ /** Most recent time this customer was seen on this channel. */
2043
+ lastSeenAt: string;
2044
+ }
2004
2045
  /**
2005
2046
  * Display-only summary of a vaulted payment method.
2006
2047
  *
@@ -2091,6 +2132,14 @@ interface CreateCustomerDto {
2091
2132
  tags?: string[];
2092
2133
  /** Free-form merchant-set segment (e.g. "wholesale", "vip"), max 50 chars. */
2093
2134
  role?: string;
2135
+ /**
2136
+ * Explicit FIRST-TOUCH channel (internal SalesChannel id or public `vc_*`).
2137
+ * Creating a customer through the API is not itself a channel sighting, so
2138
+ * omitting this leaves the customer's origin unknown — set it only when you
2139
+ * actually know where the person came from (a migration, a phone order for a
2140
+ * specific storefront). Which channels they SHOP on is separate.
2141
+ */
2142
+ acquisitionSalesChannelId?: string;
2094
2143
  metadata?: Record<string, unknown>;
2095
2144
  }
2096
2145
  interface UpdateCustomerDto {
@@ -2102,6 +2151,15 @@ interface UpdateCustomerDto {
2102
2151
  tags?: string[];
2103
2152
  /** Free-form merchant-set segment. Pass '' to clear it. */
2104
2153
  role?: string;
2154
+ /**
2155
+ * Override the FIRST-TOUCH channel. Normally stamped automatically when the
2156
+ * customer registers, signs in with OAuth, or checks out — this is the
2157
+ * correction path for customers created through the API/dashboard or imported
2158
+ * from a file, where no channel was ever observed. Accepts an internal
2159
+ * SalesChannel id or a public `vc_*` connectionId; `''` clears it back to
2160
+ * unknown. Does NOT change which channels they are active in.
2161
+ */
2162
+ acquisitionSalesChannelId?: string;
2105
2163
  metadata?: Record<string, unknown>;
2106
2164
  }
2107
2165
  interface CustomerQueryParams {
@@ -2111,6 +2169,17 @@ interface CustomerQueryParams {
2111
2169
  hasAccount?: boolean;
2112
2170
  /** Filter by merchant-set customer role/segment (exact match, case-insensitive). */
2113
2171
  role?: string;
2172
+ /**
2173
+ * Only customers ACTIVE IN this channel (they registered, signed in, checked
2174
+ * out or ordered there, or a merchant attached them). Accepts an internal
2175
+ * SalesChannel id or a public `vc_*` connectionId.
2176
+ */
2177
+ salesChannelId?: string;
2178
+ /**
2179
+ * Only customers whose FIRST TOUCH was this channel, regardless of where they
2180
+ * have been active since. Customers with no attribution match nothing here.
2181
+ */
2182
+ acquisitionSalesChannelId?: string;
2114
2183
  sortBy?: 'createdAt' | 'email' | 'firstName' | 'lastName' | 'lastOrderAt';
2115
2184
  sortOrder?: 'asc' | 'desc';
2116
2185
  }
@@ -6817,6 +6886,41 @@ declare class BrainerceClient {
6817
6886
  * ```
6818
6887
  */
6819
6888
  getProducts(params?: ProductQueryParams): Promise<PaginatedResponse<Product>>;
6889
+ /**
6890
+ * Lightweight product rows for sitemap generation: `slug`, `updatedAt`, and
6891
+ * per-locale `localeSlugs` only — up to `limit` (max 5000) in ONE request,
6892
+ * with none of the 100-per-page clamp the full listing applies.
6893
+ *
6894
+ * Sales-channel (`salesChannelId`) mode only; other modes throw so
6895
+ * {@link getProductSitemapEntries} (sitemap.ts) can catch and fall back to
6896
+ * paginating `getProducts`. Prefer that helper over calling this directly.
6897
+ */
6898
+ getSitemapProducts(limit?: number): Promise<Array<{
6899
+ id: string;
6900
+ slug: string | null;
6901
+ updatedAt: string;
6902
+ localeSlugs: Record<string, string> | null;
6903
+ }>>;
6904
+ /**
6905
+ * Resolve an old (renamed) slug to the entity's CURRENT slug, so the
6906
+ * storefront can issue a permanent (301/308) redirect instead of a 404.
6907
+ *
6908
+ * Call this in the catch/not-found path of a product or blog page:
6909
+ * the platform records every slug rename, so a URL that stopped matching
6910
+ * usually has a redirect. Returns `null` when there is no redirect (real
6911
+ * 404) or outside sales-channel mode — always fall through to notFound().
6912
+ *
6913
+ * @example
6914
+ * ```typescript
6915
+ * // app/products/[slug]/page.tsx — in the catch path:
6916
+ * const redirect = await client.resolveSlugRedirect('product', slug);
6917
+ * if (redirect) permanentRedirect(`/products/${redirect.currentSlug}`);
6918
+ * notFound();
6919
+ * ```
6920
+ */
6921
+ resolveSlugRedirect(entityType: 'product' | 'blog', slug: string): Promise<{
6922
+ currentSlug: string;
6923
+ } | null>;
6820
6924
  /**
6821
6925
  * Get a single product by ID
6822
6926
  * Works in vibe-coded, storefront (public), and admin mode
@@ -10918,6 +11022,33 @@ declare class BrainerceClient {
10918
11022
  unpublishProductFromSalesChannel(productId: string, salesChannelId: string): Promise<{
10919
11023
  success: boolean;
10920
11024
  }>;
11025
+ /**
11026
+ * Attach a customer to a sales channel (admin mode) — marks them as active in
11027
+ * that storefront. Accepts the sales-channel record ID or its public `vc_*`
11028
+ * connection ID.
11029
+ *
11030
+ * Rarely needed: the platform records a channel by itself whenever the
11031
+ * customer registers, signs in or checks out on it. Use this for migrations
11032
+ * from another system and for fixing up records you created yourself. A
11033
+ * customer belongs to one store but can be active in any number of its
11034
+ * channels, so calling this for several channels is normal and expected.
11035
+ *
11036
+ * This does not change where the customer CAME FROM — for that, pass
11037
+ * `acquisitionSalesChannelId` to {@link updateCustomer}.
11038
+ */
11039
+ publishCustomerToSalesChannel(customerId: string, salesChannelId: string): Promise<{
11040
+ success: boolean;
11041
+ }>;
11042
+ /**
11043
+ * Detach a customer from a sales channel (admin mode).
11044
+ *
11045
+ * A correction, NOT a block — it does not stop that person from buying on
11046
+ * that storefront, and the channel is recorded again the next time they sign
11047
+ * in or order there. There is no way to bar a customer from a channel.
11048
+ */
11049
+ unpublishCustomerFromSalesChannel(customerId: string, salesChannelId: string): Promise<{
11050
+ success: boolean;
11051
+ }>;
10921
11052
  /**
10922
11053
  * Publish a coupon to a sales channel (admin mode) — makes it redeemable on
10923
11054
  * that vibe-coded storefront. Accepts the sales-channel record ID or its
@@ -11725,6 +11856,34 @@ interface BlogSitemapOptions {
11725
11856
  * only returns PUBLISHED posts, so no status filtering is needed.
11726
11857
  */
11727
11858
  declare function getBlogSitemapEntries(client: BrainerceClient, opts: BlogSitemapOptions): Promise<SitemapEntry[]>;
11859
+ interface ProductSitemapOptions {
11860
+ /** Canonical site origin, e.g. "https://shop.com" (no trailing slash). */
11861
+ siteUrl: string;
11862
+ /** Product route prefix. Default '/products'. */
11863
+ basePath?: string;
11864
+ /**
11865
+ * Locales to emit locale-prefixed entries for. The default locale is emitted
11866
+ * unprefixed; every other locale as `/{locale}{basePath}/{localeSlug}`,
11867
+ * using the product's per-locale slug (`localeSlugs`) when one exists.
11868
+ */
11869
+ locales?: string[];
11870
+ defaultLocale?: string;
11871
+ /** Page size for the pagination fallback (max 100). Default 100. */
11872
+ pageSize?: number;
11873
+ /** Safety cap on total products. Default 5000. */
11874
+ maxEntries?: number;
11875
+ }
11876
+ /**
11877
+ * Every published product as sitemap entries — the REQUIRED way to build the
11878
+ * products section of `app/sitemap.ts`.
11879
+ *
11880
+ * Do NOT call `getProducts({ limit: 1000 })` for sitemaps: the public API
11881
+ * clamps `limit` to 100, so any store with more than 100 products silently
11882
+ * ships a truncated sitemap. This helper uses the dedicated lightweight
11883
+ * sitemap endpoint (slug + updatedAt only, up to 5000 in one call) and falls
11884
+ * back to paginating the full listing on older backends.
11885
+ */
11886
+ declare function getProductSitemapEntries(client: BrainerceClient, opts: ProductSitemapOptions): Promise<SitemapEntry[]>;
11728
11887
  interface CategorySitemapOptions {
11729
11888
  /** Canonical site origin, e.g. "https://shop.com" (no trailing slash). */
11730
11889
  siteUrl: string;
@@ -11742,4 +11901,4 @@ interface CategorySitemapOptions {
11742
11901
  */
11743
11902
  declare function getCategorySitemapEntries(client: BrainerceClient, opts: CategorySitemapOptions): Promise<SitemapEntry[]>;
11744
11903
 
11745
- 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 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, 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, getProductSwatches, getStockStatus, getVariantOptions, getVariantPrice, isAllowedPaymentUrl, isCalendarDateAllowed, isCouponApplicableToProduct, isDateValueAllowed, isHtmlDescription, isWebhookEventType, jsonLdScriptProps, parseDateFieldValue, parseWebhookEvent, resolveStoreLocalParts, safePaymentRedirect, stripHtml, validateDateAvailabilityConfig, verifyWebhook };
11904
+ 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, 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
@@ -63,6 +63,7 @@ __export(index_exports, {
63
63
  getProductMetafieldsByType: () => getProductMetafieldsByType,
64
64
  getProductPrice: () => getProductPrice,
65
65
  getProductPriceInfo: () => getProductPriceInfo,
66
+ getProductSitemapEntries: () => getProductSitemapEntries,
66
67
  getProductSwatches: () => getProductSwatches,
67
68
  getStockStatus: () => getStockStatus,
68
69
  getVariantOptions: () => getVariantOptions,
@@ -1653,6 +1654,50 @@ var _BrainerceClient = class _BrainerceClient {
1653
1654
  queryParamsWithRegion
1654
1655
  );
1655
1656
  }
1657
+ /**
1658
+ * Lightweight product rows for sitemap generation: `slug`, `updatedAt`, and
1659
+ * per-locale `localeSlugs` only — up to `limit` (max 5000) in ONE request,
1660
+ * with none of the 100-per-page clamp the full listing applies.
1661
+ *
1662
+ * Sales-channel (`salesChannelId`) mode only; other modes throw so
1663
+ * {@link getProductSitemapEntries} (sitemap.ts) can catch and fall back to
1664
+ * paginating `getProducts`. Prefer that helper over calling this directly.
1665
+ */
1666
+ async getSitemapProducts(limit = 5e3) {
1667
+ if (!this.isVibeCodedMode()) {
1668
+ throw new Error("getSitemapProducts is available in salesChannelId mode only");
1669
+ }
1670
+ const res = await this.vibeCodedRequest("GET", "/sitemap-products", void 0, { limit: Math.min(limit, 5e3) });
1671
+ return res.data;
1672
+ }
1673
+ /**
1674
+ * Resolve an old (renamed) slug to the entity's CURRENT slug, so the
1675
+ * storefront can issue a permanent (301/308) redirect instead of a 404.
1676
+ *
1677
+ * Call this in the catch/not-found path of a product or blog page:
1678
+ * the platform records every slug rename, so a URL that stopped matching
1679
+ * usually has a redirect. Returns `null` when there is no redirect (real
1680
+ * 404) or outside sales-channel mode — always fall through to notFound().
1681
+ *
1682
+ * @example
1683
+ * ```typescript
1684
+ * // app/products/[slug]/page.tsx — in the catch path:
1685
+ * const redirect = await client.resolveSlugRedirect('product', slug);
1686
+ * if (redirect) permanentRedirect(`/products/${redirect.currentSlug}`);
1687
+ * notFound();
1688
+ * ```
1689
+ */
1690
+ async resolveSlugRedirect(entityType, slug) {
1691
+ if (!this.isVibeCodedMode()) return null;
1692
+ try {
1693
+ return await this.vibeCodedRequest(
1694
+ "GET",
1695
+ `/slug-redirects/${entityType}/${encodePathSegment(slug)}`
1696
+ );
1697
+ } catch {
1698
+ return null;
1699
+ }
1700
+ }
1656
1701
  /**
1657
1702
  * Get a single product by ID
1658
1703
  * Works in vibe-coded, storefront (public), and admin mode
@@ -8945,6 +8990,41 @@ var _BrainerceClient = class _BrainerceClient {
8945
8990
  { salesChannelId }
8946
8991
  );
8947
8992
  }
8993
+ /**
8994
+ * Attach a customer to a sales channel (admin mode) — marks them as active in
8995
+ * that storefront. Accepts the sales-channel record ID or its public `vc_*`
8996
+ * connection ID.
8997
+ *
8998
+ * Rarely needed: the platform records a channel by itself whenever the
8999
+ * customer registers, signs in or checks out on it. Use this for migrations
9000
+ * from another system and for fixing up records you created yourself. A
9001
+ * customer belongs to one store but can be active in any number of its
9002
+ * channels, so calling this for several channels is normal and expected.
9003
+ *
9004
+ * This does not change where the customer CAME FROM — for that, pass
9005
+ * `acquisitionSalesChannelId` to {@link updateCustomer}.
9006
+ */
9007
+ async publishCustomerToSalesChannel(customerId, salesChannelId) {
9008
+ return this.adminRequest(
9009
+ "POST",
9010
+ `/api/v1/customers/${encodePathSegment(customerId)}/publish-sales-channel`,
9011
+ { salesChannelId }
9012
+ );
9013
+ }
9014
+ /**
9015
+ * Detach a customer from a sales channel (admin mode).
9016
+ *
9017
+ * A correction, NOT a block — it does not stop that person from buying on
9018
+ * that storefront, and the channel is recorded again the next time they sign
9019
+ * in or order there. There is no way to bar a customer from a channel.
9020
+ */
9021
+ async unpublishCustomerFromSalesChannel(customerId, salesChannelId) {
9022
+ return this.adminRequest(
9023
+ "POST",
9024
+ `/api/v1/customers/${encodePathSegment(customerId)}/unpublish-sales-channel`,
9025
+ { salesChannelId }
9026
+ );
9027
+ }
8948
9028
  /**
8949
9029
  * Publish a coupon to a sales channel (admin mode) — makes it redeemable on
8950
9030
  * that vibe-coded storefront. Accepts the sales-channel record ID or its
@@ -10136,7 +10216,8 @@ function buildProductJsonLd(product, opts) {
10136
10216
  const brand = opts.brandName ?? product.brands?.[0]?.name;
10137
10217
  const description = stripHtml(product.description).slice(0, 5e3);
10138
10218
  const effectivePrice = product.salePrice ?? product.basePrice;
10139
- const inStock = product.inventory ? (product.inventory.available ?? 0) > 0 : true;
10219
+ const inv = product.inventory;
10220
+ const availability = !inv ? "https://schema.org/InStock" : inv.inStock ?? (inv.available ?? 0) > 0 ? "https://schema.org/InStock" : inv.canPurchase ? "https://schema.org/BackOrder" : "https://schema.org/OutOfStock";
10140
10221
  const isVariable = product.type === "VARIABLE" && product.priceMin && product.priceMax;
10141
10222
  const itemCondition = "https://schema.org/NewCondition";
10142
10223
  const shippingDetails = (opts.shipping ?? []).filter((z) => z.amount !== null).map((z) => ({
@@ -10167,8 +10248,9 @@ function buildProductJsonLd(product, opts) {
10167
10248
  "@type": "AggregateOffer",
10168
10249
  lowPrice: product.priceMin,
10169
10250
  highPrice: product.priceMax,
10251
+ ...product.variants?.length ? { offerCount: product.variants.length } : {},
10170
10252
  priceCurrency: opts.currency,
10171
- availability: inStock ? "https://schema.org/InStock" : "https://schema.org/OutOfStock",
10253
+ availability,
10172
10254
  itemCondition,
10173
10255
  ...shippingDetails.length > 0 ? { shippingDetails } : {},
10174
10256
  ...url ? { url } : {}
@@ -10176,7 +10258,7 @@ function buildProductJsonLd(product, opts) {
10176
10258
  "@type": "Offer",
10177
10259
  price: effectivePrice,
10178
10260
  priceCurrency: opts.currency,
10179
- availability: inStock ? "https://schema.org/InStock" : "https://schema.org/OutOfStock",
10261
+ availability,
10180
10262
  itemCondition,
10181
10263
  // Only meaningful for an active sale price with a known end date —
10182
10264
  // a regular (non-sale) price has no expiry to declare.
@@ -10191,19 +10273,25 @@ function buildProductJsonLd(product, opts) {
10191
10273
  ...description ? { description } : {},
10192
10274
  ...images.length > 0 ? { image: images } : {},
10193
10275
  ...url ? { url } : {},
10194
- sku: product.sku,
10276
+ // Fall back to the product id so the offer always carries a stable SKU —
10277
+ // Merchant Center matching and review aggregation both key on it.
10278
+ sku: product.sku || product.id,
10195
10279
  // Identifiers Google uses to match a product to its catalog — key for
10196
10280
  // free merchant-listing eligibility without a Merchant Center feed.
10197
10281
  ...product.gtin ? { gtin: product.gtin } : {},
10198
10282
  ...product.mpn ? { mpn: product.mpn } : {},
10199
10283
  ...brand ? { brand: { "@type": "Brand", name: brand } } : {},
10200
10284
  offers: offer,
10201
- // Google policy: never emit an empty/zero rating block.
10285
+ // Google policy: never emit an empty/zero rating block. bestRating /
10286
+ // worstRating make the 1-5 scale explicit so aggregators can't misread
10287
+ // a 4.8 on an assumed 0-10 scale.
10202
10288
  ...product.reviewCount && product.reviewCount > 0 && product.avgRating ? {
10203
10289
  aggregateRating: {
10204
10290
  "@type": "AggregateRating",
10205
10291
  ratingValue: product.avgRating,
10206
- reviewCount: product.reviewCount
10292
+ reviewCount: product.reviewCount,
10293
+ bestRating: 5,
10294
+ worstRating: 1
10207
10295
  }
10208
10296
  } : {}
10209
10297
  };
@@ -10314,6 +10402,54 @@ async function getBlogSitemapEntries(client, opts) {
10314
10402
  }
10315
10403
  return entries;
10316
10404
  }
10405
+ async function getProductSitemapEntries(client, opts) {
10406
+ const base = opts.siteUrl.replace(/\/+$/, "");
10407
+ const basePath = opts.basePath ?? "/products";
10408
+ const pageSize = Math.min(opts.pageSize ?? 100, 100);
10409
+ const maxEntries = opts.maxEntries ?? 5e3;
10410
+ let rows = [];
10411
+ try {
10412
+ rows = await client.getSitemapProducts(maxEntries);
10413
+ } catch {
10414
+ let page = 1;
10415
+ for (; ; ) {
10416
+ const res = await client.getProducts({ page, limit: pageSize });
10417
+ rows.push(
10418
+ ...res.data.map((p) => ({
10419
+ slug: p.slug ?? null,
10420
+ id: p.id,
10421
+ updatedAt: p.updatedAt,
10422
+ localeSlugs: p.localeSlugs ?? null
10423
+ }))
10424
+ );
10425
+ if (page >= res.meta.totalPages || rows.length >= maxEntries) break;
10426
+ page += 1;
10427
+ }
10428
+ }
10429
+ const nonDefaultLocales = opts.locales?.filter((locale) => locale !== opts.defaultLocale) ?? [];
10430
+ const entries = [];
10431
+ for (const row of rows.slice(0, maxEntries)) {
10432
+ const baseSlug = row.slug || row.id;
10433
+ if (!baseSlug) continue;
10434
+ const lastModified = row.updatedAt ? new Date(row.updatedAt) : void 0;
10435
+ const localeSlugs = row.localeSlugs ?? {};
10436
+ entries.push({
10437
+ url: `${base}${basePath}/${baseSlug}`,
10438
+ ...lastModified ? { lastModified } : {},
10439
+ changeFrequency: "daily",
10440
+ priority: 0.8
10441
+ });
10442
+ for (const locale of nonDefaultLocales) {
10443
+ entries.push({
10444
+ url: `${base}/${locale}${basePath}/${localeSlugs[locale] || baseSlug}`,
10445
+ ...lastModified ? { lastModified } : {},
10446
+ changeFrequency: "daily",
10447
+ priority: 0.7
10448
+ });
10449
+ }
10450
+ }
10451
+ return entries;
10452
+ }
10317
10453
  async function getCategorySitemapEntries(client, opts) {
10318
10454
  const base = opts.siteUrl.replace(/\/+$/, "");
10319
10455
  const basePath = opts.basePath ?? "/category";
@@ -10619,6 +10755,7 @@ function isCouponApplicableToProduct(coupon, productId) {
10619
10755
  getProductMetafieldsByType,
10620
10756
  getProductPrice,
10621
10757
  getProductPriceInfo,
10758
+ getProductSitemapEntries,
10622
10759
  getProductSwatches,
10623
10760
  getStockStatus,
10624
10761
  getVariantOptions,
package/dist/index.mjs CHANGED
@@ -1567,6 +1567,50 @@ var _BrainerceClient = class _BrainerceClient {
1567
1567
  queryParamsWithRegion
1568
1568
  );
1569
1569
  }
1570
+ /**
1571
+ * Lightweight product rows for sitemap generation: `slug`, `updatedAt`, and
1572
+ * per-locale `localeSlugs` only — up to `limit` (max 5000) in ONE request,
1573
+ * with none of the 100-per-page clamp the full listing applies.
1574
+ *
1575
+ * Sales-channel (`salesChannelId`) mode only; other modes throw so
1576
+ * {@link getProductSitemapEntries} (sitemap.ts) can catch and fall back to
1577
+ * paginating `getProducts`. Prefer that helper over calling this directly.
1578
+ */
1579
+ async getSitemapProducts(limit = 5e3) {
1580
+ if (!this.isVibeCodedMode()) {
1581
+ throw new Error("getSitemapProducts is available in salesChannelId mode only");
1582
+ }
1583
+ const res = await this.vibeCodedRequest("GET", "/sitemap-products", void 0, { limit: Math.min(limit, 5e3) });
1584
+ return res.data;
1585
+ }
1586
+ /**
1587
+ * Resolve an old (renamed) slug to the entity's CURRENT slug, so the
1588
+ * storefront can issue a permanent (301/308) redirect instead of a 404.
1589
+ *
1590
+ * Call this in the catch/not-found path of a product or blog page:
1591
+ * the platform records every slug rename, so a URL that stopped matching
1592
+ * usually has a redirect. Returns `null` when there is no redirect (real
1593
+ * 404) or outside sales-channel mode — always fall through to notFound().
1594
+ *
1595
+ * @example
1596
+ * ```typescript
1597
+ * // app/products/[slug]/page.tsx — in the catch path:
1598
+ * const redirect = await client.resolveSlugRedirect('product', slug);
1599
+ * if (redirect) permanentRedirect(`/products/${redirect.currentSlug}`);
1600
+ * notFound();
1601
+ * ```
1602
+ */
1603
+ async resolveSlugRedirect(entityType, slug) {
1604
+ if (!this.isVibeCodedMode()) return null;
1605
+ try {
1606
+ return await this.vibeCodedRequest(
1607
+ "GET",
1608
+ `/slug-redirects/${entityType}/${encodePathSegment(slug)}`
1609
+ );
1610
+ } catch {
1611
+ return null;
1612
+ }
1613
+ }
1570
1614
  /**
1571
1615
  * Get a single product by ID
1572
1616
  * Works in vibe-coded, storefront (public), and admin mode
@@ -8859,6 +8903,41 @@ var _BrainerceClient = class _BrainerceClient {
8859
8903
  { salesChannelId }
8860
8904
  );
8861
8905
  }
8906
+ /**
8907
+ * Attach a customer to a sales channel (admin mode) — marks them as active in
8908
+ * that storefront. Accepts the sales-channel record ID or its public `vc_*`
8909
+ * connection ID.
8910
+ *
8911
+ * Rarely needed: the platform records a channel by itself whenever the
8912
+ * customer registers, signs in or checks out on it. Use this for migrations
8913
+ * from another system and for fixing up records you created yourself. A
8914
+ * customer belongs to one store but can be active in any number of its
8915
+ * channels, so calling this for several channels is normal and expected.
8916
+ *
8917
+ * This does not change where the customer CAME FROM — for that, pass
8918
+ * `acquisitionSalesChannelId` to {@link updateCustomer}.
8919
+ */
8920
+ async publishCustomerToSalesChannel(customerId, salesChannelId) {
8921
+ return this.adminRequest(
8922
+ "POST",
8923
+ `/api/v1/customers/${encodePathSegment(customerId)}/publish-sales-channel`,
8924
+ { salesChannelId }
8925
+ );
8926
+ }
8927
+ /**
8928
+ * Detach a customer from a sales channel (admin mode).
8929
+ *
8930
+ * A correction, NOT a block — it does not stop that person from buying on
8931
+ * that storefront, and the channel is recorded again the next time they sign
8932
+ * in or order there. There is no way to bar a customer from a channel.
8933
+ */
8934
+ async unpublishCustomerFromSalesChannel(customerId, salesChannelId) {
8935
+ return this.adminRequest(
8936
+ "POST",
8937
+ `/api/v1/customers/${encodePathSegment(customerId)}/unpublish-sales-channel`,
8938
+ { salesChannelId }
8939
+ );
8940
+ }
8862
8941
  /**
8863
8942
  * Publish a coupon to a sales channel (admin mode) — makes it redeemable on
8864
8943
  * that vibe-coded storefront. Accepts the sales-channel record ID or its
@@ -10050,7 +10129,8 @@ function buildProductJsonLd(product, opts) {
10050
10129
  const brand = opts.brandName ?? product.brands?.[0]?.name;
10051
10130
  const description = stripHtml(product.description).slice(0, 5e3);
10052
10131
  const effectivePrice = product.salePrice ?? product.basePrice;
10053
- const inStock = product.inventory ? (product.inventory.available ?? 0) > 0 : true;
10132
+ const inv = product.inventory;
10133
+ const availability = !inv ? "https://schema.org/InStock" : inv.inStock ?? (inv.available ?? 0) > 0 ? "https://schema.org/InStock" : inv.canPurchase ? "https://schema.org/BackOrder" : "https://schema.org/OutOfStock";
10054
10134
  const isVariable = product.type === "VARIABLE" && product.priceMin && product.priceMax;
10055
10135
  const itemCondition = "https://schema.org/NewCondition";
10056
10136
  const shippingDetails = (opts.shipping ?? []).filter((z) => z.amount !== null).map((z) => ({
@@ -10081,8 +10161,9 @@ function buildProductJsonLd(product, opts) {
10081
10161
  "@type": "AggregateOffer",
10082
10162
  lowPrice: product.priceMin,
10083
10163
  highPrice: product.priceMax,
10164
+ ...product.variants?.length ? { offerCount: product.variants.length } : {},
10084
10165
  priceCurrency: opts.currency,
10085
- availability: inStock ? "https://schema.org/InStock" : "https://schema.org/OutOfStock",
10166
+ availability,
10086
10167
  itemCondition,
10087
10168
  ...shippingDetails.length > 0 ? { shippingDetails } : {},
10088
10169
  ...url ? { url } : {}
@@ -10090,7 +10171,7 @@ function buildProductJsonLd(product, opts) {
10090
10171
  "@type": "Offer",
10091
10172
  price: effectivePrice,
10092
10173
  priceCurrency: opts.currency,
10093
- availability: inStock ? "https://schema.org/InStock" : "https://schema.org/OutOfStock",
10174
+ availability,
10094
10175
  itemCondition,
10095
10176
  // Only meaningful for an active sale price with a known end date —
10096
10177
  // a regular (non-sale) price has no expiry to declare.
@@ -10105,19 +10186,25 @@ function buildProductJsonLd(product, opts) {
10105
10186
  ...description ? { description } : {},
10106
10187
  ...images.length > 0 ? { image: images } : {},
10107
10188
  ...url ? { url } : {},
10108
- sku: product.sku,
10189
+ // Fall back to the product id so the offer always carries a stable SKU —
10190
+ // Merchant Center matching and review aggregation both key on it.
10191
+ sku: product.sku || product.id,
10109
10192
  // Identifiers Google uses to match a product to its catalog — key for
10110
10193
  // free merchant-listing eligibility without a Merchant Center feed.
10111
10194
  ...product.gtin ? { gtin: product.gtin } : {},
10112
10195
  ...product.mpn ? { mpn: product.mpn } : {},
10113
10196
  ...brand ? { brand: { "@type": "Brand", name: brand } } : {},
10114
10197
  offers: offer,
10115
- // Google policy: never emit an empty/zero rating block.
10198
+ // Google policy: never emit an empty/zero rating block. bestRating /
10199
+ // worstRating make the 1-5 scale explicit so aggregators can't misread
10200
+ // a 4.8 on an assumed 0-10 scale.
10116
10201
  ...product.reviewCount && product.reviewCount > 0 && product.avgRating ? {
10117
10202
  aggregateRating: {
10118
10203
  "@type": "AggregateRating",
10119
10204
  ratingValue: product.avgRating,
10120
- reviewCount: product.reviewCount
10205
+ reviewCount: product.reviewCount,
10206
+ bestRating: 5,
10207
+ worstRating: 1
10121
10208
  }
10122
10209
  } : {}
10123
10210
  };
@@ -10228,6 +10315,54 @@ async function getBlogSitemapEntries(client, opts) {
10228
10315
  }
10229
10316
  return entries;
10230
10317
  }
10318
+ async function getProductSitemapEntries(client, opts) {
10319
+ const base = opts.siteUrl.replace(/\/+$/, "");
10320
+ const basePath = opts.basePath ?? "/products";
10321
+ const pageSize = Math.min(opts.pageSize ?? 100, 100);
10322
+ const maxEntries = opts.maxEntries ?? 5e3;
10323
+ let rows = [];
10324
+ try {
10325
+ rows = await client.getSitemapProducts(maxEntries);
10326
+ } catch {
10327
+ let page = 1;
10328
+ for (; ; ) {
10329
+ const res = await client.getProducts({ page, limit: pageSize });
10330
+ rows.push(
10331
+ ...res.data.map((p) => ({
10332
+ slug: p.slug ?? null,
10333
+ id: p.id,
10334
+ updatedAt: p.updatedAt,
10335
+ localeSlugs: p.localeSlugs ?? null
10336
+ }))
10337
+ );
10338
+ if (page >= res.meta.totalPages || rows.length >= maxEntries) break;
10339
+ page += 1;
10340
+ }
10341
+ }
10342
+ const nonDefaultLocales = opts.locales?.filter((locale) => locale !== opts.defaultLocale) ?? [];
10343
+ const entries = [];
10344
+ for (const row of rows.slice(0, maxEntries)) {
10345
+ const baseSlug = row.slug || row.id;
10346
+ if (!baseSlug) continue;
10347
+ const lastModified = row.updatedAt ? new Date(row.updatedAt) : void 0;
10348
+ const localeSlugs = row.localeSlugs ?? {};
10349
+ entries.push({
10350
+ url: `${base}${basePath}/${baseSlug}`,
10351
+ ...lastModified ? { lastModified } : {},
10352
+ changeFrequency: "daily",
10353
+ priority: 0.8
10354
+ });
10355
+ for (const locale of nonDefaultLocales) {
10356
+ entries.push({
10357
+ url: `${base}/${locale}${basePath}/${localeSlugs[locale] || baseSlug}`,
10358
+ ...lastModified ? { lastModified } : {},
10359
+ changeFrequency: "daily",
10360
+ priority: 0.7
10361
+ });
10362
+ }
10363
+ }
10364
+ return entries;
10365
+ }
10231
10366
  async function getCategorySitemapEntries(client, opts) {
10232
10367
  const base = opts.siteUrl.replace(/\/+$/, "");
10233
10368
  const basePath = opts.basePath ?? "/category";
@@ -10532,6 +10667,7 @@ export {
10532
10667
  getProductMetafieldsByType,
10533
10668
  getProductPrice,
10534
10669
  getProductPriceInfo,
10670
+ getProductSitemapEntries,
10535
10671
  getProductSwatches,
10536
10672
  getStockStatus,
10537
10673
  getVariantOptions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainerce",
3
- "version": "1.55.0",
3
+ "version": "1.56.0",
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",