react-shopwave-connect 0.4.2 → 0.4.3

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/dist/index.d.cts CHANGED
@@ -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>`. */
@@ -790,7 +811,7 @@ declare function buildConsumerMap(consumers: Consumer[] | null | undefined): {
790
811
  *
791
812
  * Like `SHOPWAVE_ENTITIES`, this table is shared by the client functions
792
813
  * (`fetchMerchant`, `fetchUser`, `uploadImage`, …) and the server route
793
- * handlers in `react-shopwave-connect/next`, so the two halves of the contract
814
+ * handlers in `react-shopwave-connect/server`, so the two halves of the contract
794
815
  * can't drift apart. These aren't in `SHOPWAVE_ENTITIES` because they aren't
795
816
  * keyed collections: `GET /merchant` answers `{ merchant: {…} }`, not a map by id.
796
817
  */
@@ -837,6 +858,35 @@ declare const SHOPWAVE_UPLOAD: Readonly<{
837
858
  kindField: "kind";
838
859
  }>;
839
860
  declare function isUploadKind(value: unknown): value is UploadKind;
861
+ /**
862
+ * Read-only lists that aren't records: the merchant's distinct tags.
863
+ *
864
+ * Like `SHOPWAVE_RESOURCES`, shared by the client functions
865
+ * (`fetchProductTags`, `fetchProductInstanceTags`) and the server route
866
+ * handlers (`shopwave.lookup(kind)`), so the two halves can't drift apart.
867
+ *
868
+ * - productTags: `GET /product/tags` → `{ tags: string[] }`, every distinct tag
869
+ * on the merchant's products. No parameters. The API reference says
870
+ * "internal SKU tags are excluded", but the live API includes system tags
871
+ * written by imports and syncs (`PID-133`, `VID-137`, `#Hash:…`, `upc-…`;
872
+ * test merchant 5644, 29 Oct 2026). Apps that offer the list as suggestions
873
+ * filter those themselves. Tags of deleted products drop out of the list.
874
+ * - productInstanceTags: `GET /product/instance/tags` → `{ tags: string[] }`,
875
+ * the same for price instances (channels such as "Eat In", "Takeout").
876
+ *
877
+ * The app route for instance tags is `products/instance-tags`, one segment
878
+ * under `products`, so it sits beside `products/[id]` without nesting deeper.
879
+ */
880
+ interface LookupDefinition {
881
+ /** App route: `/api/<route>`. */
882
+ route: string;
883
+ /** Key of the list in the response (`{ tags: [...] }`). */
884
+ key: string;
885
+ /** Shopwave API path. */
886
+ upstream: string;
887
+ }
888
+ type LookupKind = "productTags" | "productInstanceTags";
889
+ declare const SHOPWAVE_LOOKUPS: Readonly<Record<LookupKind, LookupDefinition>>;
840
890
  //#endregion
841
891
  //#region src/core/imageFit.d.ts
842
892
  /**
@@ -1234,6 +1284,26 @@ declare function useEmployee(params?: FetchEmployeesParams, options?: RequestOpt
1234
1284
  */
1235
1285
  declare function useProduct(params?: FetchProductsParams, options?: RequestOptions): QueryState<Product[]>;
1236
1286
  //#endregion
1287
+ //#region src/hooks/useProductTags.d.ts
1288
+ type LookupOptions = RequestOptions & {
1289
+ /** Fetch only when true (e.g. once a tag field is first opened). Defaults to true. */
1290
+ enabled?: boolean;
1291
+ };
1292
+ /**
1293
+ * The merchant's distinct product tags, for a tag field's suggestions.
1294
+ * `data` is `string[]` once loaded.
1295
+ *
1296
+ * @example
1297
+ * const [opened, setOpened] = useState(false);
1298
+ * const { data: tags, loading } = useProductTags({ enabled: opened });
1299
+ */
1300
+ declare function useProductTags(options?: LookupOptions): QueryState<string[]>;
1301
+ /**
1302
+ * The merchant's distinct price-instance (channel) tags: Eat In, Takeout, …
1303
+ * `data` is `string[]` once loaded.
1304
+ */
1305
+ declare function useProductInstanceTags(options?: LookupOptions): QueryState<string[]>;
1306
+ //#endregion
1237
1307
  //#region src/hooks/usePromotion.d.ts
1238
1308
  /**
1239
1309
  * Auto-fetches promotions on mount and whenever the params change.
@@ -1387,5 +1457,5 @@ interface UseBasketReportReturn {
1387
1457
  */
