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.
- package/README.md +35 -10
- package/dist/core/index.cjs +222 -32
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +117 -20
- package/dist/core/index.d.ts +117 -20
- package/dist/core/index.js +217 -33
- package/dist/core/index.js.map +1 -1
- package/dist/hooks/index.cjs +34 -28
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +6 -6
- package/dist/hooks/index.d.ts +6 -6
- package/dist/hooks/index.js +34 -28
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +222 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -20
- package/dist/index.d.ts +117 -20
- package/dist/index.js +217 -33
- package/dist/index.js.map +1 -1
- package/dist/next/index.cjs +2 -2
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +3 -3
- package/dist/next/index.d.ts +3 -3
- package/dist/next/index.js +2 -2
- package/dist/next/index.js.map +1 -1
- package/dist/server/index.cjs +2 -2
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +5 -5
- package/dist/server/index.d.ts +5 -5
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/package.json +5 -1
package/dist/hooks/index.d.cts
CHANGED
|
@@ -357,8 +357,8 @@ type UploadKind = "merchant" | "merchantFeature" | "product" | "user" | "applica
|
|
|
357
357
|
/**
|
|
358
358
|
* The role an image plays, sent to Shopwave as the uploader's `prefix` header.
|
|
359
359
|
* The uploader names the file `<prefix>_<hash>.<ext>`, so the role travels with
|
|
360
|
-
* the file wherever a record stores it (a product's `images`). Live,
|
|
361
|
-
*
|
|
360
|
+
* the file wherever a record stores it (a product's `images`). Live, test
|
|
361
|
+
* merchant, 4 Nov 2026: all four values answered 201.
|
|
362
362
|
* - `product`: a product gallery image;
|
|
363
363
|
* - `product_thumbnail`: the product's lead image, shown in lists;
|
|
364
364
|
* - `variant` / `variant_thumbnail`: a variant's own image and its lead image
|
|
@@ -402,7 +402,7 @@ interface UploadedImage {
|
|
|
402
402
|
//#endregion
|
|
403
403
|
//#region src/core/merchantImages.d.ts
|
|
404
404
|
/**
|
|
405
|
-
* Merchant images, as
|
|
405
|
+
* Merchant images, as Shopwave's existing admin apps save and read them:
|
|
406
406
|
*
|
|
407
407
|
* ```
|
|
408
408
|
* { logo: { receipt: "<file>", square: "<file>" }, feature: ["<file>"] }
|
|
@@ -419,7 +419,7 @@ interface UploadedImage {
|
|
|
419
419
|
* So a featured image must be uploaded with kind `merchantFeature` (which
|
|
420
420
|
* stores it under `feature/`); a `merchant` upload lands under `logo/`.
|
|
421
421
|
*
|
|
422
|
-
* Confirmed on the live API,
|
|
422
|
+
* Confirmed on the live API, 30 Sep 2026.
|
|
423
423
|
*/
|
|
424
424
|
interface MerchantImageIds {
|
|
425
425
|
logo?: {
|
|
@@ -452,7 +452,7 @@ interface MerchantColourSet {
|
|
|
452
452
|
[key: string]: string | null | undefined;
|
|
453
453
|
}
|
|
454
454
|
/**
|
|
455
|
-
* Brand colours, as
|
|
455
|
+
* Brand colours, as Shopwave's existing admin apps save and read them
|
|
456
456
|
* (`colours.primary.main` is the logo background): `{ primary: { main,
|
|
457
457
|
* highlight, contrast } }`. `{}` when unset. Confirmed live, 30 Sep 2026.
|
|
458
458
|
*/
|
|
@@ -461,7 +461,7 @@ interface MerchantColours {
|
|
|
461
461
|
[key: string]: MerchantColourSet | null | undefined;
|
|
462
462
|
}
|
|
463
463
|
/**
|
|
464
|
-
* Web and social links, as
|
|
464
|
+
* Web and social links, as Shopwave's existing admin saves them:
|
|
465
465
|
* `{ website: { home }, social: { twitter, facebook, instagram } }`.
|
|
466
466
|
* `{}` when empty (confirmed live, 30 Sep 2026). Use {@link normalizeMerchantLinks} to read older shapes and
|
|
467
467
|
* {@link merchantLinksToForm} / {@link merchantLinksFromForm} for flat forms.
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -357,8 +357,8 @@ type UploadKind = "merchant" | "merchantFeature" | "product" | "user" | "applica
|
|
|
357
357
|
/**
|
|
358
358
|
* The role an image plays, sent to Shopwave as the uploader's `prefix` header.
|
|
359
359
|
* The uploader names the file `<prefix>_<hash>.<ext>`, so the role travels with
|
|
360
|
-
* the file wherever a record stores it (a product's `images`). Live,
|
|
361
|
-
*
|
|
360
|
+
* the file wherever a record stores it (a product's `images`). Live, test
|
|
361
|
+
* merchant, 4 Nov 2026: all four values answered 201.
|
|
362
362
|
* - `product`: a product gallery image;
|
|
363
363
|
* - `product_thumbnail`: the product's lead image, shown in lists;
|
|
364
364
|
* - `variant` / `variant_thumbnail`: a variant's own image and its lead image
|
|
@@ -402,7 +402,7 @@ interface UploadedImage {
|
|
|
402
402
|
//#endregion
|
|
403
403
|
//#region src/core/merchantImages.d.ts
|
|
404
404
|
/**
|
|
405
|
-
* Merchant images, as
|
|
405
|
+
* Merchant images, as Shopwave's existing admin apps save and read them:
|
|
406
406
|
*
|
|
407
407
|
* ```
|
|
408
408
|
* { logo: { receipt: "<file>", square: "<file>" }, feature: ["<file>"] }
|
|
@@ -419,7 +419,7 @@ interface UploadedImage {
|
|
|
419
419
|
* So a featured image must be uploaded with kind `merchantFeature` (which
|
|
420
420
|
* stores it under `feature/`); a `merchant` upload lands under `logo/`.
|
|
421
421
|
*
|
|
422
|
-
* Confirmed on the live API,
|
|
422
|
+
* Confirmed on the live API, 30 Sep 2026.
|
|
423
423
|
*/
|
|
424
424
|
interface MerchantImageIds {
|
|
425
425
|
logo?: {
|
|
@@ -452,7 +452,7 @@ interface MerchantColourSet {
|
|
|
452
452
|
[key: string]: string | null | undefined;
|
|
453
453
|
}
|
|
454
454
|
/**
|
|
455
|
-
* Brand colours, as
|
|
455
|
+
* Brand colours, as Shopwave's existing admin apps save and read them
|
|
456
456
|
* (`colours.primary.main` is the logo background): `{ primary: { main,
|
|
457
457
|
* highlight, contrast } }`. `{}` when unset. Confirmed live, 30 Sep 2026.
|
|
458
458
|
*/
|
|
@@ -461,7 +461,7 @@ interface MerchantColours {
|
|
|
461
461
|
[key: string]: MerchantColourSet | null | undefined;
|
|
462
462
|
}
|
|
463
463
|
/**
|
|
464
|
-
* Web and social links, as
|
|
464
|
+
* Web and social links, as Shopwave's existing admin saves them:
|
|
465
465
|
* `{ website: { home }, social: { twitter, facebook, instagram } }`.
|
|
466
466
|
* `{}` when empty (confirmed live, 30 Sep 2026). Use {@link normalizeMerchantLinks} to read older shapes and
|
|
467
467
|
* {@link merchantLinksToForm} / {@link merchantLinksFromForm} for flat forms.
|
package/dist/hooks/index.js
CHANGED
|
@@ -515,6 +515,35 @@ function coverCrop(srcWidth, srcHeight, dstWidth, dstHeight) {
|
|
|
515
515
|
function requireBrowserImages(fn) {
|
|
516
516
|
if (typeof createImageBitmap !== "function") throw new Error(`${fn} needs a browser (createImageBitmap is not available)`);
|
|
517
517
|
}
|
|
518
|
+
/** Draws `crop` of the bitmap at `width × height` and encodes it (one resample). */
|
|
519
|
+
async function drawCrop(bitmap, crop, width, height, type, quality, fn) {
|
|
520
|
+
const { sx, sy, sw, sh } = crop;
|
|
521
|
+
if (typeof OffscreenCanvas === "function") {
|
|
522
|
+
const canvas$1 = new OffscreenCanvas(width, height);
|
|
523
|
+
const ctx$1 = canvas$1.getContext("2d");
|
|
524
|
+
if (!ctx$1) throw new Error(`${fn}: no 2D canvas context`);
|
|
525
|
+
ctx$1.imageSmoothingQuality = "high";
|
|
526
|
+
ctx$1.drawImage(bitmap, sx, sy, sw, sh, 0, 0, width, height);
|
|
527
|
+
return canvas$1.convertToBlob({
|
|
528
|
+
type,
|
|
529
|
+
quality
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
const canvas = document.createElement("canvas");
|
|
533
|
+
canvas.width = width;
|
|
534
|
+
canvas.height = height;
|
|
535
|
+
const ctx = canvas.getContext("2d");
|
|
536
|
+
if (!ctx) throw new Error(`${fn}: no 2D canvas context`);
|
|
537
|
+
ctx.imageSmoothingQuality = "high";
|
|
538
|
+
ctx.drawImage(bitmap, sx, sy, sw, sh, 0, 0, width, height);
|
|
539
|
+
return new Promise((resolve, reject) => canvas.toBlob((b) => b ? resolve(b) : reject(/* @__PURE__ */ new Error(`${fn}: encoding failed`)), type, quality));
|
|
540
|
+
}
|
|
541
|
+
/** The input's name with the output type's extension. */
|
|
542
|
+
function outputName(file, type) {
|
|
543
|
+
const name = file.name || "image";
|
|
544
|
+
const ext = type === "image/jpeg" ? "jpg" : type.split("/")[1];
|
|
545
|
+
return `${name.replace(/\.[^.]+$/, "")}.${ext}`;
|
|
546
|
+
}
|
|
518
547
|
/**
|
|
519
548
|
* Returns the image at exactly `width × height`: scaled and centre-cropped
|
|
520
549
|
* (never stretched). Browser only. The result is a `File` named like the
|
|
@@ -523,34 +552,11 @@ function requireBrowserImages(fn) {
|
|
|
523
552
|
async function fitImageToSize(file, width, height, options = {}) {
|
|
524
553
|
requireBrowserImages("fitImageToSize");
|
|
525
554
|
const { type = "image/png", quality, keepIfExact = true } = options;
|
|
526
|
-
const
|
|
527
|
-
const ext = type === "image/jpeg" ? "jpg" : type.split("/")[1];
|
|
528
|
-
const outName = `${name.replace(/\.[^.]+$/, "")}.${ext}`;
|
|
555
|
+
const outName = outputName(file, type);
|
|
529
556
|
const bitmap = await createImageBitmap(file);
|
|
530
557
|
try {
|
|
531
558
|
if (keepIfExact && bitmap.width === width && bitmap.height === height && file.type === type) return file instanceof File ? file : new File([file], outName, { type });
|
|
532
|
-
const
|
|
533
|
-
let blob;
|
|
534
|
-
if (typeof OffscreenCanvas === "function") {
|
|
535
|
-
const canvas = new OffscreenCanvas(width, height);
|
|
536
|
-
const ctx = canvas.getContext("2d");
|
|
537
|
-
if (!ctx) throw new Error("fitImageToSize: no 2D canvas context");
|
|
538
|
-
ctx.imageSmoothingQuality = "high";
|
|
539
|
-
ctx.drawImage(bitmap, sx, sy, sw, sh, 0, 0, width, height);
|
|
540
|
-
blob = await canvas.convertToBlob({
|
|
541
|
-
type,
|
|
542
|
-
quality
|
|
543
|
-
});
|
|
544
|
-
} else {
|
|
545
|
-
const canvas = document.createElement("canvas");
|
|
546
|
-
canvas.width = width;
|
|
547
|
-
canvas.height = height;
|
|
548
|
-
const ctx = canvas.getContext("2d");
|
|
549
|
-
if (!ctx) throw new Error("fitImageToSize: no 2D canvas context");
|
|
550
|
-
ctx.imageSmoothingQuality = "high";
|
|
551
|
-
ctx.drawImage(bitmap, sx, sy, sw, sh, 0, 0, width, height);
|
|
552
|
-
blob = await new Promise((resolve, reject) => canvas.toBlob((b) => b ? resolve(b) : reject(/* @__PURE__ */ new Error("fitImageToSize: encoding failed")), type, quality));
|
|
553
|
-
}
|
|
559
|
+
const blob = await drawCrop(bitmap, coverCrop(bitmap.width, bitmap.height, width, height), width, height, type, quality, "fitImageToSize");
|
|
554
560
|
return new File([blob], outName, { type });
|
|
555
561
|
} finally {
|
|
556
562
|
bitmap.close?.();
|
|
@@ -569,7 +575,7 @@ const STATIC_HOST = /^https?:\/\/static\.merchantstack\.com\/images\//i;
|
|
|
569
575
|
/**
|
|
570
576
|
* Turns an image path from the API into a URL a page can load over HTTPS:
|
|
571
577
|
* `http://static.merchantstack.com/images/x.png` → `<base>/x.png`, and a
|
|
572
|
-
* relative path (`merchant/
|
|
578
|
+
* relative path (`merchant/123/logo/x.png`) → `<base>/merchant/123/logo/x.png`.
|
|
573
579
|
* Other absolute URLs are returned unchanged; empty input gives `""`.
|
|
574
580
|
*/
|
|
575
581
|
function getImageUrl(path, base = SHOPWAVE_IMAGE_BASE_URL) {
|
|
@@ -615,7 +621,7 @@ async function uploadImage(file, params, options = {}) {
|
|
|
615
621
|
//#endregion
|
|
616
622
|
//#region src/core/merchantImages.ts
|
|
617
623
|
/**
|
|
618
|
-
* Where each slot lives, its upload kind and its exact size (from
|
|
624
|
+
* Where each slot lives, its upload kind and its exact size (from the existing admin's
|
|
619
625
|
* merchant settings page).
|
|
620
626
|
*/
|
|
621
627
|
const MERCHANT_IMAGE_SLOTS = Object.freeze({
|
|
@@ -665,7 +671,7 @@ function toStored(value) {
|
|
|
665
671
|
}
|
|
666
672
|
/**
|
|
667
673
|
* The `imageIds` to send on a save: every URL is turned back into its file
|
|
668
|
-
* name (what
|
|
674
|
+
* name (what the existing admin does with images you didn't change) and empty values
|
|
669
675
|
* are dropped. No images gives `{}`.
|
|
670
676
|
*/
|
|
671
677
|
function toStoredImageIds(imageIds) {
|