react-shopwave-connect 0.4.4 → 0.4.6

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.
@@ -850,8 +850,8 @@ declare const UPLOAD_KINDS: Readonly<Record<UploadKind, string>>;
850
850
  /**
851
851
  * The role an image plays, sent to Shopwave as the uploader's `prefix` header.
852
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.
853
+ * the file wherever a record stores it (a product's `images`). Live, test
854
+ * merchant, 4 Nov 2026: all four values answered 201.
855
855
  * - `product`: a product gallery image;
856
856
  * - `product_thumbnail`: the product's lead image, shown in lists;
857
857
  * - `variant` / `variant_thumbnail`: a variant's own image and its lead image
@@ -892,7 +892,7 @@ declare function isUploadPrefix(value: unknown): value is UploadPrefix;
892
892
  * on the merchant's products. No parameters. The API reference says
893
893
  * "internal SKU tags are excluded", but the live API includes system tags
894
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
895
+ * a test merchant, 29 Oct 2026). Apps that offer the list as suggestions
896
896
  * filter those themselves. Tags of deleted products drop out of the list.
897
897
  * - productInstanceTags: `GET /product/instance/tags` → `{ tags: string[] }`,
898
898
  * the same for price instances (channels such as "Eat In", "Takeout").
@@ -913,11 +913,12 @@ declare const SHOPWAVE_LOOKUPS: Readonly<Record<LookupKind, LookupDefinition>>;
913
913
  //#endregion
914
914
  //#region src/core/imageFit.d.ts
915
915
  /**
916
- * Browser helpers for getting an image to an exact pixel size before upload.
916
+ * Browser helpers for getting an image to the right size before upload.
917
917
  *
918
- * Shopwave doesn't resize uploads, and the merchant image slots have fixed
919
- * sizes (adminV1 refuses any other size), so the SDK scales and centre-crops
920
- * the image in the browser instead.
918
+ * Shopwave doesn't resize uploads, so images are scaled and centre-cropped in
919
+ * the browser: to an exact size for the merchant image slots
920
+ * ({@link fitImageToSize}), or to a rule (ratio, minimum, maximum) with
921
+ * {@link prepareImage}, which apps use to give each kind of image its own rule.
921
922
  */
922
923
  /** Source rectangle to draw so the image covers `dstWidth × dstHeight` (centre crop, no stretching). */