1388
1458
  declare function useBasketReport(options?: RequestOptions): UseBasketReportReturn;
1389
1459
  //#endregion
1390
- 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, MutationState, ParsedBasket, Product, ProductInstance, ProductInstanceInput, ProductInstances, ProductResponse, ProductSaveInput, Promotion, PromotionResponse, PromotionRuleSet, QueryState, 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, UseBasketReportReturn, 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, useBasketReport, useCategory, useConsumer, useDelete, useEmployee, useLogout, useMerchant, useProduct, usePromotion, useReport, useSession, useStore, useSubmit, useUpdateMerchant, useUploadImage, useUploadMerchantImage, useUser, validateMerchant, withToken };
1460
+ 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, MutationState, ParsedBasket, Product, ProductInstance, ProductInstanceInput, ProductInstances, ProductResponse, ProductSaveInput, Promotion, PromotionResponse, PromotionRuleSet, QueryState, 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, UpdateMerchantOptions, UploadImageParams, UploadKind, UploadMerchantImageOptions, UploadedImage, UseBasketReportReturn, 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, loginPath, logout, logoutPath, merchantLinksFromForm, merchantLinksToForm, normalizeMerchantLinks, normalizeTagList, parseBasketReportData, readImageSize, rolesById, saveCategory, saveEmployee, saveEntities, saveEntity, saveProduct, savePromotion, saveStore, setMerchantImage, submitEntity, toProductInstancesForSave, toShopwaveApiError, toStoredImageIds, updateMerchant, uploadImage, uploadMerchantImage, useBasketReport, useCategory, useConsumer, useDelete, useEmployee, useLogout, useMerchant, useProduct, useProductInstanceTags, useProductTags, usePromotion, useReport, useSession, useStore, useSubmit, useUpdateMerchant, useUploadImage, useUploadMerchantImage, useUser, validateMerchant, withToken };
1391
1461
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -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>`. */
@@ -790,7 +811,7 @@ declare function buildConsumerMap(consumers: Consumer[] | null | undefined): {
790
811
  *
791
812
  * Like `SHOPWAVE_ENTITIES`, this table is shared by the client functions
792
813
  * (`fetchMerchant`, `fetchUser`, `uploadImage`, …) and the server route
793
- * handlers in `react-shopwave-connect/next`, so the two halves of the contract
814
+ * handlers in `react-shopwave-connect/server`, so the two halves of the contract
794
815
  * can't drift apart. These aren't in `SHOPWAVE_ENTITIES` because they aren't
795
816
  * keyed collections: `GET /merchant` answers `{ merchant: {…} }`, not a map by id.
796
817
  */
@@ -837,6 +858,35 @@ declare const SHOPWAVE_UPLOAD: Readonly<{
837
858
  kindField: "kind";
838
859
  }>;
839
860
  declare function isUploadKind(value: unknown): value is UploadKind;
861
+ /**
862
+ * Read-only lists that aren't records: the merchant's distinct tags.
863
+ *
864
+ * Like `SHOPWAVE_RESOURCES`, shared by the client functions
865
+ * (`fetchProductTags`, `fetchProductInstanceTags`) and the server route
866
+ * handlers (`shopwave.lookup(kind)`), so the two halves can't drift apart.
867
+ *
868
+ * - productTags: `GET /product/tags` → `{ tags: string[] }`, every distinct tag
869
+ * on the merchant's products. No parameters. The API reference says
870
+ * "internal SKU tags are excluded", but the live API includes system tags
871
+ * written by imports and syncs (`PID-133`, `VID-137`, `#Hash:…`, `upc-…`;
872
+ * test merchant 5644, 29 Oct 2026). Apps that offer the list as suggestions
873
+ * filter those themselves. Tags of deleted products drop out of the list.
874
+ * - productInstanceTags: `GET /product/instance/tags` → `{ tags: string[] }`,
875
+ * the same for price instances (channels such as "Eat In", "Takeout").
876
+ *
877
+ * The app route for instance tags is `products/instance-tags`, one segment
878
+ * under `products`, so it sits beside `products/[id]` without nesting deeper.
879
+ */
880
+ interface LookupDefinition {
881
+ /** App route: `/api/<route>`. */
882
+ route: string;
883
+ /** Key of the list in the response (`{ tags: [...] }`). */
884
+ key: string;
885
+ /** Shopwave API path. */
886
+ upstream: string;
887
+ }
888
+ type LookupKind = "productTags" | "productInstanceTags";
889
+ declare const SHOPWAVE_LOOKUPS: Readonly<Record<LookupKind, LookupDefinition>>;
840
890
  //#endregion
