@misiki/gocommerce-connector 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -139,6 +139,7 @@ down stays best-effort: the storefront renders from its static record.
139
139
  | content pages (`/p/…`, legal pages) | `/x/cms/pages` |
140
140
  | FAQ | `/x/faq` |
141
141
  | composed home page | `/x/layouts/home` (`?preview=` for a draft) — `layoutService.getHomeLayout()`, null when the store has none; carries `themeSettings` and each collection list's `collections` |
142
+ | product and collection templates | `/x/layouts/product`, `/x/layouts/collection` (`?preview=` for a draft) — `layoutService.getProductLayout()` and `getCollectionLayout()`, the sections the shop arranged around the page's core (`main-product`, `main-collection`); null when none is published, and the page draws as before |
142
143
  | theme settings | `/x/layouts/theme` (`?preview=` for a draft) — `layoutService.getThemeSettings()`, the store's colours, fonts and rounding for every page; null when there are none |
143
144
  | menus | `/x/navigation/menus/{header,footer}`, laid over `store.menu`; any menu by handle |
144
145
  | product specs table | the product's category attribute answers |
@@ -1924,155 +1924,29 @@ declare class ProductService extends CatalogService {
1924
1924
  noOfPage: number;
1925
1925
  page: number;
1926
1926
  }>;
