react-shopwave-connect 0.4.2 → 0.4.4

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.
@@ -340,6 +340,26 @@ declare function fetchProductsMap(productIds: number[] | null | undefined, optio
340
340
  [id: number]: Product;
341
341
  }>;
342
342
  //#endregion
343
+ //#region src/core/productTags.d.ts
344
+ /**
345
+ * Turns a tag list from the API into clean strings: trims each tag, drops
346
+ * blanks and anything that isn't text, and removes exact duplicates (first one
347
+ * wins). The API's own order is kept. A map is accepted too (its values are
348
+ * used), in case the API ever answers keyed by id.
349
+ */
350
+ declare function normalizeTagList(value: unknown): string[];
351
+ /**
352
+ * Every distinct tag used on the merchant's products (`GET /product/tags`),
353
+ * for a tag field's suggestions. Returns `[]` when there are none.
354
+ */
355
+ declare function fetchProductTags(options?: RequestOptions): Promise<string[]>;
356
+ /**
357
+ * Every distinct tag used on the merchant's price instances
358
+ * (`GET /product/instance/tags`): the channel names (Eat In, Takeout, …).
359
+ * Returns `[]` when there are none.
360
+ */
361
+ declare function fetchProductInstanceTags(options?: RequestOptions): Promise<string[]>;
362
+ //#endregion
343
363
  //#region src/core/promotion.d.ts
344
364
  /** Promotion rule identifiers as stored by the Shopwave API. */