923
924
  interface CropRect {
@@ -951,6 +952,102 @@ interface FitImageOptions {
951
952
  * input, with the output type's extension.
952
953
  */
953
954
  declare function fitImageToSize(file: Blob, width: number, height: number, options?: FitImageOptions): Promise<File>;
955
+ /**
956
+ * How an image must end up before upload. Every field is optional; give an
957
+ * exact size (`width` + `height`) or an `aspectRatio`, not both.
958
+ *
959
+ * Images are always scaled down first and then centre-cropped (never
960
+ * stretched): the kept area is the largest one with the right shape.
961
+ *
962
+ * @example
963
+ * // "Cropped to 100:77, at least 600 × 462", at most 2000 px on the long side
964
+ * { aspectRatio: "100:77", minWidth: 600, minHeight: 462, maxLongSide: 2000 }
965
+ * // Exactly 600 × 462
966
+ * { width: 600, height: 462 }
967
+ * // Any shape, scaled down to fit 2000 px
968
+ * { maxLongSide: 2000 }
969
+ */
970
+ interface ImageRule {
971
+ /** Exact output width (needs `height`). */
972
+ width?: number;
973
+ /** Exact output height (needs `width`). */
974
+ height?: number;
975
+ /** Shape to crop to: `1.3`, `"100:77"`, `"100/77"` or `[100, 77]`. */
976
+ aspectRatio?: number | string | readonly [number, number];
977
+ /** Smallest acceptable output; a smaller image is refused (see `allowUpscale`). */
978
+ minWidth?: number;
979
+ minHeight?: number;
980
+ /** Largest output; a bigger image is scaled down to fit. */
981
+ maxWidth?: number;
982
+ maxHeight?: number;
983
+ /** Largest output on the longer side, whichever it is. */
984
+ maxLongSide?: number;
985
+ /** Enlarge a too-small image instead of refusing it. Default false. */
986
+ allowUpscale?: boolean;
987
+ }
988
+ /** What {@link prepareImage} will do to an image, worked out without touching it. */
989
+ interface ImageFitPlan {
990
+ /** The area of the source that's kept. */
991
+ crop: CropRect;
992
+ /** Output size. */
993
+ width: number;
994
+ height: number;
995
+ /** True when the source already fits the rule, so it can be uploaded as it is. */
996
+ unchanged: boolean;
997
+ }
998
+ /** A rule that can't be met by any image (a mistake in the rule, not the image). */
999
+ declare class ImageRuleError extends Error {
1000
+ constructor(message: string);
1001
+ }
1002
+ /** The image is smaller than the rule's minimum (and `allowUpscale` is off). */
1003
+ declare class ImageTooSmallError extends Error {
1004
+ /** The smallest size the rule accepts. */
1005
+ readonly required: ImageSize;
1006
+ /** The largest area of the right shape the image could give. */
1007
+ readonly actual: ImageSize;
1008
+ constructor(required: ImageSize, actual: ImageSize);
1009
+ }
1010
+ /**
1011
+ * An aspect ratio as width ÷ height: `"100:77"`, `"100/77"`, `[100, 77]` →
1012
+ * 1.2987…; `1.3` → 1.3. Throws {@link ImageRuleError} for anything else.
1013
+ */
1014
+ declare function parseAspectRatio(value: number | string | readonly [number, number]): number;
1015
+ /** Throws {@link ImageRuleError} when the rule contradicts itself. */
1016
+ declare function checkImageRule(rule: ImageRule): void;
1017
+ /**
1018
+ * Works out what to do to a `source`-sized image to meet `rule`: the centred
1019
+ * crop of the right shape (the largest one), then the output size (scaled
1020
+ * down to the maximum, never below the minimum). Pure: no browser needed.
1021
+ *
1022
+ * Throws {@link ImageTooSmallError} when the crop is below the minimum (or
1023
+ * the exact size) and `allowUpscale` is off, and {@link ImageRuleError} for a
1024
+ * contradictory rule.
1025
+ *
1026
+ * @example
1027
+ * planImageFit({ width: 6000, height: 4000 }, { aspectRatio: "100:77", minWidth: 600, minHeight: 462, maxLongSide: 2000 })
1028
+ * // → crop { sx: 403, sy: 0, sw: 5194, sh: 4000 }, 2000 × 1540
1029
+ */
1030
+ declare function planImageFit(source: ImageSize, rule: ImageRule): ImageFitPlan;
1031
+ interface PrepareImageOptions {
1032
+ /** Output type. Default: the source's type when it's PNG, JPEG or WebP, else PNG. */
1033
+ type?: "image/png" | "image/jpeg" | "image/webp";
1034
+ /** 0–1, for JPEG and WebP. Default 0.9. */
1035
+ quality?: number;
1036
+ }
1037
+ /**
1038
+ * Returns the image meeting `rule` ({@link planImageFit}): centre-cropped to
1039
+ * the right shape and scaled in a single draw. An image that already fits is
1040
+ * returned untouched (same bytes). Browser only.
1041
+ *
1042
+ * Throws {@link ImageTooSmallError} (show `required` and `actual` to the
1043
+ * person) or {@link ImageRuleError}; an unreadable file rejects with the
1044
+ * browser's decoding error.
1045
+ *
1046
+ * @example
1047
+ * const ready = await prepareImage(file, { aspectRatio: "100:77", minWidth: 600, minHeight: 462, maxLongSide: 2000 });
1048
+ * await uploadImage(ready, { kind: "product", prefix: "product" });
1049
+ */
1050
+ declare function prepareImage(file: Blob, rule: ImageRule, options?: PrepareImageOptions): Promise<File>;
954
1051
  //#endregion
955
1052
  //#region src/core/upload.d.ts
956
1053
  interface UploadImageParams {
@@ -982,7 +1079,7 @@ declare const SHOPWAVE_IMAGE_BASE_URL = "https://s3-eu-west-1.amazonaws.com/stat
982
1079
  /**
983
1080
  * Turns an image path from the API into a URL a page can load over HTTPS:
984
1081
  * `http://static.merchantstack.com/images/x.png` → `<base>/x.png`, and a
985
- * relative path (`merchant/5644/logo/x.png`) → `<base>/merchant/5644/logo/x.png`.
1082
+ * relative path (`merchant/123/logo/x.png`) → `<base>/merchant/123/logo/x.png`.
986
1083
  * Other absolute URLs are returned unchanged; empty input gives `""`.
987
1084
  */
988
1085
  declare function getImageUrl(path: string | null | undefined, base?: string): string;
@@ -998,7 +1095,7 @@ declare function uploadImage(file: Blob, params: UploadImageParams, options?: Re
998
1095
  //#endregion
999
1096
  //#region src/core/merchantImages.d.ts
1000
1097
  /**
1001
- * Merchant images, as adminV1 saves them and adminV2 reads them:
1098
+ * Merchant images, as Shopwave's existing admin apps save and read them:
1002
1099
  *
1003
1100
  * ```
1004
1101
  * { logo: { receipt: "<file>", square: "<file>" }, feature: ["<file>"] }
@@ -1015,7 +1112,7 @@ declare function uploadImage(file: Blob, params: UploadImageParams, options?: Re
1015
1112
  * So a featured image must be uploaded with kind `merchantFeature` (which
1016
1113
  * stores it under `feature/`); a `merchant` upload lands under `logo/`.
1017
1114
  *
1018
- * Confirmed on the live API, merchant 5644, 30 Sep 2026.
1115
+ * Confirmed on the live API, 30 Sep 2026.
1019
1116
  */
1020
1117
  interface MerchantImageIds {
1021
1118
  logo?: {
@@ -1034,12 +1131,12 @@ interface MerchantImageSlotDefinition {
1034
1131
  field: "logo.receipt" | "logo.square" | "feature[0]";
1035
1132
  /** Uploader `contentType` (the featured image has its own). */
1036
1133
  uploadKind: UploadKind;
1037
- /** Exact size in pixels. adminV1 refuses any other size; the API doesn't resize. */
1134
+ /** Exact size in pixels. Shopwave's existing admin refuses any other size; the API doesn't resize. */
1038
1135
  width: number;
1039
1136
  height: number;
1040
1137
  }
1041
1138
  /**
1042
- * Where each slot lives, its upload kind and its exact size (from adminV1's
1139
+ * Where each slot lives, its upload kind and its exact size (from the existing admin's
1043
1140
  * merchant settings page).
1044
1141
  */
1045
1142
  declare const MERCHANT_IMAGE_SLOTS: Readonly<Record<MerchantImageSlot, MerchantImageSlotDefinition>>;
@@ -1064,7 +1161,7 @@ declare function getMerchantImageUrl(imageIds: MerchantImageIds | null | undefin
1064
1161
  declare function setMerchantImage(imageIds: MerchantImageIds | null | undefined, slot: MerchantImageSlot, fileName: string | null): MerchantImageIds;
1065
1162
  /**
1066
1163
  * The `imageIds` to send on a save: every URL is turned back into its file
1067
- * name (what adminV1 does with images you didn't change) and empty values
1164
+ * name (what the existing admin does with images you didn't change) and empty values
1068
1165
  * are dropped. No images gives `{}`.
1069
1166
  */
1070
1167
  declare function toStoredImageIds(imageIds: unknown): MerchantImageIds;
@@ -1093,7 +1190,7 @@ interface MerchantColourSet {
1093
1190
  [key: string]: string | null | undefined;
1094
1191
  }
1095
1192
  /**
1096
- * Brand colours, as adminV1 saves them and adminV2 reads them
1193
+ * Brand colours, as Shopwave's existing admin apps save and read them
1097
1194
  * (`colours.primary.main` is the logo background): `{ primary: { main,
1098
1195
  * highlight, contrast } }`. `{}` when unset. Confirmed live, 30 Sep 2026.
1099
1196
  */
@@ -1105,7 +1202,7 @@ interface MerchantColours {
1105
1202
  declare const MERCHANT_COLOUR_KEYS: readonly ["main", "highlight", "contrast"];
1106
1203
  type MerchantColourKey = (typeof MERCHANT_COLOUR_KEYS)[number];
1107
1204
  /**
1108
- * Web and social links, as adminV1 saves them:
1205
+ * Web and social links, as Shopwave's existing admin saves them:
1109
1206
  * `{ website: { home }, social: { twitter, facebook, instagram } }`.
1110
1207
  * `{}` when empty (confirmed live, 30 Sep 2026). Use {@link normalizeMerchantLinks} to read older shapes and
1111
1208
  * {@link merchantLinksToForm} / {@link merchantLinksFromForm} for flat forms.
@@ -1131,9 +1228,9 @@ declare const MERCHANT_LINK_PATHS: Readonly<Record<MerchantLinkKey, readonly [st
1131
1228
  /**
1132
1229
  * Reads `merchant.links` as flat fields (`{ website, twitter, facebook,
1133
1230
  * instagram }`), whatever shape it was saved in:
1134
- * - the nested shape adminV1 saves (`{ website: { home }, social: { … } }`);
1231
+ * - the nested shape the existing admin saves (`{ website: { home }, social: { … } }`);
1135
1232
  * - flat keys (`{ website: "…" }`, what SDK 0.4.0 pre-releases sent);
1136
- * - an array in {@link MERCHANT_LINK_KEYS} order (older AdminUI versions).
1233
+ * - an array in {@link MERCHANT_LINK_KEYS} order (older app versions).
1137
1234
  * Empty values are dropped.
1138
1235
  */
1139
1236
  declare function merchantLinksToForm(links: unknown): Partial<Record<MerchantLinkKey, string>>;
@@ -1142,7 +1239,7 @@ declare function merchantLinksToForm(links: unknown): Partial<Record<MerchantLin
1142
1239
  * out, and so is a group with nothing in it; no links gives `{}`.
1143
1240
  */
1144
1241
  declare function merchantLinksFromForm(form: Partial<Record<MerchantLinkKey, string | null | undefined>>): MerchantLinks;
1145
- /** Reads any stored or older `links` value into the nested shape adminV1 saves. */
1242
+ /** Reads any stored or older `links` value into the nested shape the existing admin saves. */
1146
1243
  declare function normalizeMerchantLinks(links: unknown): MerchantLinks;
1147
1244
  interface Merchant {
1148
1245
  id: number;
@@ -1255,7 +1352,7 @@ declare function fetchUser(options?: RequestOptions): Promise<User | null>;
1255
1352
  //#endregion
1256
1353
  //#region src/core/productImages.d.ts
1257
1354
  /**
1258
- * Product images, as the live API stores them (merchant 5644, 4 Nov 2026):
1355
+ * Product images, as the live API stores them (4 Nov 2026):
1259
1356
  * - A product's `images` is a list. **Reads return full URLs**
1260
1357
  * (`http://static.merchantstack.com/images/merchant/<id>/product/<file>`);
1261
1358
  * **writes take the uploader's file names** ({@link toStoredProductImages};
@@ -1278,5 +1375,5 @@ declare function productImageRole(value: unknown): UploadPrefix | null;
1278
1375
  */
1279
1376
  declare function toStoredProductImages(images: unknown): string[];
1280
1377
  //#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 };
1378
+ 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, ImageFitPlan, ImageRule, ImageRuleError, ImageSize, ImageTooSmallError, 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, PrepareImageOptions, 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, checkImageRule, 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, parseAspectRatio, parseBasketReportData, planImageFit, prepareImage, productImageRole, readImageSize, rolesById, saveCategory, saveEmployee, saveEntities, saveEntity, saveProduct, savePromotion, saveStore, setMerchantImage, submitEntity, toProductInstancesForSave, toShopwaveApiError, toStoredImageIds, toStoredProductImages, updateMerchant, uploadImage, uploadMerchantImage, validateMerchant, withToken };
1282
1379
  //# sourceMappingURL=index.d.cts.map
@@ -850,8 +850,8 @@ declare const UPLOAD_KINDS: Readonly<Record<UploadKind, string>>;
850
850
  /**
851
851
  * The role an image plays, sent to Shopwave as the uploader's `prefix` header.
852
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.
853
+ * the file wherever a record stores it (a product's `images`). Live, test
854
+ * merchant, 4 Nov 2026: all four values answered 201.
855
855
  * - `product`: a product gallery image;
856
856
  * - `product_thumbnail`: the product's lead image, shown in lists;
857
857
  * - `variant` / `variant_thumbnail`: a variant's own image and its lead image
@@ -892,7 +892,7 @@ declare function isUploadPrefix(value: unknown): value is UploadPrefix;
892
892
  * on the merchant's products. No parameters. The API reference says
893
893
  * "internal SKU tags are excluded", but the live API includes system tags
894
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
895
+ * a test merchant, 29 Oct 2026). Apps that offer the list as suggestions
896
896
  * filter those themselves. Tags of deleted products drop out of the list.
897
897
  * - productInstanceTags: `GET /product/instance/tags` → `{ tags: string[] }`,
898
898
  * the same for price instances (channels such as "Eat In", "Takeout").
@@ -913,11 +913,12 @@ declare const SHOPWAVE_LOOKUPS: Readonly<Record<LookupKind, LookupDefinition>>;
913
913
  //#endregion
914
914
  //#region src/core/imageFit.d.ts
915
915
  /**
916
- * Browser helpers for getting an image to an exact pixel size before upload.
916
+ * Browser helpers for getting an image to the right size before upload.
917
917
  *
918
- * Shopwave doesn't resize uploads, and the merchant image slots have fixed
919
- * sizes (adminV1 refuses any other size), so the SDK scales and centre-crops
920
- * the image in the browser instead.
918
+ * Shopwave doesn't resize uploads, so images are scaled and centre-cropped in
919
+ * the browser: to an exact size for the merchant image slots
920
+ * ({@link fitImageToSize}), or to a rule (ratio, minimum, maximum) with
921
+ * {@link prepareImage}, which apps use to give each kind of image its own rule.
921
922
  */
922
923
  /** Source rectangle to draw so the image covers `dstWidth × dstHeight` (centre crop, no stretching). */
923
924
  interface CropRect {
@@ -951,6 +952,102 @@ interface FitImageOptions {
951
952
  * input, with the output type's extension.
952
953
  */
953
954
  declare function fitImageToSize(file: Blob, width: number, height: number, options?: FitImageOptions): Promise<File>;
955
+ /**
956
+ * How an image must end up before upload. Every field is optional; give an
957
+ * exact size (`width` + `height`) or an `aspectRatio`, not both.
958
+ *
959
+ * Images are always scaled down first and then centre-cropped (never
960
+ * stretched): the kept area is the largest one with the right shape.
961
+ *
962
+ * @example
963
+ * // "Cropped to 100:77, at least 600 × 462", at most 2000 px on the long side
964
+ * { aspectRatio: "100:77", minWidth: 600, minHeight: 462, maxLongSide: 2000 }
965
+ * // Exactly 600 × 462
966
+ * { width: 600, height: 462 }
967
+ * // Any shape, scaled down to fit 2000 px
968
+ * { maxLongSide: 2000 }
969
+ */
970
+ interface ImageRule {
971
+ /** Exact output width (needs `height`). */
972
+ width?: number;
973
+ /** Exact output height (needs `width`). */
974
+ height?: number;
975
+ /** Shape to crop to: `1.3`, `"100:77"`, `"100/77"` or `[100, 77]`. */
976
+ aspectRatio?: number | string | readonly [number, number];
977
+ /** Smallest acceptable output; a smaller image is refused (see `allowUpscale`). */
978
+ minWidth?: number;
979
+ minHeight?: number;
980
+ /** Largest output; a bigger image is scaled down to fit. */
981
+ maxWidth?: number;
982
+ maxHeight?: number;
983
+ /** Largest output on the longer side, whichever it is. */
984
+ maxLongSide?: number;
985
+ /** Enlarge a too-small image instead of refusing it. Default false. */
986
+ allowUpscale?: boolean;
987
+ }
988
+ /** What {@link prepareImage} will do to an image, worked out without touching it. */
989
+ interface ImageFitPlan {
990
+ /** The area of the source that's kept. */
991
+ crop: CropRect;
992
+ /** Output size. */
993
+ width: number;
994
+ height: number;
995
+ /** True when the source already fits the rule, so it can be uploaded as it is. */
996
+ unchanged: boolean;
997
+ }
998
+ /** A rule that can't be met by any image (a mistake in the rule, not the image). */
999
+ declare class ImageRuleError extends Error {
1000
+ constructor(message: string);
1001
+ }
1002
+ /** The image is smaller than the rule's minimum (and `allowUpscale` is off). */
1003
+ declare class ImageTooSmallError extends Error {
1004
+ /** The smallest size the rule accepts. */
1005
+ readonly required: ImageSize;
1006
+ /** The largest area of the right shape the image could give. */
1007
+ readonly actual: ImageSize;
1008
+ constructor(required: ImageSize, actual: ImageSize);
1009
+ }
1010
+ /**
1011
+ * An aspect ratio as width ÷ height: `"100:77"`, `"100/77"`, `[100, 77]` →
1012
+ * 1.2987…; `1.3` → 1.3. Throws {@link ImageRuleError} for anything else.
1013
+ */
1014
+ declare function parseAspectRatio(value: number | string | readonly [number, number]): number;
1015
+ /** Throws {@link ImageRuleError} when the rule contradicts itself. */
1016
+ declare function checkImageRule(rule: ImageRule): void;
1017
+ /**
1018
+ * Works out what to do to a `source`-sized image to meet `rule`: the centred
1019
+ * crop of the right shape (the largest one), then the output size (scaled
1020
+ * down to the maximum, never below the minimum). Pure: no browser needed.
1021
+ *
1022
+ * Throws {@link ImageTooSmallError} when the crop is below the minimum (or
1023
+ * the exact size) and `allowUpscale` is off, and {@link ImageRuleError} for a
1024
+ * contradictory rule.
1025
+ *
1026
+ * @example
1027
+ * planImageFit({ width: 6000, height: 4000 }, { aspectRatio: "100:77", minWidth: 600, minHeight: 462, maxLongSide: 2000 })
1028
+ * // → crop { sx: 403, sy: 0, sw: 5194, sh: 4000 }, 2000 × 1540
1029
+ */
1030
+ declare function planImageFit(source: ImageSize, rule: ImageRule): ImageFitPlan;
1031
+ interface PrepareImageOptions {
1032
+ /** Output type. Default: the source's type when it's PNG, JPEG or WebP, else PNG. */
1033
+ type?: "image/png" | "image/jpeg" | "image/webp";
1034
+ /** 0–1, for JPEG and WebP. Default 0.9. */
1035
+ quality?: number;
1036
+ }
1037
+ /**
1038
+ * Returns the image meeting `rule` ({@link planImageFit}): centre-cropped to
1039
+ * the right shape and scaled in a single draw. An image that already fits is
1040
+ * returned untouched (same bytes). Browser only.
1041
+ *
1042
+ * Throws {@link ImageTooSmallError} (show `required` and `actual` to the
1043
+ * person) or {@link ImageRuleError}; an unreadable file rejects with the
1044
+ * browser's decoding error.
1045
+ *
1046
+ * @example
1047
+ * const ready = await prepareImage(file, { aspectRatio: "100:77", minWidth: 600, minHeight: 462, maxLongSide: 2000 });
1048
+ * await uploadImage(ready, { kind: "product", prefix: "product" });
1049
+ */
1050
+ declare function prepareImage(file: Blob, rule: ImageRule, options?: PrepareImageOptions): Promise<File>;
954
1051
  //#endregion
955
1052
  //#region src/core/upload.d.ts
956
1053
  interface UploadImageParams {
@@ -982,7 +1079,7 @@ declare const SHOPWAVE_IMAGE_BASE_URL = "https://s3-eu-west-1.amazonaws.com/stat
982
1079
  /**
983
1080
  * Turns an image path from the API into a URL a page can load over HTTPS:
984
1081
  * `http://static.merchantstack.com/images/x.png` → `<base>/x.png`, and a
985
- * relative path (`merchant/5644/logo/x.png`) → `<base>/merchant/5644/logo/x.png`.
1082
+ * relative path (`merchant/123/logo/x.png`) → `<base>/merchant/123/logo/x.png`.
986
1083
  * Other absolute URLs are returned unchanged; empty input gives `""`.
987
1084
  */
988
1085
  declare function getImageUrl(path: string | null | undefined, base?: string): string;
@@ -998,7 +1095,7 @@ declare function uploadImage(file: Blob, params: UploadImageParams, options?: Re
998
1095
  //#endregion
999
1096
  //#region src/core/merchantImages.d.ts
1000
1097
  /**
1001
- * Merchant images, as adminV1 saves them and adminV2 reads them:
1098
+ * Merchant images, as Shopwave's existing admin apps save and read them:
1002
1099
  *
1003
1100
  * ```
1004
1101
  * { logo: { receipt: "<file>", square: "<file>" }, feature: ["<file>"] }
@@ -1015,7 +1112,7 @@ declare function uploadImage(file: Blob, params: UploadImageParams, options?: Re
1015
1112
  * So a featured image must be uploaded with kind `merchantFeature` (which
1016
1113
  * stores it under `feature/`); a `merchant` upload lands under `logo/`.
1017
1114
  *
1018
- * Confirmed on the live API, merchant 5644, 30 Sep 2026.
1115
+ * Confirmed on the live API, 30 Sep 2026.
1019
1116
  */
1020
1117
  interface MerchantImageIds {
1021
1118
  logo?: {
@@ -1034,12 +1131,12 @@ interface MerchantImageSlotDefinition {
1034
1131
  field: "logo.receipt" | "logo.square" | "feature[0]";
1035
1132
  /** Uploader `contentType` (the featured image has its own). */
1036
1133
  uploadKind: UploadKind;
1037
- /** Exact size in pixels. adminV1 refuses any other size; the API doesn't resize. */
1134
+ /** Exact size in pixels. Shopwave's existing admin refuses any other size; the API doesn't resize. */
1038
1135
  width: number;
1039
1136
  height: number;
1040
1137
  }
1041
1138
  /**
1042
- * Where each slot lives, its upload kind and its exact size (from adminV1's
1139
+ * Where each slot lives, its upload kind and its exact size (from the existing admin's
1043
1140
  * merchant settings page).
1044
1141
  */
1045
1142
  declare const MERCHANT_IMAGE_SLOTS: Readonly<Record<MerchantImageSlot, MerchantImageSlotDefinition>>;
@@ -1064,7 +1161,7 @@ declare function getMerchantImageUrl(imageIds: MerchantImageIds | null | undefin
1064
1161
  declare function setMerchantImage(imageIds: MerchantImageIds | null | undefined, slot: MerchantImageSlot, fileName: string | null): MerchantImageIds;
1065
1162
  /**
1066
1163
  * The `imageIds` to send on a save: every URL is turned back into its file
1067
- * name (what adminV1 does with images you didn't change) and empty values
1164
+ * name (what the existing admin does with images you didn't change) and empty values
1068
1165
  * are dropped. No images gives `{}`.
1069
1166
  */
1070
1167
  declare function toStoredImageIds(imageIds: unknown): MerchantImageIds;
@@ -1093,7 +1190,7 @@ interface MerchantColourSet {
1093
1190
  [key: string]: string | null | undefined;
1094
1191
  }
1095
1192
  /**
1096
- * Brand colours, as adminV1 saves them and adminV2 reads them
1193
+ * Brand colours, as Shopwave's existing admin apps save and read them
1097
1194
  * (`colours.primary.main` is the logo background): `{ primary: { main,
1098
1195
  * highlight, contrast } }`. `{}` when unset. Confirmed live, 30 Sep 2026.
1099
1196
  */
@@ -1105,7 +1202,7 @@ interface MerchantColours {
1105
1202
  declare const MERCHANT_COLOUR_KEYS: readonly ["main", "highlight", "contrast"];
1106
1203
  type MerchantColourKey = (typeof MERCHANT_COLOUR_KEYS)[number];
1107
1204
  /**
1108
- * Web and social links, as adminV1 saves them:
1205
+ * Web and social links, as Shopwave's existing admin saves them:
1109
1206
  * `{ website: { home }, social: { twitter, facebook, instagram } }`.
1110
1207
  * `{}` when empty (confirmed live, 30 Sep 2026). Use {@link normalizeMerchantLinks} to read older shapes and
1111
1208
  * {@link merchantLinksToForm} / {@link merchantLinksFromForm} for flat forms.
@@ -1131,9 +1228,9 @@ declare const MERCHANT_LINK_PATHS: Readonly<Record<MerchantLinkKey, readonly [st
1131
1228
  /**
1132
1229
  * Reads `merchant.links` as flat fields (`{ website, twitter, facebook,
1133
1230
  * instagram }`), whatever shape it was saved in:
1134
- * - the nested shape adminV1 saves (`{ website: { home }, social: { … } }`);
1231
+ * - the nested shape the existing admin saves (`{ website: { home }, social: { … } }`);
1135
1232
  * - flat keys (`{ website: "…" }`, what SDK 0.4.0 pre-releases sent);
1136
- * - an array in {@link MERCHANT_LINK_KEYS} order (older AdminUI versions).
1233
+ * - an array in {@link MERCHANT_LINK_KEYS} order (older app versions).
1137
1234
  * Empty values are dropped.
1138
1235
  */
1139
1236
  declare function merchantLinksToForm(links: unknown): Partial<Record<MerchantLinkKey, string>>;
@@ -1142,7 +1239,7 @@ declare function merchantLinksToForm(links: unknown): Partial<Record<MerchantLin
1142
1239
  * out, and so is a group with nothing in it; no links gives `{}`.
1143
1240
  */
1144
1241
  declare function merchantLinksFromForm(form: Partial<Record<MerchantLinkKey, string | null | undefined>>): MerchantLinks;
1145
- /** Reads any stored or older `links` value into the nested shape adminV1 saves. */
1242
+ /** Reads any stored or older `links` value into the nested shape the existing admin saves. */
1146
1243
  declare function normalizeMerchantLinks(links: unknown): MerchantLinks;
1147
1244
  interface Merchant {
1148
1245
  id: number;
@@ -1255,7 +1352,7 @@ declare function fetchUser(options?: RequestOptions): Promise<User | null>;
1255
1352
  //#endregion
1256
1353
  //#region src/core/productImages.d.ts
1257
1354
  /**
1258
- * Product images, as the live API stores them (merchant 5644, 4 Nov 2026):
1355
+ * Product images, as the live API stores them (4 Nov 2026):
1259
1356
  * - A product's `images` is a list. **Reads return full URLs**
1260
1357
  * (`http://static.merchantstack.com/images/merchant/<id>/product/<file>`);
1261
1358
  * **writes take the uploader's file names** ({@link toStoredProductImages};
@@ -1278,5 +1375,5 @@ declare function productImageRole(value: unknown): UploadPrefix | null;
1278
1375
  */
1279
1376
  declare function toStoredProductImages(images: unknown): string[];
1280
1377
  //#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 };
1378
+ 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, ImageFitPlan, ImageRule, ImageRuleError, ImageSize, ImageTooSmallError, 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, PrepareImageOptions, 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, checkImageRule, 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, parseAspectRatio, parseBasketReportData, planImageFit, prepareImage, productImageRole, readImageSize, rolesById, saveCategory, saveEmployee, saveEntities, saveEntity, saveProduct, savePromotion, saveStore, setMerchantImage, submitEntity, toProductInstancesForSave, toShopwaveApiError, toStoredImageIds, toStoredProductImages, updateMerchant, uploadImage, uploadMerchantImage, validateMerchant, withToken };
1282
1379
  //# sourceMappingURL=index.d.ts.map