841
891
  //#region src/core/imageFit.d.ts
842
892
  /**
@@ -1234,6 +1284,26 @@ declare function useEmployee(params?: FetchEmployeesParams, options?: RequestOpt
1234
1284
  */
1235
1285
  declare function useProduct(params?: FetchProductsParams, options?: RequestOptions): QueryState<Product[]>;
1236
1286
  //#endregion
1287
+ //#region src/hooks/useProductTags.d.ts
1288
+ type LookupOptions = RequestOptions & {
1289
+ /** Fetch only when true (e.g. once a tag field is first opened). Defaults to true. */
1290
+ enabled?: boolean;
1291
+ };
1292
+ /**
1293
+ * The merchant's distinct product tags, for a tag field's suggestions.
1294
+ * `data` is `string[]` once loaded.
1295
+ *
1296
+ * @example
1297
+ * const [opened, setOpened] = useState(false);
1298
+ * const { data: tags, loading } = useProductTags({ enabled: opened });
1299
+ */
1300
+ declare function useProductTags(options?: LookupOptions): QueryState<string[]>;
1301
+ /**
1302
+ * The merchant's distinct price-instance (channel) tags: Eat In, Takeout, …
1303
+ * `data` is `string[]` once loaded.
1304
+ */
1305
+ declare function useProductInstanceTags(options?: LookupOptions): QueryState<string[]>;
1306
+ //#endregion
1237
1307
  //#region src/hooks/usePromotion.d.ts
1238
1308
  /**
1239
1309
  * Auto-fetches promotions on mount and whenever the params change.
@@ -1387,5 +1457,5 @@ interface UseBasketReportReturn {
1387
1457
  */
1388
1458
  declare function useBasketReport(options?: RequestOptions): UseBasketReportReturn;
1389
1459
  //#endregion
1390
- 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, MutationState, ParsedBasket, Product, ProductInstance, ProductInstanceInput, ProductInstances, ProductResponse, ProductSaveInput, Promotion, PromotionResponse, PromotionRuleSet, QueryState, 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, UseBasketReportReturn, 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, useBasketReport, useCategory, useConsumer, useDelete, useEmployee, useLogout, useMerchant, useProduct, usePromotion, useReport, useSession, useStore, useSubmit, useUpdateMerchant, useUploadImage, useUploadMerchantImage, useUser, validateMerchant, withToken };
1460
+ 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, MutationState, ParsedBasket, Product, ProductInstance, ProductInstanceInput, ProductInstances, ProductResponse, ProductSaveInput, Promotion, PromotionResponse, PromotionRuleSet, QueryState, 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, UpdateMerchantOptions, UploadImageParams, UploadKind, UploadMerchantImageOptions, UploadedImage, UseBasketReportReturn, 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, loginPath, logout, logoutPath, merchantLinksFromForm, merchantLinksToForm, normalizeMerchantLinks, normalizeTagList, parseBasketReportData, readImageSize, rolesById, saveCategory, saveEmployee, saveEntities, saveEntity, saveProduct, savePromotion, saveStore, setMerchantImage, submitEntity, toProductInstancesForSave, toShopwaveApiError, toStoredImageIds, updateMerchant, uploadImage, uploadMerchantImage, useBasketReport, useCategory, useConsumer, useDelete, useEmployee, useLogout, useMerchant, useProduct, useProductInstanceTags, useProductTags, usePromotion, useReport, useSession, useStore, useSubmit, useUpdateMerchant, useUploadImage, useUploadMerchantImage, useUser, validateMerchant, withToken };
1391
1461
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -351,6 +351,106 @@ async function fetchProductsMap(productIds, options = {}, batchSize = 200) {
351
351
  return result;
352
352
  }
353
353
 