345
365
  declare enum PromotionRuleSet {
@@ -537,8 +557,9 @@ declare function submitEntity<R = any>({
537
557
  //#region src/core/entities.d.ts
538
558
  /**
539
559
  * How each Shopwave entity is addressed, shared by the client functions below
540
- * and the server route handlers in `react-shopwave-connect/next`, so the two
541
- * halves of the contract can't drift apart.
560
+ * and the server route handlers in `react-shopwave-connect/server` (wrapped with
561
+ * the session by `react-shopwave-connect/next`), so the two halves of the
562
+ * contract can't drift apart.
542
563
  */
543
564
  interface EntityDefinition {
544
565
  /** App route segment: `/api/<route>` and `/api/<route>/<id>`. */
@@ -655,6 +676,9 @@ declare function fetchEntityById<K extends EntityKind>(kind: K, id: EntityId, pa
655
676
  * read) so an edited price is sent as a new instance. As a safeguard, a new
656
677
  * product (no `id`, e.g. a duplicate) never sends instance ids: an id copied from
657
678
  * another product would otherwise point the save at that product's instances.
679
+ *
680
+ * `images` is sent as file names ({@link toStoredProductImages}), so the URLs a
681
+ * read returns can be passed straight back; leaving `images` out keeps them.
658
682
  */
659
683
  declare const saveProduct: (product: ProductSaveInput, options?: RequestOptions) => Promise<Saved<Product>>;
660
684
  declare const deleteProduct: (id: EntityId, options?: RequestOptions) => Promise<void>;
@@ -790,7 +814,7 @@ declare function buildConsumerMap(consumers: Consumer[] | null | undefined): {
790
814
  *
791
815
  * Like `SHOPWAVE_ENTITIES`, this table is shared by the client functions
792
816
  * (`fetchMerchant`, `fetchUser`, `uploadImage`, …) and the server route
793
- * handlers in `react-shopwave-connect/next`, so the two halves of the contract
817
+ * handlers in `react-shopwave-connect/server`, so the two halves of the contract
794
818
  * can't drift apart. These aren't in `SHOPWAVE_ENTITIES` because they aren't
795
819
  * keyed collections: `GET /merchant` answers `{ merchant: {…} }`, not a map by id.
796
820
  */
@@ -823,20 +847,69 @@ declare const SHOPWAVE_RESOURCES: Readonly<Record<ResourceKind, ResourceDefiniti
823
847
  type UploadKind = "merchant" | "merchantFeature" | "product" | "user" | "applicationLogo" | "applicationImages";
824
848
  /** `UploadKind` → the API's `contentType` value. */
825
849
  declare const UPLOAD_KINDS: Readonly<Record<UploadKind, string>>;
850
+ /**
851
+ * The role an image plays, sent to Shopwave as the uploader's `prefix` header.
852
+ * The uploader names the file `<prefix>_<hash>.<ext>`, so the role travels with
853
+ * the file wherever a record stores it (a product's `images`). Live, merchant
854
+ * 5644, 4 Nov 2026: all four values answered 201.
855
+ * - `product`: a product gallery image;
856
+ * - `product_thumbnail`: the product's lead image, shown in lists;
857
+ * - `variant` / `variant_thumbnail`: a variant's own image and its lead image
858
+ * (used by the Connect integrations).
859
+ *
860
+ * Values are the ones Connect's `uploadFileToShopwave` sends.
861
+ */
862
+ type UploadPrefix = "product" | "product_thumbnail" | "variant" | "variant_thumbnail";
863
+ /** Every `UploadPrefix`, longest first so a name check never takes `product` for `product_thumbnail`. */
864
+ declare const UPLOAD_PREFIXES: ReadonlyArray<UploadPrefix>;
826
865
  /** How uploads are addressed (app route and Shopwave uploader). */
827
866
  declare const SHOPWAVE_UPLOAD: Readonly<{
828
- /** App route: `POST /api/<route>` (multipart `file` + `kind`). */
867
+ /** App route: `POST /api/<route>` (multipart `file` + `kind`, optional `prefix`). */
829
868
  route: "upload";
830
869
  /** Shopwave path: `PUT {apiUrl}/uploader` (multipart `file`). */
831
870
  upstream: "uploader";
832
871
  /** Header that carries the upload kind upstream. */
833
872
  kindHeader: "contentType";
873
+ /** Header that carries the image role upstream (see `UploadPrefix`). */
874
+ prefixHeader: "prefix";
834
875
  /** Multipart field name for the file, on both sides. */
835
876
  fileField: "file";
836
877
  /** Multipart field name for the kind in the app request. */
837
878
  kindField: "kind";
879
+ /** Multipart field name for the image role in the app request. */
880
+ prefixField: "prefix";
838
881
  }>;
839
882
  declare function isUploadKind(value: unknown): value is UploadKind;
883
+ declare function isUploadPrefix(value: unknown): value is UploadPrefix;
884
+ /**
885
+ * Read-only lists that aren't records: the merchant's distinct tags.
886
+ *
887
+ * Like `SHOPWAVE_RESOURCES`, shared by the client functions
888
+ * (`fetchProductTags`, `fetchProductInstanceTags`) and the server route
889
+ * handlers (`shopwave.lookup(kind)`), so the two halves can't drift apart.
890
+ *
891
+ * - productTags: `GET /product/tags` → `{ tags: string[] }`, every distinct tag
892
+ * on the merchant's products. No parameters. The API reference says
893
+ * "internal SKU tags are excluded", but the live API includes system tags
894
+ * written by imports and syncs (`PID-133`, `VID-137`, `#Hash:…`, `upc-…`;
895
+ * test merchant 5644, 29 Oct 2026). Apps that offer the list as suggestions
896
+ * filter those themselves. Tags of deleted products drop out of the list.
897
+ * - productInstanceTags: `GET /product/instance/tags` → `{ tags: string[] }`,
898
+ * the same for price instances (channels such as "Eat In", "Takeout").
899
+ *
900
+ * The app route for instance tags is `products/instance-tags`, one segment
901
+ * under `products`, so it sits beside `products/[id]` without nesting deeper.
902
+ */
903
+ interface LookupDefinition {
904
+ /** App route: `/api/<route>`. */
905
+ route: string;
906
+ /** Key of the list in the response (`{ tags: [...] }`). */
907
+ key: string;
908
+ /** Shopwave API path. */
909
+ upstream: string;
910
+ }
911
+ type LookupKind = "productTags" | "productInstanceTags";
912
+ declare const SHOPWAVE_LOOKUPS: Readonly<Record<LookupKind, LookupDefinition>>;
840
913
  //#endregion
841
914
  //#region src/core/imageFit.d.ts
842
915
  /**
@@ -883,6 +956,12 @@ declare function fitImageToSize(file: Blob, width: number, height: number, optio
883
956
  interface UploadImageParams {
884
957
  /** What the image is for (sent to Shopwave as the uploader's `contentType`). */
885
958
  kind: UploadKind;
959
+ /**
960
+ * The image's role (sent to Shopwave as the uploader's `prefix` header), e.g.
961
+ * `product_thumbnail` for a product's lead image. Leave it out for images
962
+ * without a role (merchant logos).
963
+ */
964
+ prefix?: UploadPrefix;
886
965
  /** File name to send when `file` is a Blob without one. Defaults to `File.name`, else `"upload"`. */
887
966
  fileName?: string;
888
967
  }
@@ -1174,5 +1253,30 @@ interface UserResponse {
1174
1253
  /** Reads the logged-in user, or `null` when the API returns none. */
1175
1254
  declare function fetchUser(options?: RequestOptions): Promise<User | null>;
1176
1255
  //#endregion
1177
- export { Basket, BasketFilters, BasketItem, BasketPagination, BasketReportRow, BasketSummary, Category, CategoryResponse, CombineBasketRowsParams, Consumer, ConsumerResponse, CropRect, DEFAULT_BASKET_FILTERS, DEFAULT_PAGINATION, DeletableEntityKind, Employee, EmployeeResponse, EntityDefinition, EntityId, EntityInput, EntityKind, EntityTypes, ErrorMessage, Extras, FetchByIdParams, FetchCategoriesParams, FetchEmployeesParams, FetchProductsParams, FetchPromotionsParams, FetchStoresParams, FitImageOptions, ImageSize, MERCHANT_COLOUR_KEYS, MERCHANT_FIELD_MAX_LENGTH, MERCHANT_IMAGE_SLOTS, MERCHANT_IMAGE_SLOT_KEYS, MERCHANT_LINK_KEYS, MERCHANT_LINK_PATHS, MERCHANT_OBJECT_FIELDS, MERCHANT_READ_ONLY_FIELDS, Merchant, MerchantColourKey, MerchantColourSet, MerchantColours, MerchantImageIds, MerchantImageSlot, MerchantImageSlotDefinition, MerchantLinkKey, MerchantLinks, MerchantPatch, MerchantResponse, MessageInfo, ParsedBasket, Product, ProductInstance, ProductInstanceInput, ProductInstances, ProductResponse, ProductSaveInput, Promotion, PromotionResponse, PromotionRuleSet, ReportData, ReportKey, ReportQuery, ReportQueryMap, ReportResponse, RepricedInstance, RequestOptions, ResourceDefinition, ResourceKind, SHOPWAVE_ENTITIES, SHOPWAVE_IMAGE_BASE_URL, SHOPWAVE_RESOURCES, SHOPWAVE_UPLOAD, Saved, SessionStatus, ShopwaveApiError, ShopwaveErrorMap, Store, StoreResponse, SubmitEntityArgs, SubmitEntityResponse, SuccessMessage, UPLOAD_KINDS, UpdateMerchantOptions, UploadImageParams, UploadKind, UploadMerchantImageOptions, UploadedImage, User, UserEmployee, UserResponse, WritableEntityKind, apiDelete, apiGet, apiRequest, apiResponse, apiSend, assertNoApiErrors, authorizationFor, buildBasketReportQuery, buildConsumerMap, collectConsumerIds, collectProductIds, combineBasketRows, computeBasketSummary, coverCrop, deleteCategory, deleteEmployee, deleteEntity, deleteEntityById, deleteProduct, deletePromotion, deleteStore, fetchCategories, fetchCategory, fetchConsumer, fetchConsumers, fetchEmployee, fetchEmployees, fetchEntityById, fetchMerchant, fetchProduct, fetchProducts, fetchProductsMap, fetchPromotion, fetchPromotions, fetchReport, fetchSession, fetchStore, fetchStores, fetchUser, findRepricedInstances, fitImageToSize, formatDateForQuery, getApiErrorMap, getApiErrors, getImageUrl, getMerchantImage, getMerchantImageUrl, imageFileName, isSameInstancePrice, isUploadKind, loginPath, logout, logoutPath, merchantLinksFromForm, merchantLinksToForm, normalizeMerchantLinks, parseBasketReportData, readImageSize, rolesById, saveCategory, saveEmployee, saveEntities, saveEntity, saveProduct, savePromotion, saveStore, setMerchantImage, submitEntity, toProductInstancesForSave, toShopwaveApiError, toStoredImageIds, updateMerchant, uploadImage, uploadMerchantImage, validateMerchant, withToken };
1256
+ //#region src/core/productImages.d.ts
1257
+ /**
1258
+ * Product images, as the live API stores them (merchant 5644, 4 Nov 2026):
1259
+ * - A product's `images` is a list. **Reads return full URLs**
1260
+ * (`http://static.merchantstack.com/images/merchant/<id>/product/<file>`);
1261
+ * **writes take the uploader's file names** ({@link toStoredProductImages};
1262
+ * `saveProduct` does this for you).
1263
+ * - The uploader takes one file per request. With a `prefix` (see
1264
+ * `UploadPrefix`) it names the file `<prefix>_<hash>.<ext>`
1265
+ * (`product_thumbnail_1bdd…41090b.png`); without one, `<hash>.<ext>`. So an
1266
+ * image's role can be read back from its name ({@link productImageRole}).
1267
+ */
1268
+ /**
1269
+ * The role in an image's file name or URL, from the uploader's `prefix`:
1270
+ * `"…/product_thumbnail_1bdd.png"` → `"product_thumbnail"`. `null` for a name
1271
+ * without one (images uploaded without a prefix, e.g. before prefixes existed).
1272
+ */
1273
+ declare function productImageRole(value: unknown): UploadPrefix | null;
1274
+ /**
1275
+ * A product's `images` as the API takes them on a save: file names, not the
1276
+ * URLs a read returns. Non-strings, blanks and duplicates are dropped; the
1277
+ * order is kept.
1278
+ */
1279
+ declare function toStoredProductImages(images: unknown): string[];
1280
+ //#endregion
1281
+ export { Basket, BasketFilters, BasketItem, BasketPagination, BasketReportRow, BasketSummary, Category, CategoryResponse, CombineBasketRowsParams, Consumer, ConsumerResponse, CropRect, DEFAULT_BASKET_FILTERS, DEFAULT_PAGINATION, DeletableEntityKind, Employee, EmployeeResponse, EntityDefinition, EntityId, EntityInput, EntityKind, EntityTypes, ErrorMessage, Extras, FetchByIdParams, FetchCategoriesParams, FetchEmployeesParams, FetchProductsParams, FetchPromotionsParams, FetchStoresParams, FitImageOptions, ImageSize, LookupDefinition, LookupKind, MERCHANT_COLOUR_KEYS, MERCHANT_FIELD_MAX_LENGTH, MERCHANT_IMAGE_SLOTS, MERCHANT_IMAGE_SLOT_KEYS, MERCHANT_LINK_KEYS, MERCHANT_LINK_PATHS, MERCHANT_OBJECT_FIELDS, MERCHANT_READ_ONLY_FIELDS, Merchant, MerchantColourKey, MerchantColourSet, MerchantColours, MerchantImageIds, MerchantImageSlot, MerchantImageSlotDefinition, MerchantLinkKey, MerchantLinks, MerchantPatch, MerchantResponse, MessageInfo, ParsedBasket, Product, ProductInstance, ProductInstanceInput, ProductInstances, ProductResponse, ProductSaveInput, Promotion, PromotionResponse, PromotionRuleSet, ReportData, ReportKey, ReportQuery, ReportQueryMap, ReportResponse, RepricedInstance, RequestOptions, ResourceDefinition, ResourceKind, SHOPWAVE_ENTITIES, SHOPWAVE_IMAGE_BASE_URL, SHOPWAVE_LOOKUPS, SHOPWAVE_RESOURCES, SHOPWAVE_UPLOAD, Saved, SessionStatus, ShopwaveApiError, ShopwaveErrorMap, Store, StoreResponse, SubmitEntityArgs, SubmitEntityResponse, SuccessMessage, UPLOAD_KINDS, UPLOAD_PREFIXES, UpdateMerchantOptions, UploadImageParams, UploadKind, UploadMerchantImageOptions, UploadPrefix, UploadedImage, User, UserEmployee, UserResponse, WritableEntityKind, apiDelete, apiGet, apiRequest, apiResponse, apiSend, assertNoApiErrors, authorizationFor, buildBasketReportQuery, buildConsumerMap, collectConsumerIds, collectProductIds, combineBasketRows, computeBasketSummary, coverCrop, deleteCategory, deleteEmployee, deleteEntity, deleteEntityById, deleteProduct, deletePromotion, deleteStore, fetchCategories, fetchCategory, fetchConsumer, fetchConsumers, fetchEmployee, fetchEmployees, fetchEntityById, fetchMerchant, fetchProduct, fetchProductInstanceTags, fetchProductTags, fetchProducts, fetchProductsMap, fetchPromotion, fetchPromotions, fetchReport, fetchSession, fetchStore, fetchStores, fetchUser, findRepricedInstances, fitImageToSize, formatDateForQuery, getApiErrorMap, getApiErrors, getImageUrl, getMerchantImage, getMerchantImageUrl, imageFileName, isSameInstancePrice, isUploadKind, isUploadPrefix, loginPath, logout, logoutPath, merchantLinksFromForm, merchantLinksToForm, normalizeMerchantLinks, normalizeTagList, parseBasketReportData, productImageRole, readImageSize, rolesById, saveCategory, saveEmployee, saveEntities, saveEntity, saveProduct, savePromotion, saveStore, setMerchantImage, submitEntity, toProductInstancesForSave, toShopwaveApiError, toStoredImageIds, toStoredProductImages, updateMerchant, uploadImage, uploadMerchantImage, validateMerchant, withToken };
1178
1282
  //# sourceMappingURL=index.d.cts.map
@@ -340,6 +340,26 @@ declare function fetchProductsMap(productIds: number[] | null | undefined, optio
340
340
  [id: number]: Product;
341
341
  }>;
342
342
  //#endregion
343
+ //#region src/core/productTags.d.ts
344
+ /**
345
+ * Turns a tag list from the API into clean strings: trims each tag, drops
346
+ * blanks and anything that isn't text, and removes exact duplicates (first one
347
+ * wins). The API's own order is kept. A map is accepted too (its values are
348
+ * used), in case the API ever answers keyed by id.
349
+ */
350
+ declare function normalizeTagList(value: unknown): string[];
351
+ /**
352
+ * Every distinct tag used on the merchant's products (`GET /product/tags`),
353
+ * for a tag field's suggestions. Returns `[]` when there are none.
354
+ */
355
+ declare function fetchProductTags(options?: RequestOptions): Promise<string[]>;
356
+ /**
357
+ * Every distinct tag used on the merchant's price instances
358
+ * (`GET /product/instance/tags`): the channel names (Eat In, Takeout, …).
359
+ * Returns `[]` when there are none.
360
+ */
361
+ declare function fetchProductInstanceTags(options?: RequestOptions): Promise<string[]>;
362
+ //#endregion
343
363
  //#region src/core/promotion.d.ts
344
364
  /** Promotion rule identifiers as stored by the Shopwave API. */
345
365
  declare enum PromotionRuleSet {
@@ -537,8 +557,9 @@ declare function submitEntity<R = any>({
537
557
  //#region src/core/entities.d.ts
538
558
  /**
539
559
  * How each Shopwave entity is addressed, shared by the client functions below
540
- * and the server route handlers in `react-shopwave-connect/next`, so the two
541
- * halves of the contract can't drift apart.
560
+ * and the server route handlers in `react-shopwave-connect/server` (wrapped with
561
+ * the session by `react-shopwave-connect/next`), so the two halves of the
562
+ * contract can't drift apart.
542
563
  */
543
564
  interface EntityDefinition {
544
565
  /** App route segment: `/api/<route>` and `/api/<route>/<id>`. */
@@ -655,6 +676,9 @@ declare function fetchEntityById<K extends EntityKind>(kind: K, id: EntityId, pa
655
676
  * read) so an edited price is sent as a new instance. As a safeguard, a new
656
677
  * product (no `id`, e.g. a duplicate) never sends instance ids: an id copied from
657
678
  * another product would otherwise point the save at that product's instances.
679
+ *
680
+ * `images` is sent as file names ({@link toStoredProductImages}), so the URLs a
681
+ * read returns can be passed straight back; leaving `images` out keeps them.
658
682
  */
659
683
  declare const saveProduct: (product: ProductSaveInput, options?: RequestOptions) => Promise<Saved<Product>>;
660
684
  declare const deleteProduct: (id: EntityId, options?: RequestOptions) => Promise<void>;
@@ -790,7 +814,7 @@ declare function buildConsumerMap(consumers: Consumer[] | null | undefined): {
790
814
  *
791
815
  * Like `SHOPWAVE_ENTITIES`, this table is shared by the client functions
792
816
  * (`fetchMerchant`, `fetchUser`, `uploadImage`, …) and the server route
793
- * handlers in `react-shopwave-connect/next`, so the two halves of the contract
817
+ * handlers in `react-shopwave-connect/server`, so the two halves of the contract
794
818
  * can't drift apart. These aren't in `SHOPWAVE_ENTITIES` because they aren't
795
819
  * keyed collections: `GET /merchant` answers `{ merchant: {…} }`, not a map by id.
796
820
  */
@@ -823,20 +847,69 @@ declare const SHOPWAVE_RESOURCES: Readonly<Record<ResourceKind, ResourceDefiniti
823
847
  type UploadKind = "merchant" | "merchantFeature" | "product" | "user" | "applicationLogo" | "applicationImages";
824
848
  /** `UploadKind` → the API's `contentType` value. */
825
849
  declare const UPLOAD_KINDS: Readonly<Record<UploadKind, string>>;
850
+ /**
851
+ * The role an image plays, sent to Shopwave as the uploader's `prefix` header.
852
+ * The uploader names the file `<prefix>_<hash>.<ext>`, so the role travels with
853
+ * the file wherever a record stores it (a product's `images`). Live, merchant
854
+ * 5644, 4 Nov 2026: all four values answered 201.
855
+ * - `product`: a product gallery image;
856
+ * - `product_thumbnail`: the product's lead image, shown in lists;
857
+ * - `variant` / `variant_thumbnail`: a variant's own image and its lead image
858
+ * (used by the Connect integrations).
859
+ *
860
+ * Values are the ones Connect's `uploadFileToShopwave` sends.
861
+ */
862
+ type UploadPrefix = "product" | "product_thumbnail" | "variant" | "variant_thumbnail";
863
+ /** Every `UploadPrefix`, longest first so a name check never takes `product` for `product_thumbnail`. */
864
+ declare const UPLOAD_PREFIXES: ReadonlyArray<UploadPrefix>;
826
865
  /** How uploads are addressed (app route and Shopwave uploader). */
827
866
  declare const SHOPWAVE_UPLOAD: Readonly<{
828
- /** App route: `POST /api/<route>` (multipart `file` + `kind`). */
867
+ /** App route: `POST /api/<route>` (multipart `file` + `kind`, optional `prefix`). */
829
868
  route: "upload";
830
869
  /** Shopwave path: `PUT {apiUrl}/uploader` (multipart `file`). */
831
870
  upstream: "uploader";
832
871
  /** Header that carries the upload kind upstream. */
833
872
  kindHeader: "contentType";
873
+ /** Header that carries the image role upstream (see `UploadPrefix`). */
874
+ prefixHeader: "prefix";
834
875
  /** Multipart field name for the file, on both sides. */
835
876
  fileField: "file";
836
877
  /** Multipart field name for the kind in the app request. */
837
878
  kindField: "kind";
879
+ /** Multipart field name for the image role in the app request. */
880
+ prefixField: "prefix";
838
881
  }>;
839
882
  declare function isUploadKind(value: unknown): value is UploadKind;
883
+ declare function isUploadPrefix(value: unknown): value is UploadPrefix;
884
+ /**
885
+ * Read-only lists that aren't records: the merchant's distinct tags.
886
+ *
887
+ * Like `SHOPWAVE_RESOURCES`, shared by the client functions
888
+ * (`fetchProductTags`, `fetchProductInstanceTags`) and the server route
889
+ * handlers (`shopwave.lookup(kind)`), so the two halves can't drift apart.
890
+ *
891
+ * - productTags: `GET /product/tags` → `{ tags: string[] }`, every distinct tag
892
+ * on the merchant's products. No parameters. The API reference says
893
+ * "internal SKU tags are excluded", but the live API includes system tags
894
+ * written by imports and syncs (`PID-133`, `VID-137`, `#Hash:…`, `upc-…`;
895
+ * test merchant 5644, 29 Oct 2026). Apps that offer the list as suggestions
896
+ * filter those themselves. Tags of deleted products drop out of the list.
897
+ * - productInstanceTags: `GET /product/instance/tags` → `{ tags: string[] }`,
898
+ * the same for price instances (channels such as "Eat In", "Takeout").
899
+ *
900
+ * The app route for instance tags is `products/instance-tags`, one segment
901
+ * under `products`, so it sits beside `products/[id]` without nesting deeper.
902
+ */
903
+ interface LookupDefinition {
904
+ /** App route: `/api/<route>`. */
905
+ route: string;
906
+ /** Key of the list in the response (`{ tags: [...] }`). */
907
+ key: string;
908
+ /** Shopwave API path. */
909
+ upstream: string;
910
+ }
911
+ type LookupKind = "productTags" | "productInstanceTags";
912
+ declare const SHOPWAVE_LOOKUPS: Readonly<Record<LookupKind, LookupDefinition>>;
840
913
  //#endregion
841
914
  //#region src/core/imageFit.d.ts
842
915
  /**
@@ -883,6 +956,12 @@ declare function fitImageToSize(file: Blob, width: number, height: number, optio
883
956
  interface UploadImageParams {
884
957
  /** What the image is for (sent to Shopwave as the uploader's `contentType`). */
885
958
  kind: UploadKind;
959
+ /**
960
+ * The image's role (sent to Shopwave as the uploader's `prefix` header), e.g.
961
+ * `product_thumbnail` for a product's lead image. Leave it out for images
962
+ * without a role (merchant logos).
963
+ */
964
+ prefix?: UploadPrefix;
886
965
  /** File name to send when `file` is a Blob without one. Defaults to `File.name`, else `"upload"`. */
887
966
  fileName?: string;
888
967
  }
@@ -1174,5 +1253,30 @@ interface UserResponse {
1174
1253
  /** Reads the logged-in user, or `null` when the API returns none. */
1175
1254
  declare function fetchUser(options?: RequestOptions): Promise<User | null>;
1176
1255
  //#endregion
1177
- export { Basket, BasketFilters, BasketItem, BasketPagination, BasketReportRow, BasketSummary, Category, CategoryResponse, CombineBasketRowsParams, Consumer, ConsumerResponse, CropRect, DEFAULT_BASKET_FILTERS, DEFAULT_PAGINATION, DeletableEntityKind, Employee, EmployeeResponse, EntityDefinition, EntityId, EntityInput, EntityKind, EntityTypes, ErrorMessage, Extras, FetchByIdParams, FetchCategoriesParams, FetchEmployeesParams, FetchProductsParams, FetchPromotionsParams, FetchStoresParams, FitImageOptions, ImageSize, MERCHANT_COLOUR_KEYS, MERCHANT_FIELD_MAX_LENGTH, MERCHANT_IMAGE_SLOTS, MERCHANT_IMAGE_SLOT_KEYS, MERCHANT_LINK_KEYS, MERCHANT_LINK_PATHS, MERCHANT_OBJECT_FIELDS, MERCHANT_READ_ONLY_FIELDS, Merchant, MerchantColourKey, MerchantColourSet, MerchantColours, MerchantImageIds, MerchantImageSlot, MerchantImageSlotDefinition, MerchantLinkKey, MerchantLinks, MerchantPatch, MerchantResponse, MessageInfo, ParsedBasket, Product, ProductInstance, ProductInstanceInput, ProductInstances, ProductResponse, ProductSaveInput, Promotion, PromotionResponse, PromotionRuleSet, ReportData, ReportKey, ReportQuery, ReportQueryMap, ReportResponse, RepricedInstance, RequestOptions, ResourceDefinition, ResourceKind, SHOPWAVE_ENTITIES, SHOPWAVE_IMAGE_BASE_URL, SHOPWAVE_RESOURCES, SHOPWAVE_UPLOAD, Saved, SessionStatus, ShopwaveApiError, ShopwaveErrorMap, Store, StoreResponse, SubmitEntityArgs, SubmitEntityResponse, SuccessMessage, UPLOAD_KINDS, UpdateMerchantOptions, UploadImageParams, UploadKind, UploadMerchantImageOptions, UploadedImage, User, UserEmployee, UserResponse, WritableEntityKind, apiDelete, apiGet, apiRequest, apiResponse, apiSend, assertNoApiErrors, authorizationFor, buildBasketReportQuery, buildConsumerMap, collectConsumerIds, collectProductIds, combineBasketRows, computeBasketSummary, coverCrop, deleteCategory, deleteEmployee, deleteEntity, deleteEntityById, deleteProduct, deletePromotion, deleteStore, fetchCategories, fetchCategory, fetchConsumer, fetchConsumers, fetchEmployee, fetchEmployees, fetchEntityById, fetchMerchant, fetchProduct, fetchProducts, fetchProductsMap, fetchPromotion, fetchPromotions, fetchReport, fetchSession, fetchStore, fetchStores, fetchUser, findRepricedInstances, fitImageToSize, formatDateForQuery, getApiErrorMap, getApiErrors, getImageUrl, getMerchantImage, getMerchantImageUrl, imageFileName, isSameInstancePrice, isUploadKind, loginPath, logout, logoutPath, merchantLinksFromForm, merchantLinksToForm, normalizeMerchantLinks, parseBasketReportData, readImageSize, rolesById, saveCategory, saveEmployee, saveEntities, saveEntity, saveProduct, savePromotion, saveStore, setMerchantImage, submitEntity, toProductInstancesForSave, toShopwaveApiError, toStoredImageIds, updateMerchant, uploadImage, uploadMerchantImage, validateMerchant, withToken };
1256
+ //#region src/core/productImages.d.ts
1257
+ /**
1258
+ * Product images, as the live API stores them (merchant 5644, 4 Nov 2026):
1259
+ * - A product's `images` is a list. **Reads return full URLs**
1260
+ * (`http://static.merchantstack.com/images/merchant/<id>/product/<file>`);
1261
+ * **writes take the uploader's file names** ({@link toStoredProductImages};
1262
+ * `saveProduct` does this for you).
1263
+ * - The uploader takes one file per request. With a `prefix` (see
1264
+ * `UploadPrefix`) it names the file `<prefix>_<hash>.<ext>`
1265
+ * (`product_thumbnail_1bdd…41090b.png`); without one, `<hash>.<ext>`. So an
1266
+ * image's role can be read back from its name ({@link productImageRole}).
1267
+ */
1268
+ /**
1269
+ * The role in an image's file name or URL, from the uploader's `prefix`:
1270
+ * `"…/product_thumbnail_1bdd.png"` → `"product_thumbnail"`. `null` for a name
1271
+ * without one (images uploaded without a prefix, e.g. before prefixes existed).
1272
+ */
1273
+ declare function productImageRole(value: unknown): UploadPrefix | null;
1274
+ /**
1275
+ * A product's `images` as the API takes them on a save: file names, not the
1276
+ * URLs a read returns. Non-strings, blanks and duplicates are dropped; the
1277
+ * order is kept.
1278
+ */
1279
+ declare function toStoredProductImages(images: unknown): string[];
1280
+ //#endregion
1281
+ export { Basket, BasketFilters, BasketItem, BasketPagination, BasketReportRow, BasketSummary, Category, CategoryResponse, CombineBasketRowsParams, Consumer, ConsumerResponse, CropRect, DEFAULT_BASKET_FILTERS, DEFAULT_PAGINATION, DeletableEntityKind, Employee, EmployeeResponse, EntityDefinition, EntityId, EntityInput, EntityKind, EntityTypes, ErrorMessage, Extras, FetchByIdParams, FetchCategoriesParams, FetchEmployeesParams, FetchProductsParams, FetchPromotionsParams, FetchStoresParams, FitImageOptions, ImageSize, LookupDefinition, LookupKind, MERCHANT_COLOUR_KEYS, MERCHANT_FIELD_MAX_LENGTH, MERCHANT_IMAGE_SLOTS, MERCHANT_IMAGE_SLOT_KEYS, MERCHANT_LINK_KEYS, MERCHANT_LINK_PATHS, MERCHANT_OBJECT_FIELDS, MERCHANT_READ_ONLY_FIELDS, Merchant, MerchantColourKey, MerchantColourSet, MerchantColours, MerchantImageIds, MerchantImageSlot, MerchantImageSlotDefinition, MerchantLinkKey, MerchantLinks, MerchantPatch, MerchantResponse, MessageInfo, ParsedBasket, Product, ProductInstance, ProductInstanceInput, ProductInstances, ProductResponse, ProductSaveInput, Promotion, PromotionResponse, PromotionRuleSet, ReportData, ReportKey, ReportQuery, ReportQueryMap, ReportResponse, RepricedInstance, RequestOptions, ResourceDefinition, ResourceKind, SHOPWAVE_ENTITIES, SHOPWAVE_IMAGE_BASE_URL, SHOPWAVE_LOOKUPS, SHOPWAVE_RESOURCES, SHOPWAVE_UPLOAD, Saved, SessionStatus, ShopwaveApiError, ShopwaveErrorMap, Store, StoreResponse, SubmitEntityArgs, SubmitEntityResponse, SuccessMessage, UPLOAD_KINDS, UPLOAD_PREFIXES, UpdateMerchantOptions, UploadImageParams, UploadKind, UploadMerchantImageOptions, UploadPrefix, UploadedImage, User, UserEmployee, UserResponse, WritableEntityKind, apiDelete, apiGet, apiRequest, apiResponse, apiSend, assertNoApiErrors, authorizationFor, buildBasketReportQuery, buildConsumerMap, collectConsumerIds, collectProductIds, combineBasketRows, computeBasketSummary, coverCrop, deleteCategory, deleteEmployee, deleteEntity, deleteEntityById, deleteProduct, deletePromotion, deleteStore, fetchCategories, fetchCategory, fetchConsumer, fetchConsumers, fetchEmployee, fetchEmployees, fetchEntityById, fetchMerchant, fetchProduct, fetchProductInstanceTags, fetchProductTags, fetchProducts, fetchProductsMap, fetchPromotion, fetchPromotions, fetchReport, fetchSession, fetchStore, fetchStores, fetchUser, findRepricedInstances, fitImageToSize, formatDateForQuery, getApiErrorMap, getApiErrors, getImageUrl, getMerchantImage, getMerchantImageUrl, imageFileName, isSameInstancePrice, isUploadKind, isUploadPrefix, loginPath, logout, logoutPath, merchantLinksFromForm, merchantLinksToForm, normalizeMerchantLinks, normalizeTagList, parseBasketReportData, productImageRole, readImageSize, rolesById, saveCategory, saveEmployee, saveEntities, saveEntity, saveProduct, savePromotion, saveStore, setMerchantImage, submitEntity, toProductInstancesForSave, toShopwaveApiError, toStoredImageIds, toStoredProductImages, updateMerchant, uploadImage, uploadMerchantImage, validateMerchant, withToken };
1178
1282
  //# sourceMappingURL=index.d.ts.map