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.cjs CHANGED
@@ -375,6 +375,106 @@ async function fetchProductsMap(productIds, options = {}, batchSize = 200) {
375
375
  return result;
376
376
  }
377
377
 
378
+ //#endregion
379
+ //#region src/core/resources.ts
380
+ /**
381
+ * - merchant: `GET /merchant`; `POST /merchant` with `{ merchant: { id, … } }`
382
+ * updates it (without an `id` the API would create a second merchant, so the
383
+ * route requires one).
384
+ * - user: `GET /user` (read-only here; the API's `POST /user` invites users and
385
+ * needs the admin scope).
386
+ */
387
+ const SHOPWAVE_RESOURCES = Object.freeze({
388
+ merchant: {
389
+ route: "merchant",
390
+ key: "merchant",
391
+ upstream: "merchant",
392
+ writable: true
393
+ },
394
+ user: {
395
+ route: "user",
396
+ key: "user",
397
+ upstream: "user",
398
+ writable: false
399
+ }
400
+ });
401
+ /** `UploadKind` → the API's `contentType` value. */
402
+ const UPLOAD_KINDS = Object.freeze({
403
+ merchant: "merchant",
404
+ merchantFeature: "merchantFeature",
405
+ product: "product",
406
+ user: "user",
407
+ applicationLogo: "applicaionLogo",
408
+ applicationImages: "applicaionImages"
409
+ });
410
+ /** How uploads are addressed (app route and Shopwave uploader). */
411
+ const SHOPWAVE_UPLOAD = Object.freeze({
412
+ route: "upload",
413
+ upstream: "uploader",
414
+ kindHeader: "contentType",
415
+ fileField: "file",
416
+ kindField: "kind"
417
+ });
418
+ function isUploadKind(value) {
419
+ return typeof value === "string" && Object.prototype.hasOwnProperty.call(UPLOAD_KINDS, value);
420
+ }
421
+ const SHOPWAVE_LOOKUPS = Object.freeze({
422
+ productTags: {
423
+ route: "products/tags",
424
+ key: "tags",
425
+ upstream: "product/tags"
426
+ },
427
+ productInstanceTags: {
428
+ route: "products/instance-tags",
429
+ key: "tags",
430
+ upstream: "product/instance/tags"
431
+ }
432
+ });
433
+
434
+ //#endregion
435
+ //#region src/core/productTags.ts
436
+ /**
437
+ * Turns a tag list from the API into clean strings: trims each tag, drops
438
+ * blanks and anything that isn't text, and removes exact duplicates (first one
439
+ * wins). The API's own order is kept. A map is accepted too (its values are
440
+ * used), in case the API ever answers keyed by id.
441
+ */
442
+ function normalizeTagList(value) {
443
+ const list = Array.isArray(value) ? value : value && typeof value === "object" ? Object.values(value) : [];
444
+ const seen = /* @__PURE__ */ new Set();
445
+ const out = [];
446
+ for (const item of list) {
447
+ if (typeof item !== "string" && typeof item !== "number") continue;
448
+ const tag = String(item).trim();
449
+ if (!tag || seen.has(tag)) continue;
450
+ seen.add(tag);
451
+ out.push(tag);
452
+ }
453
+ return out;
454
+ }
455
+ async function fetchLookup(kind, options) {
456
+ const def = SHOPWAVE_LOOKUPS[kind];
457
+ if (!def) throw new Error(`Unknown Shopwave lookup "${kind}"`);
458
+ const json = await apiGet(`/api/${def.route}`, {}, options);
459
+ assertNoApiErrors(json, 200);
460
+ return normalizeTagList(json?.[def.key]);
461
+ }
462
+ /**
463
+ * Every distinct tag used on the merchant's products (`GET /product/tags`),
464
+ * for a tag field's suggestions. Returns `[]` when there are none.
465
+ */
466
+ function fetchProductTags(options = {}) {
467
+ return fetchLookup("productTags", options);
468
+ }
469
+ /**
470
+ * Every distinct tag used on the merchant's price instances
471
+ * (`GET /product/instance/tags`): the channel names (Eat In, Takeout, …).
472
+ * Returns `[]` when there are none.
473
+ */
474
+ function fetchProductInstanceTags(options = {}) {
475
+ return fetchLookup("productInstanceTags", options);
476
+ }
477
+
378
478
  //#endregion
379
479
  //#region src/core/promotion.ts
380
480
  /** Promotion rule identifiers as stored by the Shopwave API. */
@@ -836,50 +936,6 @@ function buildConsumerMap(consumers) {
836
936
  return map;
837
937
  }
838
938
 