1927
- /** More from this product's category. */
1928
- listRelatedProducts({ page, categoryId, limit, }?: {
1927
+ /**
1928
+ * More like this product. Given `product` (a slug or id), it is the
1929
+ * product's category first, then its collections, then the newest — never
1930
+ * the product itself. Many shops never fill in categories, and an empty
1931
+ * rail under every product page reads as a broken shop.
1932
+ *
1933
+ * Without `product`, it is the old answer: more from `categoryId`.
1934
+ */
1935
+ listRelatedProducts({ page, categoryId, product, limit, }?: {
1929
1936
  page?: number;
1930
1937
  categoryId?: string;
1938
+ product?: string;
1931
1939
  limit?: number;
1932
1940
  }): Promise<{
1933
1941
  data: {
1934
1942
  id: string;
1935
- slug: string;
1936
- title: string;
1937
- name: string;
1938
- subtitle: null;
1939
- description: string;
1940
- status: string;
1941
- active: boolean;
1942
- type: string;
1943
- currency: string;
1944
- currencyCode: string;
1945
- price: number;
1946
- mrp: number;
1947
- minPrice: number;
1948
- maxPrice: number;
1949
- sku: string;
1950
- barcode: string | null;
1951
- weight: number | null;
1952
- originCountry: string | null;
1953
- thumbnail: string;
1954
- image_url: string;
1955
- images: string;
1956
- imageList: string[];
1957
- manageInventory: boolean;
1958
- allowBackorder: boolean;
1959
- stock: number;
1960
- hasStock: boolean;
1961
- categoryId: string | null;
1962
- category: {
1963
- id: string;
1964
- name: string;
1965
- slug: string;
1966
- } | null;
1967
- categories: {
1968
- category: {
1969
- id: string;
1970
- name: string;
1971
- slug: string;
1972
- };
1973
- }[];
1974
- categoryHierarchy: {
1975
- name: string;
1976
- slug: string;
1977
- }[];
1978
- collections: {
1979
- id: string;
1980
- name: string;
1981
- slug: string;
1982
- }[];
1983
- vendor: {
1984
- businessName: string;
1985
- } | null;
1986
- productTags: string;
1987
- keywords: string;
1988
- metaTitle: string;
1989
- metaDescription: string | null;
1990
- link: string;
1991
- options: {
1992
- id: string;
1993
- title: string;
1994
- name: string;
1995
- type: string;
1996
- values: {
1997
- id: string;
1998
- value: string;
1999
- }[];
2000
- }[];
2001
- variants: {
2002
- id: string;
2003
- productId: string;
2004
- title: string;
2005
- sku: string;
2006
- barcode: string | null;
2007
- price: number;
2008
- mrp: number;
2009
- stock: number;
2010
- manageInventory: boolean;
2011
- allowBackorder: boolean;
2012
- active: boolean;
2013
- weight: number | null;
2014
- length: number | null;
2015
- width: number | null;
2016
- height: number | null;
2017
- images: string;
2018
- img: string;
2019
- image: string;
2020
- thumbnail: string;
2021
- options: {
2022
- optionId: string;
2023
- value: string;
2024
- }[];
2025
- metadata: Record<string, unknown> | null;
2026
- }[];
2027
- ratings: ReturnType<typeof toRating>[];
2028
- rating: number | null;
2029
- ratingCount: number;
2030
- reviewCount: number;
2031
- attributes: {
2032
- name: string;
2033
- value: string;
2034
- handle: string;
2035
- }[];
2036
- metadata: Record<string, unknown> | null;
2037
- createdAt: string;
2038
- updatedAt: string;
2039
- }[] | {
2040
- id: string;
2041
- slug: string;
2042
- title: string;
2043
- name: string;
2044
- description: string;
2045
- currency: string;
2046
- price: number;
2047
- mrp: number;
2048
- minPrice: number;
2049
- maxPrice: number;
2050
- thumbnail: string | null;
2051
- image_url: string | null;
2052
- images: string;
2053
- stock: number;
2054
- hasStock: boolean;
2055
- manageInventory: boolean;
2056
- allowBackorder: boolean;
2057
- productTags: string;
2058
- category: {
2059
- name: string;
2060
- slug: string;
2061
- } | null;
2062
- vendor: {
2063
- businessName: string;
2064
- } | null;
2065
- variants: ReturnType<typeof toVariant>[];
2066
- options: never[];
2067
- ratings: never[];
2068
- link: string;
2069
- updatedAt: string;
2070
1943
  }[];
2071
1944
  count: number;
2072
1945
  pageSize: number;
2073
1946
  noOfPage: number;
2074
1947
  page: number;
2075
1948
  }>;
1949
+ private relatedTo;
2076
1950
  private shelf;
2077
1951
  /**
2078
1952
  * A review, through ext/reviews. The engine asks for a name and an email
@@ -5861,6 +5735,14 @@ type HomeLayoutSection = {
5861
5735
  products?: StorefrontProduct[];
5862
5736
  collections?: LayoutCollection[];
5863
5737
  };
5738
+ /**
5739
+ * A page the shop arranges: the home page, or the template every product or
5740
+ * every collection is drawn in (ext/layouts, D128). A template holds its
5741
+ * core once — `main-product` (the catalogue's pictures, price and buy box)
5742
+ * or `main-collection` (the collection's grid) — at the place the shop put
5743
+ * it, and the storefront draws its own core there.
5744
+ */
5745
+ type LayoutPage = 'home' | 'product' | 'collection';
5864
5746
  type HomeLayout = {
5865
5747
  page: string;
5866
5748
  theme: string;
@@ -5872,6 +5754,8 @@ type HomeLayout = {
5872
5754
  themeSettings: ThemeSettings | null;
5873
5755
  sections: HomeLayoutSection[];
5874
5756
  };
5757
+ /** A composed page of any kind; a template's `themeSettings` is always null. */
5758
+ type PageLayout = HomeLayout;
5875
5759
  /** The design tokens alone, for every page the storefront draws. */
5876
5760
  type ThemeSettingsResult = {
5877
5761
  revision?: number;
@@ -5888,6 +5772,22 @@ declare class LayoutService extends BaseService {
5888
5772
  getHomeLayout({ preview }?: {
5889
5773
  preview?: string | null;
5890
5774
  }): Promise<HomeLayout | null>;
5775
+ /**
5776
+ * The template every product page is drawn in: the sections around the
5777
+ * product's core (`main-product`). Null when none is published, so the
5778
+ * product page draws exactly as it did before templates existed.
5779
+ */
5780
+ getProductLayout({ preview }?: {
5781
+ preview?: string | null;
5782
+ }): Promise<PageLayout | null>;
5783
+ /** The template every collection page is drawn in, around its grid (`main-collection`). */
5784
+ getCollectionLayout({ preview }?: {
5785
+ preview?: string | null;
5786
+ }): Promise<PageLayout | null>;
5787
+ /** Any arranged page by its key; null for none, as the three above. */
5788
+ getPageLayout(page: LayoutPage, { preview }?: {
5789
+ preview?: string | null;
5790
+ }): Promise<PageLayout | null>;
5891
5791
  /**
5892
5792
  * The store's design tokens, for a page other than the home page: the
5893
5793
  * published ones, or a preview key's draft. Null when there are none to
@@ -7041,4 +6941,4 @@ declare class B2bService extends BaseService {
7041
6941
  }
7042
6942
  declare const b2bService: B2bService;
7043
6943
 
7044
- export { type Lead as $, type Address as A, type B2bPlaced as B, type Cart as C, CountryService as D, CouponService as E, type Credentials as F, type Credit as G, CurrencyService as H, type Customer as I, DealService as J, DemoRequestService as K, type EngineRequest as L, EnquiryService as M, type Envelope as N, type Faq as O, FaqService as P, FeedbackService as Q, type Fulfillment as R, GalleryService as S, type HomeLayout as T, type HomeLayoutSection as U, HomeService as V, type IdentityAddress as W, InitService as X, type Invitation as Y, type LayoutCollection as Z, LayoutService as _, AddressService as a, bannerService as a$, type ListMeta as a0, MeilisearchService as a1, type Member as a2, type Menu as a3, type MenuItem as a4, MenuService as a5, type MenuSummary as a6, type Money as a7, NewsletterService as a8, type Offer as a9, type ShippingRate as aA, StateService as aB, type StoreProfile as aC, StoreService as aD, type StorefrontCategory as aE, type StorefrontMenu as aF, type StorefrontOrder as aG, type StorefrontProduct as aH, type ThemeSettings as aI, type ThemeSettingsResult as aJ, UploadService as aK, UserService as aL, type Variant as aM, type VariantImage as aN, VariantService as aO, VarniCustomDesignService as aP, VarniCustomProductService as aQ, type Vendor as aR, VendorService as aS, WarrantyService as aT, type Wishlist as aU, type WishlistItem as aV, WishlistService as aW, addressService as aX, authService as aY, autocompleteService as aZ, b2bService as a_, type Order as aa, type OrderLine as ab, OrderService as ac, PageService as ad, type PaymentIntent as ae, PaymentMethodService as af, type Plugin as ag, PluginService as ah, PopularSearchService as ai, PopularityService as aj, type Product as ak, type ProductOption as al, ProductService as am, ProfileService as an, type Quote as ao, REDIRECT_GATEWAYS as ap, ReelsService as aq, RegionService as ar, type RejectedLine as as, type Review as at, type ReviewPage as au, ReviewService as av, type SearchDoc as aw, type SearchResult as ax, SearchService as ay, SettingService as az, type AppliedDiscount as b, toOrder as b$, blogService as b0, cartService as b1, categoryService as b2, chatService as b3, checkoutService as b4, collectionService as b5, contactService as b6, countryService as b7, couponService as b8, currencyExponent as b9, popularSearchService as bA, popularityService as bB, priceOf as bC, productImages as bD, productService as bE, profileService as bF, qs as bG, reelsService as bH, regionService as bI, reviewService as bJ, searchService as bK, setRequestHost as bL, settingService as bM, settingsService as bN, stateService as bO, staticStore as bP, storeForHost as bQ, storeService as bR, toCart as bS, toCartLine as bT, toCategory as bU, toCmsPage as bV, toCollection as bW, toEngineAddress as bX, toIdentityAddress as bY, toMajor as bZ, toMinor as b_, currencyService as ba, dealService as bb, demoRequestService as bc, emptyCart as bd, emptyPage as be, enquiryService as bf, faqService as bg, feedbackService as bh, fromEngineAddress as bi, fromIdentityAddress as bj, fromSearchDoc as bk, galleryService as bl, homeService as bm, initService as bn, layoutService as bo, mediaUrl as bp, meilisearchService as bq, menuService as br, minorToMajor as bs, newsletterService as bt, orderService as bu, ownDomain as bv, pageService as bw, paymentMethodService as bx, pluginService as by, pluginsService as bz, type Approval as c, toPage as c0, toProduct as c1, toRating as c2, toUser as c3, toVariant as c4, toVendor as c5, uploadService as c6, userService as c7, variantService as c8, varniCustomDesignService as c9, varniCustomProductService as ca, vendorService as cb, warrantyService as cc, wishlistService as cd, type AuthResponse as d, AuthService as e, AutocompleteService as f, type B2bRole as g, B2bService as h, BannerService as i, BaseService as j, BlogService as k, type CartLine as l, CartService as m, CatalogService as n, type Category as o, CategoryService as p, ChatService as q, type CheckoutOptions as r, type CheckoutResult as s, CheckoutService as t, type CmsPage as u, type Collection as v, CollectionService as w, type Company as x, type CompanyOrder as y, ContactService as z };
6944
+ export { LayoutService as $, type Address as A, type B2bPlaced as B, type Cart as C, CountryService as D, CouponService as E, type Credentials as F, type Credit as G, CurrencyService as H, type Customer as I, DealService as J, DemoRequestService as K, type EngineRequest as L, EnquiryService as M, type Envelope as N, type Faq as O, FaqService as P, FeedbackService as Q, type Fulfillment as R, GalleryService as S, type HomeLayout as T, type HomeLayoutSection as U, HomeService as V, type IdentityAddress as W, InitService as X, type Invitation as Y, type LayoutCollection as Z, type LayoutPage as _, AddressService as a, autocompleteService as a$, type Lead as a0, type ListMeta as a1, MeilisearchService as a2, type Member as a3, type Menu as a4, type MenuItem as a5, MenuService as a6, type MenuSummary as a7, type Money as a8, NewsletterService as a9, SearchService as aA, SettingService as aB, type ShippingRate as aC, StateService as aD, type StoreProfile as aE, StoreService as aF, type StorefrontCategory as aG, type StorefrontMenu as aH, type StorefrontOrder as aI, type StorefrontProduct as aJ, type ThemeSettings as aK, type ThemeSettingsResult as aL, UploadService as aM, UserService as aN, type Variant as aO, type VariantImage as aP, VariantService as aQ, VarniCustomDesignService as aR, VarniCustomProductService as aS, type Vendor as aT, VendorService as aU, WarrantyService as aV, type Wishlist as aW, type WishlistItem as aX, WishlistService as aY, addressService as aZ, authService as a_, type Offer as aa, type Order as ab, type OrderLine as ac, OrderService as ad, type PageLayout as ae, PageService as af, type PaymentIntent as ag, PaymentMethodService as ah, type Plugin as ai, PluginService as aj, PopularSearchService as ak, PopularityService as al, type Product as am, type ProductOption as an, ProductService as ao, ProfileService as ap, type Quote as aq, REDIRECT_GATEWAYS as ar, ReelsService as as, RegionService as at, type RejectedLine as au, type Review as av, type ReviewPage as aw, ReviewService as ax, type SearchDoc as ay, type SearchResult as az, type AppliedDiscount as b, toMajor as b$, b2bService as b0, bannerService as b1, blogService as b2, cartService as b3, categoryService as b4, chatService as b5, checkoutService as b6, collectionService as b7, contactService as b8, countryService as b9, pluginService as bA, pluginsService as bB, popularSearchService as bC, popularityService as bD, priceOf as bE, productImages as bF, productService as bG, profileService as bH, qs as bI, reelsService as bJ, regionService as bK, reviewService as bL, searchService as bM, setRequestHost as bN, settingService as bO, settingsService as bP, stateService as bQ, staticStore as bR, storeForHost as bS, storeService as bT, toCart as bU, toCartLine as bV, toCategory as bW, toCmsPage as bX, toCollection as bY, toEngineAddress as bZ, toIdentityAddress as b_, couponService as ba, currencyExponent as bb, currencyService as bc, dealService as bd, demoRequestService as be, emptyCart as bf, emptyPage as bg, enquiryService as bh, faqService as bi, feedbackService as bj, fromEngineAddress as bk, fromIdentityAddress as bl, fromSearchDoc as bm, galleryService as bn, homeService as bo, initService as bp, layoutService as bq, mediaUrl as br, meilisearchService as bs, menuService as bt, minorToMajor as bu, newsletterService as bv, orderService as bw, ownDomain as bx, pageService as by, paymentMethodService as bz, type Approval as c, toMinor as c0, toOrder as c1, toPage as c2, toProduct as c3, toRating as c4, toUser as c5, toVariant as c6, toVendor as c7, uploadService as c8, userService as c9, variantService as ca, varniCustomDesignService as cb, varniCustomProductService as cc, vendorService as cd, warrantyService as ce, wishlistService as cf, type AuthResponse as d, AuthService as e, AutocompleteService as f, type B2bRole as g, B2bService as h, BannerService as i, BaseService as j, BlogService as k, type CartLine as l, CartService as m, CatalogService as n, type Category as o, CategoryService as p, ChatService as q, type CheckoutOptions as r, type CheckoutResult as s, CheckoutService as t, type CmsPage as u, type Collection as v, CollectionService as w, type Company as x, type CompanyOrder as y, ContactService as z };
@@ -1924,155 +1924,29 @@ declare class ProductService extends CatalogService {
1924
1924
  noOfPage: number;
1925
1925
  page: number;
1926
1926
  }>;
1927
- /** More from this product's category. */
1928
- listRelatedProducts({ page, categoryId, limit, }?: {
1927
+ /**
1928
+ * More like this product. Given `product` (a slug or id), it is the
1929
+ * product's category first, then its collections, then the newest — never
1930
+ * the product itself. Many shops never fill in categories, and an empty
1931
+ * rail under every product page reads as a broken shop.
1932
+ *
1933
+ * Without `product`, it is the old answer: more from `categoryId`.
1934
+ */
1935
+ listRelatedProducts({ page, categoryId, product, limit, }?: {
1929
1936
  page?: number;
1930
1937
  categoryId?: string;
1938
+ product?: string;
1931
1939
  limit?: number;
1932
1940
  }): Promise<{
1933
1941
  data: {
1934
1942
  id: string;
1935
- slug: string;
1936
- title: string;
1937
- name: string;
1938
- subtitle: null;
1939
- description: string;
1940
- status: string;
1941
- active: boolean;
1942
- type: string;
1943
- currency: string;
1944
- currencyCode: string;
1945
- price: number;
1946
- mrp: number;
1947
- minPrice: number;
1948
- maxPrice: number;
1949
- sku: string;
1950
- barcode: string | null;
1951
- weight: number | null;
1952
- originCountry: string | null;
1953
- thumbnail: string;
1954
- image_url: string;
1955
- images: string;
1956
- imageList: string[];
1957
- manageInventory: boolean;
1958
- allowBackorder: boolean;
1959
- stock: number;
1960
- hasStock: boolean;
1961
- categoryId: string | null;
1962
- category: {
1963
- id: string;
1964
- name: string;
1965
- slug: string;
1966
- } | null;
1967
- categories: {
1968
- category: {
1969
- id: string;
1970
- name: string;
1971
- slug: string;
1972
- };
1973
- }[];
1974
- categoryHierarchy: {
1975
- name: string;
1976
- slug: string;
1977
- }[];
1978
- collections: {
1979
- id: string;
1980
- name: string;
1981
- slug: string;
1982
- }[];
1983
- vendor: {
1984
- businessName: string;
1985
- } | null;
1986
- productTags: string;
1987
- keywords: string;
1988
- metaTitle: string;
1989
- metaDescription: string | null;
1990
- link: string;
1991
- options: {
1992
- id: string;
1993
- title: string;
1994
- name: string;
1995
- type: string;
1996
- values: {
1997
- id: string;
1998
- value: string;
1999
- }[];
2000
- }[];
2001
- variants: {
2002
- id: string;
2003
- productId: string;
2004
- title: string;
2005
- sku: string;
2006
- barcode: string | null;
2007
- price: number;
2008
- mrp: number;
2009
- stock: number;
2010
- manageInventory: boolean;
2011
- allowBackorder: boolean;
2012
- active: boolean;
2013
- weight: number | null;
2014
- length: number | null;
2015
- width: number | null;
2016
- height: number | null;
2017
- images: string;
2018
- img: string;
2019
- image: string;
2020
- thumbnail: string;
2021
- options: {
2022
- optionId: string;
2023
- value: string;
2024
- }[];
2025
- metadata: Record<string, unknown> | null;
2026
- }[];
2027
- ratings: ReturnType<typeof toRating>[];
2028
- rating: number | null;
2029
- ratingCount: number;
2030
- reviewCount: number;
2031
- attributes: {
2032
- name: string;
2033
- value: string;
2034
- handle: string;
2035
- }[];
2036
- metadata: Record<string, unknown> | null;
2037
- createdAt: string;
2038
- updatedAt: string;
2039
- }[] | {
2040
- id: string;
2041
- slug: string;
2042
- title: string;
2043
- name: string;
2044
- description: string;
2045
- currency: string;
2046
- price: number;
2047
- mrp: number;
2048
- minPrice: number;
2049
- maxPrice: number;
2050
- thumbnail: string | null;
2051
- image_url: string | null;
2052
- images: string;
2053
- stock: number;
2054
- hasStock: boolean;
2055
- manageInventory: boolean;
2056
- allowBackorder: boolean;
2057
- productTags: string;
2058
- category: {
2059
- name: string;
2060
- slug: string;
2061
- } | null;
2062
- vendor: {
2063
- businessName: string;
2064
- } | null;
2065
- variants: ReturnType<typeof toVariant>[];
2066
- options: never[];
2067
- ratings: never[];
2068
- link: string;
2069
- updatedAt: string;
2070
1943
  }[];
2071
1944
  count: number;
2072
1945
  pageSize: number;
2073
1946
  noOfPage: number;
2074
1947
  page: number;
2075
1948
  }>;
1949
+ private relatedTo;
2076
1950
  private shelf;
2077
1951
  /**
2078
1952
  * A review, through ext/reviews. The engine asks for a name and an email
@@ -5861,6 +5735,14 @@ type HomeLayoutSection = {
5861
5735
  products?: StorefrontProduct[];
5862
5736
  collections?: LayoutCollection[];
5863
5737
  };
5738
+ /**
5739
+ * A page the shop arranges: the home page, or the template every product or
5740
+ * every collection is drawn in (ext/layouts, D128). A template holds its
5741
+ * core once — `main-product` (the catalogue's pictures, price and buy box)
5742
+ * or `main-collection` (the collection's grid) — at the place the shop put
5743
+ * it, and the storefront draws its own core there.
5744
+ */
5745
+ type LayoutPage = 'home' | 'product' | 'collection';
5864
5746
  type HomeLayout = {
5865
5747
  page: string;
5866
5748
  theme: string;
@@ -5872,6 +5754,8 @@ type HomeLayout = {
5872
5754
  themeSettings: ThemeSettings | null;
5873
5755
  sections: HomeLayoutSection[];
5874
5756
  };
5757
+ /** A composed page of any kind; a template's `themeSettings` is always null. */
5758
+ type PageLayout = HomeLayout;
5875
5759
  /** The design tokens alone, for every page the storefront draws. */
5876
5760
  type ThemeSettingsResult = {
5877
5761
  revision?: number;
@@ -5888,6 +5772,22 @@ declare class LayoutService extends BaseService {
5888
5772
  getHomeLayout({ preview }?: {
5889
5773
  preview?: string | null;
5890
5774
  }): Promise<HomeLayout | null>;
5775
+ /**
5776
+ * The template every product page is drawn in: the sections around the
5777
+ * product's core (`main-product`). Null when none is published, so the
5778
+ * product page draws exactly as it did before templates existed.
5779
+ */
5780
+ getProductLayout({ preview }?: {
5781
+ preview?: string | null;
5782
+ }): Promise<PageLayout | null>;
5783
+ /** The template every collection page is drawn in, around its grid (`main-collection`). */
5784
+ getCollectionLayout({ preview }?: {
5785
+ preview?: string | null;
5786
+ }): Promise<PageLayout | null>;
5787
+ /** Any arranged page by its key; null for none, as the three above. */
5788
+ getPageLayout(page: LayoutPage, { preview }?: {
5789
+ preview?: string | null;
5790
+ }): Promise<PageLayout | null>;
5891
5791
  /**
5892
5792
  * The store's design tokens, for a page other than the home page: the
5893
5793
  * published ones, or a preview key's draft. Null when there are none to
@@ -7041,4 +6941,4 @@ declare class B2bService extends BaseService {
7041
6941
  }
7042
6942
  declare const b2bService: B2bService;
7043
6943
 
7044
- export { type Lead as $, type Address as A, type B2bPlaced as B, type Cart as C, CountryService as D, CouponService as E, type Credentials as F, type Credit as G, CurrencyService as H, type Customer as I, DealService as J, DemoRequestService as K, type EngineRequest as L, EnquiryService as M, type Envelope as N, type Faq as O, FaqService as P, FeedbackService as Q, type Fulfillment as R, GalleryService as S, type HomeLayout as T, type HomeLayoutSection as U, HomeService as V, type IdentityAddress as W, InitService as X, type Invitation as Y, type LayoutCollection as Z, LayoutService as _, AddressService as a, bannerService as a$, type ListMeta as a0, MeilisearchService as a1, type Member as a2, type Menu as a3, type MenuItem as a4, MenuService as a5, type MenuSummary as a6, type Money as a7, NewsletterService as a8, type Offer as a9, type ShippingRate as aA, StateService as aB, type StoreProfile as aC, StoreService as aD, type StorefrontCategory as aE, type StorefrontMenu as aF, type StorefrontOrder as aG, type StorefrontProduct as aH, type ThemeSettings as aI, type ThemeSettingsResult as aJ, UploadService as aK, UserService as aL, type Variant as aM, type VariantImage as aN, VariantService as aO, VarniCustomDesignService as aP, VarniCustomProductService as aQ, type Vendor as aR, VendorService as aS, WarrantyService as aT, type Wishlist as aU, type WishlistItem as aV, WishlistService as aW, addressService as aX, authService as aY, autocompleteService as aZ, b2bService as a_, type Order as aa, type OrderLine as ab, OrderService as ac, PageService as ad, type PaymentIntent as ae, PaymentMethodService as af, type Plugin as ag, PluginService as ah, PopularSearchService as ai, PopularityService as aj, type Product as ak, type ProductOption as al, ProductService as am, ProfileService as an, type Quote as ao, REDIRECT_GATEWAYS as ap, ReelsService as aq, RegionService as ar, type RejectedLine as as, type Review as at, type ReviewPage as au, ReviewService as av, type SearchDoc as aw, type SearchResult as ax, SearchService as ay, SettingService as az, type AppliedDiscount as b, toOrder as b$, blogService as b0, cartService as b1, categoryService as b2, chatService as b3, checkoutService as b4, collectionService as b5, contactService as b6, countryService as b7, couponService as b8, currencyExponent as b9, popularSearchService as bA, popularityService as bB, priceOf as bC, productImages as bD, productService as bE, profileService as bF, qs as bG, reelsService as bH, regionService as bI, reviewService as bJ, searchService as bK, setRequestHost as bL, settingService as bM, settingsService as bN, stateService as bO, staticStore as bP, storeForHost as bQ, storeService as bR, toCart as bS, toCartLine as bT, toCategory as bU, toCmsPage as bV, toCollection as bW, toEngineAddress as bX, toIdentityAddress as bY, toMajor as bZ, toMinor as b_, currencyService as ba, dealService as bb, demoRequestService as bc, emptyCart as bd, emptyPage as be, enquiryService as bf, faqService as bg, feedbackService as bh, fromEngineAddress as bi, fromIdentityAddress as bj, fromSearchDoc as bk, galleryService as bl, homeService as bm, initService as bn, layoutService as bo, mediaUrl as bp, meilisearchService as bq, menuService as br, minorToMajor as bs, newsletterService as bt, orderService as bu, ownDomain as bv, pageService as bw, paymentMethodService as bx, pluginService as by, pluginsService as bz, type Approval as c, toPage as c0, toProduct as c1, toRating as c2, toUser as c3, toVariant as c4, toVendor as c5, uploadService as c6, userService as c7, variantService as c8, varniCustomDesignService as c9, varniCustomProductService as ca, vendorService as cb, warrantyService as cc, wishlistService as cd, type AuthResponse as d, AuthService as e, AutocompleteService as f, type B2bRole as g, B2bService as h, BannerService as i, BaseService as j, BlogService as k, type CartLine as l, CartService as m, CatalogService as n, type Category as o, CategoryService as p, ChatService as q, type CheckoutOptions as r, type CheckoutResult as s, CheckoutService as t, type CmsPage as u, type Collection as v, CollectionService as w, type Company as x, type CompanyOrder as y, ContactService as z };
6944
+ export { LayoutService as $, type Address as A, type B2bPlaced as B, type Cart as C, CountryService as D, CouponService as E, type Credentials as F, type Credit as G, CurrencyService as H, type Customer as I, DealService as J, DemoRequestService as K, type EngineRequest as L, EnquiryService as M, type Envelope as N, type Faq as O, FaqService as P, FeedbackService as Q, type Fulfillment as R, GalleryService as S, type HomeLayout as T, type HomeLayoutSection as U, HomeService as V, type IdentityAddress as W, InitService as X, type Invitation as Y, type LayoutCollection as Z, type LayoutPage as _, AddressService as a, autocompleteService as a$, type Lead as a0, type ListMeta as a1, MeilisearchService as a2, type Member as a3, type Menu as a4, type MenuItem as a5, MenuService as a6, type MenuSummary as a7, type Money as a8, NewsletterService as a9, SearchService as aA, SettingService as aB, type ShippingRate as aC, StateService as aD, type StoreProfile as aE, StoreService as aF, type StorefrontCategory as aG, type StorefrontMenu as aH, type StorefrontOrder as aI, type StorefrontProduct as aJ, type ThemeSettings as aK, type ThemeSettingsResult as aL, UploadService as aM, UserService as aN, type Variant as aO, type VariantImage as aP, VariantService as aQ, VarniCustomDesignService as aR, VarniCustomProductService as aS, type Vendor as aT, VendorService as aU, WarrantyService as aV, type Wishlist as aW, type WishlistItem as aX, WishlistService as aY, addressService as aZ, authService as a_, type Offer as aa, type Order as ab, type OrderLine as ac, OrderService as ad, type PageLayout as ae, PageService as af, type PaymentIntent as ag, PaymentMethodService as ah, type Plugin as ai, PluginService as aj, PopularSearchService as ak, PopularityService as al, type Product as am, type ProductOption as an, ProductService as ao, ProfileService as ap, type Quote as aq, REDIRECT_GATEWAYS as ar, ReelsService as as, RegionService as at, type RejectedLine as au, type Review as av, type ReviewPage as aw, ReviewService as ax, type SearchDoc as ay, type SearchResult as az, type AppliedDiscount as b, toMajor as b$, b2bService as b0, bannerService as b1, blogService as b2, cartService as b3, categoryService as b4, chatService as b5, checkoutService as b6, collectionService as b7, contactService as b8, countryService as b9, pluginService as bA, pluginsService as bB, popularSearchService as bC, popularityService as bD, priceOf as bE, productImages as bF, productService as bG, profileService as bH, qs as bI, reelsService as bJ, regionService as bK, reviewService as bL, searchService as bM, setRequestHost as bN, settingService as bO, settingsService as bP, stateService as bQ, staticStore as bR, storeForHost as bS, storeService as bT, toCart as bU, toCartLine as bV, toCategory as bW, toCmsPage as bX, toCollection as bY, toEngineAddress as bZ, toIdentityAddress as b_, couponService as ba, currencyExponent as bb, currencyService as bc, dealService as bd, demoRequestService as be, emptyCart as bf, emptyPage as bg, enquiryService as bh, faqService as bi, feedbackService as bj, fromEngineAddress as bk, fromIdentityAddress as bl, fromSearchDoc as bm, galleryService as bn, homeService as bo, initService as bp, layoutService as bq, mediaUrl as br, meilisearchService as bs, menuService as bt, minorToMajor as bu, newsletterService as bv, orderService as bw, ownDomain as bx, pageService as by, paymentMethodService as bz, type Approval as c, toMinor as c0, toOrder as c1, toPage as c2, toProduct as c3, toRating as c4, toUser as c5, toVariant as c6, toVendor as c7, uploadService as c8, userService as c9, variantService as ca, varniCustomDesignService as cb, varniCustomProductService as cc, vendorService as cd, warrantyService as ce, wishlistService as cf, type AuthResponse as d, AuthService as e, AutocompleteService as f, type B2bRole as g, B2bService as h, BannerService as i, BaseService as j, BlogService as k, type CartLine as l, CartService as m, CatalogService as n, type Category as o, CategoryService as p, ChatService as q, type CheckoutOptions as r, type CheckoutResult as s, CheckoutService as t, type CmsPage as u, type Collection as v, CollectionService as w, type Company as x, type CompanyOrder as y, ContactService as z };
package/dist/index.cjs CHANGED
@@ -1241,17 +1241,46 @@ var ProductService = class extends CatalogService {
1241
1241
  async listTrendingProducts({ page = 1, limit } = {}) {
1242
1242
  return this.shelf("trending", { page, limit });
1243
1243
  }
1244
- /** More from this product's category. */
1244
+ /**
1245
+ * More like this product. Given `product` (a slug or id), it is the
1246
+ * product's category first, then its collections, then the newest — never
1247
+ * the product itself. Many shops never fill in categories, and an empty
1248
+ * rail under every product page reads as a broken shop.
1249
+ *
1250
+ * Without `product`, it is the old answer: more from `categoryId`.
1251
+ */
1245
1252
  async listRelatedProducts({
1246
1253
  page = 1,
1247
1254
  categoryId,
1255
+ product,
1248
1256
  limit
1249
1257
  } = {}) {
1258
+ if (product) return this.relatedTo(String(product), limit);
1250
1259
  if (!categoryId) return this.list({ page, limit });
1251
1260
  const category = (await this.facts.categories()).find((c) => String(c.id) === String(categoryId));
1252
1261
  if (!category) return this.list({ page, limit });
1253
1262
  return this.list({ page, limit, categories: category.slug });
1254
1263
  }
1264
+ async relatedTo(slug, limit) {
1265
+ const size = Math.min(100, Math.max(1, Number(limit) || PAGE_SIZE));
1266
+ const p = await this.findProduct(slug);
1267
+ const self = String(p.id);
1268
+ const picked = /* @__PURE__ */ new Map();
1269
+ const add = (rows) => {
1270
+ for (const r of rows) {
1271
+ if (picked.size >= size) return;
1272
+ if (r.id !== self && !picked.has(r.id)) picked.set(r.id, r);
1273
+ }
1274
+ };
1275
+ if (p.category) add((await this.list({ limit: size + 1, categories: p.category.slug })).data);
1276
+ for (const c of p.collections ?? []) {
1277
+ if (picked.size >= size) break;
1278
+ add((await this.shelf(c.slug, { page: 1, limit: size + 1 })).data);
1279
+ }
1280
+ if (picked.size < size) add((await this.list({ limit: size + 1 })).data);
1281
+ const data = [...picked.values()];
1282
+ return { data, count: data.length, pageSize: size, noOfPage: 1, page: 1 };
1283
+ }
1255
1284
  async shelf(slug, { page, sort, limit }) {
1256
1285
  const size = Math.min(100, Math.max(1, Number(limit) || PAGE_SIZE));
1257
1286
  try {
@@ -2761,9 +2790,25 @@ var faqService = new FaqService();
2761
2790
  var MEDIA_KEYS = /* @__PURE__ */ new Set(["image", "mobile_image", "poster", "video_file"]);
2762
2791
  var LayoutService = class extends BaseService {
2763
2792
  async getHomeLayout({ preview } = {}) {
2793
+ return this.getPageLayout("home", { preview });
2794
+ }
2795
+ /**
2796
+ * The template every product page is drawn in: the sections around the
2797
+ * product's core (`main-product`). Null when none is published, so the
2798
+ * product page draws exactly as it did before templates existed.
2799
+ */
2800
+ async getProductLayout({ preview } = {}) {
2801
+ return this.getPageLayout("product", { preview });
2802
+ }
2803
+ /** The template every collection page is drawn in, around its grid (`main-collection`). */
2804
+ async getCollectionLayout({ preview } = {}) {
2805
+ return this.getPageLayout("collection", { preview });
2806
+ }
2807
+ /** Any arranged page by its key; null for none, as the three above. */
2808
+ async getPageLayout(page, { preview } = {}) {
2764
2809
  let layout;
2765
2810
  try {
2766
- layout = await this.data("/x/layouts/home", {
2811
+ layout = await this.data(`/x/layouts/${encodeURIComponent(page)}`, {
2767
2812
  query: { preview: preview?.trim() || void 0 }
2768
2813
  });
2769
2814
  } catch (err) {