354
+ //#endregion
355
+ //#region src/core/resources.ts
356
+ /**
357
+ * - merchant: `GET /merchant`; `POST /merchant` with `{ merchant: { id, … } }`
358
+ * updates it (without an `id` the API would create a second merchant, so the
359
+ * route requires one).
360
+ * - user: `GET /user` (read-only here; the API's `POST /user` invites users and
361
+ * needs the admin scope).
362
+ */
363
+ const SHOPWAVE_RESOURCES = Object.freeze({
364
+ merchant: {
365
+ route: "merchant",
366
+ key: "merchant",
367
+ upstream: "merchant",
368
+ writable: true
369
+ },
370
+ user: {
371
+ route: "user",
372
+ key: "user",
373
+ upstream: "user",
374
+ writable: false
375
+ }
376
+ });
377
+ /** `UploadKind` → the API's `contentType` value. */
378
+ const UPLOAD_KINDS = Object.freeze({
379
+ merchant: "merchant",
380
+ merchantFeature: "merchantFeature",
381
+ product: "product",
382
+ user: "user",
383
+ applicationLogo: "applicaionLogo",
384
+ applicationImages: "applicaionImages"
385
+ });
386
+ /** How uploads are addressed (app route and Shopwave uploader). */
387
+ const SHOPWAVE_UPLOAD = Object.freeze({
388
+ route: "upload",
389
+ upstream: "uploader",
390
+ kindHeader: "contentType",
391
+ fileField: "file",
392
+ kindField: "kind"
393
+ });
394
+ function isUploadKind(value) {
395
+ return typeof value === "string" && Object.prototype.hasOwnProperty.call(UPLOAD_KINDS, value);
396
+ }
397
+ const SHOPWAVE_LOOKUPS = Object.freeze({
398
+ productTags: {
399
+ route: "products/tags",
400
+ key: "tags",
401
+ upstream: "product/tags"
402
+ },
403
+ productInstanceTags: {
404
+ route: "products/instance-tags",
405
+ key: "tags",
406
+ upstream: "product/instance/tags"
407
+ }
408
+ });
409
+
410
+ //#endregion
411
+ //#region src/core/productTags.ts
412
+ /**
413
+ * Turns a tag list from the API into clean strings: trims each tag, drops
414
+ * blanks and anything that isn't text, and removes exact duplicates (first one
415
+ * wins). The API's own order is kept. A map is accepted too (its values are
416
+ * used), in case the API ever answers keyed by id.
417
+ */
418
+ function normalizeTagList(value) {
419
+ const list = Array.isArray(value) ? value : value && typeof value === "object" ? Object.values(value) : [];
420
+ const seen = /* @__PURE__ */ new Set();
421
+ const out = [];
422
+ for (const item of list) {
423
+ if (typeof item !== "string" && typeof item !== "number") continue;
424
+ const tag = String(item).trim();
425
+ if (!tag || seen.has(tag)) continue;
426
+ seen.add(tag);
427
+ out.push(tag);
428
+ }
429
+ return out;
430
+ }
431
+ async function fetchLookup(kind, options) {
432
+ const def = SHOPWAVE_LOOKUPS[kind];
433
+ if (!def) throw new Error(`Unknown Shopwave lookup "${kind}"`);
434
+ const json = await apiGet(`/api/${def.route}`, {}, options);
435
+ assertNoApiErrors(json, 200);
436
+ return normalizeTagList(json?.[def.key]);
437
+ }
438
+ /**
439
+ * Every distinct tag used on the merchant's products (`GET /product/tags`),
440
+ * for a tag field's suggestions. Returns `[]` when there are none.
441
+ */
442
+ function fetchProductTags(options = {}) {
443
+ return fetchLookup("productTags", options);
444
+ }
445
+ /**
446
+ * Every distinct tag used on the merchant's price instances
447
+ * (`GET /product/instance/tags`): the channel names (Eat In, Takeout, …).
448
+ * Returns `[]` when there are none.
449
+ */
450
+ function fetchProductInstanceTags(options = {}) {
451
+ return fetchLookup("productInstanceTags", options);
452
+ }
453
+
354
454
  //#endregion
355
455
  //#region src/core/promotion.ts
356
456
  /** Promotion rule identifiers as stored by the Shopwave API. */
@@ -812,50 +912,6 @@ function buildConsumerMap(consumers) {
812
912
  return map;
813
913
  }
814
914
 