839
- //#endregion
840
- //#region src/core/resources.ts
841
- /**
842
- * - merchant: `GET /merchant`; `POST /merchant` with `{ merchant: { id, … } }`
843
- * updates it (without an `id` the API would create a second merchant, so the
844
- * route requires one).
845
- * - user: `GET /user` (read-only here; the API's `POST /user` invites users and
846
- * needs the admin scope).
847
- */
848
- const SHOPWAVE_RESOURCES = Object.freeze({
849
- merchant: {
850
- route: "merchant",
851
- key: "merchant",
852
- upstream: "merchant",
853
- writable: true
854
- },
855
- user: {
856
- route: "user",
857
- key: "user",
858
- upstream: "user",
859
- writable: false
860
- }
861
- });
862
- /** `UploadKind` → the API's `contentType` value. */
863
- const UPLOAD_KINDS = Object.freeze({
864
- merchant: "merchant",
865
- merchantFeature: "merchantFeature",
866
- product: "product",
867
- user: "user",
868
- applicationLogo: "applicaionLogo",
869
- applicationImages: "applicaionImages"
870
- });
871
- /** How uploads are addressed (app route and Shopwave uploader). */
872
- const SHOPWAVE_UPLOAD = Object.freeze({
873
- route: "upload",
874
- upstream: "uploader",
875
- kindHeader: "contentType",
876
- fileField: "file",
877
- kindField: "kind"
878
- });
879
- function isUploadKind(value) {
880
- return typeof value === "string" && Object.prototype.hasOwnProperty.call(UPLOAD_KINDS, value);
881
- }
882
-
883
939
  //#endregion
884
940
  //#region src/core/imageFit.ts
885
941
  /**
@@ -1546,6 +1602,33 @@ function useProduct(params = {}, options) {
1546
1602
  ]);
1547
1603
  }
1548
1604
 
1605
+ //#endregion
1606
+ //#region src/hooks/useProductTags.ts
1607
+ /**
1608
+ * The merchant's distinct product tags, for a tag field's suggestions.
1609
+ * `data` is `string[]` once loaded.
1610
+ *
1611
+ * @example
1612
+ * const [opened, setOpened] = useState(false);
1613
+ * const { data: tags, loading } = useProductTags({ enabled: opened });
1614
+ */
1615
+ function useProductTags(options) {
1616
+ return useQuery((signal) => fetchProductTags({
1617
+ ...options,
1618
+ signal
1619
+ }), [options?.baseUrl, options?.token], options?.enabled ?? true);
1620
+ }
1621
+ /**
1622
+ * The merchant's distinct price-instance (channel) tags: Eat In, Takeout, …
1623
+ * `data` is `string[]` once loaded.
1624
+ */
1625
+ function useProductInstanceTags(options) {
1626
+ return useQuery((signal) => fetchProductInstanceTags({
1627
+ ...options,
1628
+ signal
1629
+ }), [options?.baseUrl, options?.token], options?.enabled ?? true);
1630
+ }
1631
+
1549
1632
  //#endregion
1550
1633
  //#region src/hooks/usePromotion.ts
1551
1634
  /**
@@ -1869,6 +1952,7 @@ exports.MERCHANT_READ_ONLY_FIELDS = MERCHANT_READ_ONLY_FIELDS;
1869
1952
  exports.PromotionRuleSet = PromotionRuleSet;
1870
1953
  exports.SHOPWAVE_ENTITIES = SHOPWAVE_ENTITIES;
1871
1954
  exports.SHOPWAVE_IMAGE_BASE_URL = SHOPWAVE_IMAGE_BASE_URL;
1955
+ exports.SHOPWAVE_LOOKUPS = SHOPWAVE_LOOKUPS;
1872
1956
  exports.SHOPWAVE_RESOURCES = SHOPWAVE_RESOURCES;
1873
1957
  exports.SHOPWAVE_UPLOAD = SHOPWAVE_UPLOAD;
1874
1958
  exports.ShopwaveApiError = ShopwaveApiError;
@@ -1902,6 +1986,8 @@ exports.fetchEmployees = fetchEmployees;
1902
1986
  exports.fetchEntityById = fetchEntityById;
1903
1987
  exports.fetchMerchant = fetchMerchant;
1904
1988
  exports.fetchProduct = fetchProduct;
1989
+ exports.fetchProductInstanceTags = fetchProductInstanceTags;
1990
+ exports.fetchProductTags = fetchProductTags;
1905
1991
  exports.fetchProducts = fetchProducts;
1906
1992
  exports.fetchProductsMap = fetchProductsMap;
1907
1993
  exports.fetchPromotion = fetchPromotion;
@@ -1928,6 +2014,7 @@ exports.logoutPath = logoutPath;
1928
2014
  exports.merchantLinksFromForm = merchantLinksFromForm;
1929
2015
  exports.merchantLinksToForm = merchantLinksToForm;
1930
2016
  exports.normalizeMerchantLinks = normalizeMerchantLinks;
2017
+ exports.normalizeTagList = normalizeTagList;
1931
2018
  exports.parseBasketReportData = parseBasketReportData;
1932
2019
  exports.readImageSize = readImageSize;
1933
2020
  exports.rolesById = rolesById;
@@ -1954,6 +2041,8 @@ exports.useEmployee = useEmployee;
1954
2041
  exports.useLogout = useLogout;
1955
2042
  exports.useMerchant = useMerchant;
1956
2043
  exports.useProduct = useProduct;
2044
+ exports.useProductInstanceTags = useProductInstanceTags;
2045
+ exports.useProductTags = useProductTags;
1957
2046
  exports.usePromotion = usePromotion;
1958
2047
  exports.useReport = useReport;
1959
2048
  exports.useSession = useSession;