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/README.md +14 -2
- package/dist/core/index.cjs +104 -44
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +54 -4
- package/dist/core/index.d.ts +54 -4
- package/dist/core/index.js +101 -45
- package/dist/core/index.js.map +1 -1
- package/dist/hooks/index.cjs +129 -44
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +21 -1
- package/dist/hooks/index.d.ts +21 -1
- package/dist/hooks/index.js +128 -45
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +133 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -4
- package/dist/index.d.ts +74 -4
- package/dist/index.js +128 -45
- package/dist/index.js.map +1 -1
- package/dist/next/index.cjs +24 -0
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +45 -4
- package/dist/next/index.d.ts +45 -4
- package/dist/next/index.js +24 -1
- package/dist/next/index.js.map +1 -1
- package/dist/server/index.cjs +21 -0
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +42 -4
- package/dist/server/index.d.ts +42 -4
- package/dist/server/index.js +21 -1
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/hooks/index.cjs
CHANGED
|
@@ -283,6 +283,106 @@ async function fetchProductsMap(productIds, options = {}, batchSize = 200) {
|
|
|
283
283
|
return result;
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
//#endregion
|
|
287
|
+
//#region src/core/resources.ts
|
|
288
|
+
/**
|
|
289
|
+
* - merchant: `GET /merchant`; `POST /merchant` with `{ merchant: { id, … } }`
|
|
290
|
+
* updates it (without an `id` the API would create a second merchant, so the
|
|
291
|
+
* route requires one).
|
|
292
|
+
* - user: `GET /user` (read-only here; the API's `POST /user` invites users and
|
|
293
|
+
* needs the admin scope).
|
|
294
|
+
*/
|
|
295
|
+
const SHOPWAVE_RESOURCES = Object.freeze({
|
|
296
|
+
merchant: {
|
|
297
|
+
route: "merchant",
|
|
298
|
+
key: "merchant",
|
|
299
|
+
upstream: "merchant",
|
|
300
|
+
writable: true
|
|
301
|
+
},
|
|
302
|
+
user: {
|
|
303
|
+
route: "user",
|
|
304
|
+
key: "user",
|
|
305
|
+
upstream: "user",
|
|
306
|
+
writable: false
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
/** `UploadKind` → the API's `contentType` value. */
|
|
310
|
+
const UPLOAD_KINDS = Object.freeze({
|
|
311
|
+
merchant: "merchant",
|
|
312
|
+
merchantFeature: "merchantFeature",
|
|
313
|
+
product: "product",
|
|
314
|
+
user: "user",
|
|
315
|
+
applicationLogo: "applicaionLogo",
|
|
316
|
+
applicationImages: "applicaionImages"
|
|
317
|
+
});
|
|
318
|
+
/** How uploads are addressed (app route and Shopwave uploader). */
|
|
319
|
+
const SHOPWAVE_UPLOAD = Object.freeze({
|
|
320
|
+
route: "upload",
|
|
321
|
+
upstream: "uploader",
|
|
322
|
+
kindHeader: "contentType",
|
|
323
|
+
fileField: "file",
|
|
324
|
+
kindField: "kind"
|
|
325
|
+
});
|
|
326
|
+
function isUploadKind(value) {
|
|
327
|
+
return typeof value === "string" && Object.prototype.hasOwnProperty.call(UPLOAD_KINDS, value);
|
|
328
|
+
}
|
|
329
|
+
const SHOPWAVE_LOOKUPS = Object.freeze({
|
|
330
|
+
productTags: {
|
|
331
|
+
route: "products/tags",
|
|
332
|
+
key: "tags",
|
|
333
|
+
upstream: "product/tags"
|
|
334
|
+
},
|
|
335
|
+
productInstanceTags: {
|
|
336
|
+
route: "products/instance-tags",
|
|
337
|
+
key: "tags",
|
|
338
|
+
upstream: "product/instance/tags"
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
//#endregion
|
|
343
|
+
//#region src/core/productTags.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
|
+
function normalizeTagList(value) {
|
|
351
|
+
const list = Array.isArray(value) ? value : value && typeof value === "object" ? Object.values(value) : [];
|
|
352
|
+
const seen = /* @__PURE__ */ new Set();
|
|
353
|
+
const out = [];
|
|
354
|
+
for (const item of list) {
|
|
355
|
+
if (typeof item !== "string" && typeof item !== "number") continue;
|
|
356
|
+
const tag = String(item).trim();
|
|
357
|
+
if (!tag || seen.has(tag)) continue;
|
|
358
|
+
seen.add(tag);
|
|
359
|
+
out.push(tag);
|
|
360
|
+
}
|
|
361
|
+
return out;
|
|
362
|
+
}
|
|
363
|
+
async function fetchLookup(kind, options) {
|
|
364
|
+
const def = SHOPWAVE_LOOKUPS[kind];
|
|
365
|
+
if (!def) throw new Error(`Unknown Shopwave lookup "${kind}"`);
|
|
366
|
+
const json = await apiGet(`/api/${def.route}`, {}, options);
|
|
367
|
+
assertNoApiErrors(json, 200);
|
|
368
|
+
return normalizeTagList(json?.[def.key]);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Every distinct tag used on the merchant's products (`GET /product/tags`),
|
|
372
|
+
* for a tag field's suggestions. Returns `[]` when there are none.
|
|
373
|
+
*/
|
|
374
|
+
function fetchProductTags(options = {}) {
|
|
375
|
+
return fetchLookup("productTags", options);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Every distinct tag used on the merchant's price instances
|
|
379
|
+
* (`GET /product/instance/tags`): the channel names (Eat In, Takeout, …).
|
|
380
|
+
* Returns `[]` when there are none.
|
|
381
|
+
*/
|
|
382
|
+
function fetchProductInstanceTags(options = {}) {
|
|
383
|
+
return fetchLookup("productInstanceTags", options);
|
|
384
|
+
}
|
|
385
|
+
|
|
286
386
|
//#endregion
|
|
287
387
|
//#region src/core/promotion.ts
|
|
288
388
|
/**
|
|
@@ -536,50 +636,6 @@ function buildConsumerMap(consumers) {
|
|
|
536
636
|
return map;
|
|
537
637
|
}
|
|
538
638
|
|
|
539
|
-
//#endregion
|
|
540
|
-
//#region src/core/resources.ts
|
|
541
|
-
/**
|
|
542
|
-
* - merchant: `GET /merchant`; `POST /merchant` with `{ merchant: { id, … } }`
|
|
543
|
-
* updates it (without an `id` the API would create a second merchant, so the
|
|
544
|
-
* route requires one).
|
|
545
|
-
* - user: `GET /user` (read-only here; the API's `POST /user` invites users and
|
|
546
|
-
* needs the admin scope).
|
|
547
|
-
*/
|
|
548
|
-
const SHOPWAVE_RESOURCES = Object.freeze({
|
|
549
|
-
merchant: {
|
|
550
|
-
route: "merchant",
|
|
551
|
-
key: "merchant",
|
|
552
|
-
upstream: "merchant",
|
|
553
|
-
writable: true
|
|
554
|
-
},
|
|
555
|
-
user: {
|
|
556
|
-
route: "user",
|
|
557
|
-
key: "user",
|
|
558
|
-
upstream: "user",
|
|
559
|
-
writable: false
|
|
560
|
-
}
|
|
561
|
-
});
|
|
562
|
-
/** `UploadKind` → the API's `contentType` value. */
|
|
563
|
-
const UPLOAD_KINDS = Object.freeze({
|
|
564
|
-
merchant: "merchant",
|
|
565
|
-
merchantFeature: "merchantFeature",
|
|
566
|
-
product: "product",
|
|
567
|
-
user: "user",
|
|
568
|
-
applicationLogo: "applicaionLogo",
|
|
569
|
-
applicationImages: "applicaionImages"
|
|
570
|
-
});
|
|
571
|
-
/** How uploads are addressed (app route and Shopwave uploader). */
|
|
572
|
-
const SHOPWAVE_UPLOAD = Object.freeze({
|
|
573
|
-
route: "upload",
|
|
574
|
-
upstream: "uploader",
|
|
575
|
-
kindHeader: "contentType",
|
|
576
|
-
fileField: "file",
|
|
577
|
-
kindField: "kind"
|
|
578
|
-
});
|
|
579
|
-
function isUploadKind(value) {
|
|
580
|
-
return typeof value === "string" && Object.prototype.hasOwnProperty.call(UPLOAD_KINDS, value);
|
|
581
|
-
}
|
|
582
|
-
|
|
583
639
|
//#endregion
|
|
584
640
|
//#region src/core/imageFit.ts
|
|
585
641
|
/**
|
|
@@ -1124,6 +1180,33 @@ function useProduct(params = {}, options) {
|
|
|
1124
1180
|
]);
|
|
1125
1181
|
}
|
|
1126
1182
|
|
|
1183
|
+
//#endregion
|
|
1184
|
+
//#region src/hooks/useProductTags.ts
|
|
1185
|
+
/**
|
|
1186
|
+
* The merchant's distinct product tags, for a tag field's suggestions.
|
|
1187
|
+
* `data` is `string[]` once loaded.
|
|
1188
|
+
*
|
|
1189
|
+
* @example
|
|
1190
|
+
* const [opened, setOpened] = useState(false);
|
|
1191
|
+
* const { data: tags, loading } = useProductTags({ enabled: opened });
|
|
1192
|
+
*/
|
|
1193
|
+
function useProductTags(options) {
|
|
1194
|
+
return useQuery((signal) => fetchProductTags({
|
|
1195
|
+
...options,
|
|
1196
|
+
signal
|
|
1197
|
+
}), [options?.baseUrl, options?.token], options?.enabled ?? true);
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* The merchant's distinct price-instance (channel) tags: Eat In, Takeout, …
|
|
1201
|
+
* `data` is `string[]` once loaded.
|
|
1202
|
+
*/
|
|
1203
|
+
function useProductInstanceTags(options) {
|
|
1204
|
+
return useQuery((signal) => fetchProductInstanceTags({
|
|
1205
|
+
...options,
|
|
1206
|
+
signal
|
|
1207
|
+
}), [options?.baseUrl, options?.token], options?.enabled ?? true);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1127
1210
|
//#endregion
|
|
1128
1211
|
//#region src/hooks/usePromotion.ts
|
|
1129
1212
|
/**
|
|
@@ -1442,6 +1525,8 @@ exports.useEmployee = useEmployee;
|
|
|
1442
1525
|
exports.useLogout = useLogout;
|
|
1443
1526
|
exports.useMerchant = useMerchant;
|
|
1444
1527
|
exports.useProduct = useProduct;
|
|
1528
|
+
exports.useProductInstanceTags = useProductInstanceTags;
|
|
1529
|
+
exports.useProductTags = useProductTags;
|
|
1445
1530
|
exports.usePromotion = usePromotion;
|
|
1446
1531
|
exports.useReport = useReport;
|
|
1447
1532
|
exports.useSession = useSession;
|