815
- //#endregion
816
- //#region src/core/resources.ts
817
- /**
818
- * - merchant: `GET /merchant`; `POST /merchant` with `{ merchant: { id, … } }`
819
- * updates it (without an `id` the API would create a second merchant, so the
820
- * route requires one).
821
- * - user: `GET /user` (read-only here; the API's `POST /user` invites users and
822
- * needs the admin scope).
823
- */
824
- const SHOPWAVE_RESOURCES = Object.freeze({
825
- merchant: {
826
- route: "merchant",
827
- key: "merchant",
828
- upstream: "merchant",
829
- writable: true
830
- },
831
- user: {
832
- route: "user",
833
- key: "user",
834
- upstream: "user",
835
- writable: false
836
- }
837
- });
838
- /** `UploadKind` → the API's `contentType` value. */
839
- const UPLOAD_KINDS = Object.freeze({
840
- merchant: "merchant",
841
- merchantFeature: "merchantFeature",
842
- product: "product",
843
- user: "user",
844
- applicationLogo: "applicaionLogo",
845
- applicationImages: "applicaionImages"
846
- });
847
- /** How uploads are addressed (app route and Shopwave uploader). */
848
- const SHOPWAVE_UPLOAD = Object.freeze({
849
- route: "upload",
850
- upstream: "uploader",
851
- kindHeader: "contentType",
852
- fileField: "file",
853
- kindField: "kind"
854
- });
855
- function isUploadKind(value) {
856
- return typeof value === "string" && Object.prototype.hasOwnProperty.call(UPLOAD_KINDS, value);
857
- }
858
-
859
915
  //#endregion
860
916
  //#region src/core/imageFit.ts
861
917
  /**
@@ -1522,6 +1578,33 @@ function useProduct(params = {}, options) {
1522
1578
  ]);
1523
1579
  }
1524
1580
 
1581
+ //#endregion
1582
+ //#region src/hooks/useProductTags.ts
1583
+ /**
1584
+ * The merchant's distinct product tags, for a tag field's suggestions.
1585
+ * `data` is `string[]` once loaded.
1586
+ *
1587
+ * @example
1588
+ * const [opened, setOpened] = useState(false);
1589
+ * const { data: tags, loading } = useProductTags({ enabled: opened });
1590
+ */
1591
+ function useProductTags(options) {
1592
+ return useQuery((signal) => fetchProductTags({
1593
+ ...options,
1594
+ signal
1595
+ }), [options?.baseUrl, options?.token], options?.enabled ?? true);
1596
+ }
1597
+ /**
1598
+ * The merchant's distinct price-instance (channel) tags: Eat In, Takeout, …
1599
+ * `data` is `string[]` once loaded.
1600
+ */
1601
+ function useProductInstanceTags(options) {
1602
+ return useQuery((signal) => fetchProductInstanceTags({
1603
+ ...options,
1604
+ signal
1605
+ }), [options?.baseUrl, options?.token], options?.enabled ?? true);
1606
+ }
1607
+
1525
1608
  //#endregion
1526
1609
  //#region src/hooks/usePromotion.ts
1527
1610
  /**
@@ -1832,5 +1915,5 @@ function useBasketReport(options) {
1832
1915
  }
1833
1916
 
1834
1917
  //#endregion
1835
- export { DEFAULT_BASKET_FILTERS, DEFAULT_PAGINATION, 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, PromotionRuleSet, SHOPWAVE_ENTITIES, SHOPWAVE_IMAGE_BASE_URL, SHOPWAVE_RESOURCES, SHOPWAVE_UPLOAD, ShopwaveApiError, UPLOAD_KINDS, apiDelete, apiGet, apiRequest, 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, useBasketReport, useCategory, useConsumer, useDelete, useEmployee, useLogout, useMerchant, useProduct, usePromotion, useReport, useSession, useStore, useSubmit, useUpdateMerchant, useUploadImage, useUploadMerchantImage, useUser, validateMerchant, withToken };
1918
+ export { DEFAULT_BASKET_FILTERS, DEFAULT_PAGINATION, 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, PromotionRuleSet, SHOPWAVE_ENTITIES, SHOPWAVE_IMAGE_BASE_URL, SHOPWAVE_LOOKUPS, SHOPWAVE_RESOURCES, SHOPWAVE_UPLOAD, ShopwaveApiError, UPLOAD_KINDS, apiDelete, apiGet, apiRequest, 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, loginPath, logout, logoutPath, merchantLinksFromForm, merchantLinksToForm, normalizeMerchantLinks, normalizeTagList, parseBasketReportData, readImageSize, rolesById, saveCategory, saveEmployee, saveEntities, saveEntity, saveProduct, savePromotion, saveStore, setMerchantImage, submitEntity, toProductInstancesForSave, toShopwaveApiError, toStoredImageIds, updateMerchant, uploadImage, uploadMerchantImage, useBasketReport, useCategory, useConsumer, useDelete, useEmployee, useLogout, useMerchant, useProduct, useProductInstanceTags, useProductTags, usePromotion, useReport, useSession, useStore, useSubmit, useUpdateMerchant, useUploadImage, useUploadMerchantImage, useUser, validateMerchant, withToken };
1836
1919
  //# sourceMappingURL=index.js.map