@wocart/storefront 1.22.0 → 2.0.0
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/CHANGELOG.md +62 -0
- package/README.md +22 -117
- package/USAGE.md +59 -71
- package/dist/abandoned-checkout.d.ts +2 -3
- package/dist/abandoned-checkout.js +2 -12
- package/dist/actions.d.ts +1 -0
- package/dist/actions.js +3 -0
- package/dist/checkout-key.d.ts +25 -0
- package/dist/checkout-key.js +42 -0
- package/dist/client/orders.js +2 -1
- package/dist/client/paths.d.ts +4 -4
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/schemas.d.ts +84 -35
- package/dist/schemas.js +17 -12
- package/dist/seo.js +1 -1
- package/dist/types.d.ts +14 -7
- package/dist/utils/image.d.ts +50 -169
- package/dist/utils/image.js +72 -165
- package/dist/utils/product-image.d.ts +6 -6
- package/dist/utils/product-image.js +7 -7
- package/dist/utils/uuid.d.ts +6 -0
- package/dist/utils/uuid.js +10 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Internal modules stay reachable only through their intentional entry points.
|
|
11
11
|
*/
|
|
12
12
|
export { formatMoney } from "./utils/money.js";
|
|
13
|
-
export {
|
|
13
|
+
export { isMediaKey, mediaImageSrcset, mediaImageUrl, mediaUrl, pictureOf } from "./utils/image.js";
|
|
14
14
|
export { productImageSource } from "./utils/product-image.js";
|
|
15
15
|
export { MAX_RESOLVED_PREFILL_LENGTH, PREFILL_TOKENS, stripTrackingParams, truncateAtWordBoundary, resolvePrefillText, buildWhatsAppHref, } from "./whatsapp.js";
|
|
16
16
|
export { STOREFRONT_PAGE_PATHS, STOREFRONT_ROUTES, matchStorefrontPath, showsWidgetOn, storefrontPath } from "./routes.js";
|
|
@@ -18,6 +18,7 @@ export { servedLanguage } from "./locales.js";
|
|
|
18
18
|
export { alternateLinks, localeRouting, localizeHref, resolveLocalePath } from "./locale-routing.js";
|
|
19
19
|
export { addedLines, createBasketStore, createMemoryStorageAdapter, createLocalStorageAdapter, DEFAULT_BASKET_STORAGE_KEY, toOrderItems, } from "./basket.js";
|
|
20
20
|
export { MAX_BASKET_LINES, MAX_BASKET_LINE_QUANTITY, basketLineKey } from "./basket-line.js";
|
|
21
|
+
export { bindCheckoutKey } from "./checkout-key.js";
|
|
21
22
|
export { createOtpMachine, createOtpTransport, mapOtpResponse, otpTransportFailure, } from "./otp.js";
|
|
22
23
|
export { WILAYAS } from "./data/wilayas.js";
|
|
23
24
|
export { ALGERIA_COMMUNES, communesForWilaya } from "./data/communes.js";
|
package/dist/schemas.d.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
export declare const MediaImageSchema: z.ZodObject<{
|
|
3
|
+
key: z.ZodString;
|
|
4
|
+
url: z.ZodString;
|
|
5
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
6
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
7
|
+
}, z.core.$strip>;
|
|
8
|
+
export declare const MediaDeliverySchema: z.ZodObject<{
|
|
9
|
+
kind: z.ZodEnum<{
|
|
10
|
+
cloudflare: "cloudflare";
|
|
11
|
+
direct: "direct";
|
|
12
|
+
imagekit: "imagekit";
|
|
13
|
+
}>;
|
|
14
|
+
origin: z.ZodString;
|
|
15
|
+
}, z.core.$strip>;
|
|
2
16
|
export declare const ProductImageSchema: z.ZodObject<{
|
|
17
|
+
key: z.ZodString;
|
|
18
|
+
url: z.ZodString;
|
|
19
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
20
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
3
21
|
id: z.ZodString;
|
|
4
|
-
src: z.ZodString;
|
|
5
|
-
srcSm: z.ZodNullable<z.ZodString>;
|
|
6
|
-
srcMd: z.ZodNullable<z.ZodString>;
|
|
7
|
-
srcLg: z.ZodNullable<z.ZodString>;
|
|
8
22
|
altText: z.ZodNullable<z.ZodString>;
|
|
9
23
|
position: z.ZodNumber;
|
|
10
24
|
}, z.core.$strip>;
|
|
@@ -64,7 +78,12 @@ export declare const CategorySchema: z.ZodObject<{
|
|
|
64
78
|
slug: z.ZodString;
|
|
65
79
|
description: z.ZodNullable<z.ZodString>;
|
|
66
80
|
parentId: z.ZodNullable<z.ZodString>;
|
|
67
|
-
|
|
81
|
+
image: z.ZodNullable<z.ZodObject<{
|
|
82
|
+
key: z.ZodString;
|
|
83
|
+
url: z.ZodString;
|
|
84
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
85
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
86
|
+
}, z.core.$strip>>;
|
|
68
87
|
metaTitle: z.ZodNullable<z.ZodString>;
|
|
69
88
|
metaDescription: z.ZodNullable<z.ZodString>;
|
|
70
89
|
metaKeywords: z.ZodNullable<z.ZodString>;
|
|
@@ -114,11 +133,11 @@ export declare const ProductListSchema: z.ZodObject<{
|
|
|
114
133
|
variantOptions: z.ZodNullable<z.ZodString>;
|
|
115
134
|
tags: z.ZodNullable<z.ZodString>;
|
|
116
135
|
coverImage: z.ZodNullable<z.ZodObject<{
|
|
136
|
+
key: z.ZodString;
|
|
137
|
+
url: z.ZodString;
|
|
138
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
139
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
117
140
|
id: z.ZodString;
|
|
118
|
-
src: z.ZodString;
|
|
119
|
-
srcSm: z.ZodNullable<z.ZodString>;
|
|
120
|
-
srcMd: z.ZodNullable<z.ZodString>;
|
|
121
|
-
srcLg: z.ZodNullable<z.ZodString>;
|
|
122
141
|
altText: z.ZodNullable<z.ZodString>;
|
|
123
142
|
position: z.ZodNumber;
|
|
124
143
|
}, z.core.$strip>>;
|
|
@@ -180,7 +199,12 @@ export declare const ProductSchema: z.ZodObject<{
|
|
|
180
199
|
slug: z.ZodString;
|
|
181
200
|
description: z.ZodNullable<z.ZodString>;
|
|
182
201
|
parentId: z.ZodNullable<z.ZodString>;
|
|
183
|
-
|
|
202
|
+
image: z.ZodNullable<z.ZodObject<{
|
|
203
|
+
key: z.ZodString;
|
|
204
|
+
url: z.ZodString;
|
|
205
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
206
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
207
|
+
}, z.core.$strip>>;
|
|
184
208
|
metaTitle: z.ZodNullable<z.ZodString>;
|
|
185
209
|
metaDescription: z.ZodNullable<z.ZodString>;
|
|
186
210
|
metaKeywords: z.ZodNullable<z.ZodString>;
|
|
@@ -208,11 +232,11 @@ export declare const ProductSchema: z.ZodObject<{
|
|
|
208
232
|
updatedAt: z.ZodString;
|
|
209
233
|
}, z.core.$strip>>;
|
|
210
234
|
images: z.ZodArray<z.ZodObject<{
|
|
235
|
+
key: z.ZodString;
|
|
236
|
+
url: z.ZodString;
|
|
237
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
238
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
211
239
|
id: z.ZodString;
|
|
212
|
-
src: z.ZodString;
|
|
213
|
-
srcSm: z.ZodNullable<z.ZodString>;
|
|
214
|
-
srcMd: z.ZodNullable<z.ZodString>;
|
|
215
|
-
srcLg: z.ZodNullable<z.ZodString>;
|
|
216
240
|
altText: z.ZodNullable<z.ZodString>;
|
|
217
241
|
position: z.ZodNumber;
|
|
218
242
|
}, z.core.$strip>>;
|
|
@@ -282,11 +306,11 @@ export declare const StoreCollectionSchema: z.ZodObject<{
|
|
|
282
306
|
description: z.ZodNullable<z.ZodString>;
|
|
283
307
|
productCount: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
284
308
|
image: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
309
|
+
key: z.ZodString;
|
|
310
|
+
url: z.ZodString;
|
|
311
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
312
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
285
313
|
id: z.ZodString;
|
|
286
|
-
src: z.ZodString;
|
|
287
|
-
srcSm: z.ZodNullable<z.ZodString>;
|
|
288
|
-
srcMd: z.ZodNullable<z.ZodString>;
|
|
289
|
-
srcLg: z.ZodNullable<z.ZodString>;
|
|
290
314
|
altText: z.ZodNullable<z.ZodString>;
|
|
291
315
|
position: z.ZodNumber;
|
|
292
316
|
}, z.core.$strip>>>;
|
|
@@ -417,7 +441,12 @@ export declare const StoreConfigSchema: z.ZodObject<{
|
|
|
417
441
|
id: z.ZodString;
|
|
418
442
|
name: z.ZodString;
|
|
419
443
|
domain: z.ZodNullable<z.ZodString>;
|
|
420
|
-
|
|
444
|
+
logo: z.ZodNullable<z.ZodObject<{
|
|
445
|
+
key: z.ZodString;
|
|
446
|
+
url: z.ZodString;
|
|
447
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
448
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
449
|
+
}, z.core.$strip>>;
|
|
421
450
|
themeId: z.ZodString;
|
|
422
451
|
primaryColor: z.ZodString;
|
|
423
452
|
accentColor: z.ZodString;
|
|
@@ -440,7 +469,20 @@ export declare const StoreConfigSchema: z.ZodObject<{
|
|
|
440
469
|
currencySymbol: z.ZodString;
|
|
441
470
|
metaTitle: z.ZodNullable<z.ZodString>;
|
|
442
471
|
metaDescription: z.ZodNullable<z.ZodString>;
|
|
443
|
-
ogImage: z.ZodNullable<z.
|
|
472
|
+
ogImage: z.ZodNullable<z.ZodObject<{
|
|
473
|
+
key: z.ZodString;
|
|
474
|
+
url: z.ZodString;
|
|
475
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
476
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
477
|
+
}, z.core.$strip>>;
|
|
478
|
+
media: z.ZodObject<{
|
|
479
|
+
kind: z.ZodEnum<{
|
|
480
|
+
cloudflare: "cloudflare";
|
|
481
|
+
direct: "direct";
|
|
482
|
+
imagekit: "imagekit";
|
|
483
|
+
}>;
|
|
484
|
+
origin: z.ZodString;
|
|
485
|
+
}, z.core.$strip>;
|
|
444
486
|
announcementBar: z.ZodNullable<z.ZodString>;
|
|
445
487
|
reviewsEnabled: z.ZodBoolean;
|
|
446
488
|
cartEnabled: z.ZodBoolean;
|
|
@@ -549,12 +591,13 @@ export declare const StoreConfigSchema: z.ZodObject<{
|
|
|
549
591
|
}, z.core.$strip>>>;
|
|
550
592
|
}, z.core.$strip>;
|
|
551
593
|
export declare const LandingPageImageSchema: z.ZodObject<{
|
|
594
|
+
key: z.ZodString;
|
|
595
|
+
url: z.ZodString;
|
|
596
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
597
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
552
598
|
id: z.ZodString;
|
|
553
|
-
src: z.ZodString;
|
|
554
599
|
altText: z.ZodNullable<z.ZodString>;
|
|
555
600
|
position: z.ZodNumber;
|
|
556
|
-
width: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
557
|
-
height: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
558
601
|
}, z.core.$strip>;
|
|
559
602
|
export declare const LandingPageSchema: z.ZodObject<{
|
|
560
603
|
id: z.ZodString;
|
|
@@ -570,12 +613,13 @@ export declare const LandingPageSchema: z.ZodObject<{
|
|
|
570
613
|
metaDescription: z.ZodNullable<z.ZodString>;
|
|
571
614
|
publishedAt: z.ZodNullable<z.ZodString>;
|
|
572
615
|
images: z.ZodArray<z.ZodObject<{
|
|
616
|
+
key: z.ZodString;
|
|
617
|
+
url: z.ZodString;
|
|
618
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
619
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
573
620
|
id: z.ZodString;
|
|
574
|
-
src: z.ZodString;
|
|
575
621
|
altText: z.ZodNullable<z.ZodString>;
|
|
576
622
|
position: z.ZodNumber;
|
|
577
|
-
width: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
578
|
-
height: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
579
623
|
}, z.core.$strip>>;
|
|
580
624
|
product: z.ZodNullable<z.ZodObject<{
|
|
581
625
|
id: z.ZodString;
|
|
@@ -630,7 +674,12 @@ export declare const LandingPageSchema: z.ZodObject<{
|
|
|
630
674
|
slug: z.ZodString;
|
|
631
675
|
description: z.ZodNullable<z.ZodString>;
|
|
632
676
|
parentId: z.ZodNullable<z.ZodString>;
|
|
633
|
-
|
|
677
|
+
image: z.ZodNullable<z.ZodObject<{
|
|
678
|
+
key: z.ZodString;
|
|
679
|
+
url: z.ZodString;
|
|
680
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
681
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
682
|
+
}, z.core.$strip>>;
|
|
634
683
|
metaTitle: z.ZodNullable<z.ZodString>;
|
|
635
684
|
metaDescription: z.ZodNullable<z.ZodString>;
|
|
636
685
|
metaKeywords: z.ZodNullable<z.ZodString>;
|
|
@@ -658,11 +707,11 @@ export declare const LandingPageSchema: z.ZodObject<{
|
|
|
658
707
|
updatedAt: z.ZodString;
|
|
659
708
|
}, z.core.$strip>>;
|
|
660
709
|
images: z.ZodArray<z.ZodObject<{
|
|
710
|
+
key: z.ZodString;
|
|
711
|
+
url: z.ZodString;
|
|
712
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
713
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
661
714
|
id: z.ZodString;
|
|
662
|
-
src: z.ZodString;
|
|
663
|
-
srcSm: z.ZodNullable<z.ZodString>;
|
|
664
|
-
srcMd: z.ZodNullable<z.ZodString>;
|
|
665
|
-
srcLg: z.ZodNullable<z.ZodString>;
|
|
666
715
|
altText: z.ZodNullable<z.ZodString>;
|
|
667
716
|
position: z.ZodNumber;
|
|
668
717
|
}, z.core.$strip>>;
|
|
@@ -904,11 +953,11 @@ export declare const ProductPageEnvelopeSchema: z.ZodObject<{
|
|
|
904
953
|
variantOptions: z.ZodNullable<z.ZodString>;
|
|
905
954
|
tags: z.ZodNullable<z.ZodString>;
|
|
906
955
|
coverImage: z.ZodNullable<z.ZodObject<{
|
|
956
|
+
key: z.ZodString;
|
|
957
|
+
url: z.ZodString;
|
|
958
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
959
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
907
960
|
id: z.ZodString;
|
|
908
|
-
src: z.ZodString;
|
|
909
|
-
srcSm: z.ZodNullable<z.ZodString>;
|
|
910
|
-
srcMd: z.ZodNullable<z.ZodString>;
|
|
911
|
-
srcLg: z.ZodNullable<z.ZodString>;
|
|
912
961
|
altText: z.ZodNullable<z.ZodString>;
|
|
913
962
|
position: z.ZodNumber;
|
|
914
963
|
}, z.core.$strip>>;
|
package/dist/schemas.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
2
|
+
import { MEDIA_DELIVERY_KINDS } from "./utils/image.js";
|
|
3
|
+
export const MediaImageSchema = z.object({
|
|
4
|
+
key: z.string(),
|
|
5
|
+
url: z.string().url(),
|
|
6
|
+
width: z.number().int().nullable(),
|
|
7
|
+
height: z.number().int().nullable(),
|
|
8
|
+
});
|
|
9
|
+
export const MediaDeliverySchema = z.object({
|
|
10
|
+
kind: z.enum(MEDIA_DELIVERY_KINDS),
|
|
11
|
+
origin: z.string().url(),
|
|
12
|
+
});
|
|
13
|
+
export const ProductImageSchema = MediaImageSchema.extend({
|
|
3
14
|
id: z.string(),
|
|
4
|
-
src: z.string().url(),
|
|
5
|
-
srcSm: z.string().url().nullable(),
|
|
6
|
-
srcMd: z.string().url().nullable(),
|
|
7
|
-
srcLg: z.string().url().nullable(),
|
|
8
15
|
altText: z.string().nullable(),
|
|
9
16
|
position: z.number().int().min(0),
|
|
10
17
|
});
|
|
@@ -63,7 +70,7 @@ const productCategorySchema = z.object({
|
|
|
63
70
|
slug: z.string(),
|
|
64
71
|
description: z.string().nullable(),
|
|
65
72
|
parentId: z.string().nullable(),
|
|
66
|
-
|
|
73
|
+
image: MediaImageSchema.nullable(),
|
|
67
74
|
metaTitle: z.string().nullable(),
|
|
68
75
|
metaDescription: z.string().nullable(),
|
|
69
76
|
metaKeywords: z.string().nullable(),
|
|
@@ -265,7 +272,7 @@ export const StoreConfigSchema = z.object({
|
|
|
265
272
|
id: z.string(),
|
|
266
273
|
name: z.string(),
|
|
267
274
|
domain: z.string().nullable(),
|
|
268
|
-
|
|
275
|
+
logo: MediaImageSchema.nullable(),
|
|
269
276
|
themeId: z.string(),
|
|
270
277
|
primaryColor: z.string(),
|
|
271
278
|
accentColor: z.string(),
|
|
@@ -290,7 +297,8 @@ export const StoreConfigSchema = z.object({
|
|
|
290
297
|
currencySymbol: z.string(),
|
|
291
298
|
metaTitle: z.string().nullable(),
|
|
292
299
|
metaDescription: z.string().nullable(),
|
|
293
|
-
ogImage:
|
|
300
|
+
ogImage: MediaImageSchema.nullable(),
|
|
301
|
+
media: MediaDeliverySchema,
|
|
294
302
|
announcementBar: z.string().nullable(),
|
|
295
303
|
reviewsEnabled: z.boolean(),
|
|
296
304
|
cartEnabled: z.boolean(),
|
|
@@ -317,13 +325,10 @@ export const StoreConfigSchema = z.object({
|
|
|
317
325
|
legalContact: StoreLegalContactSchema.nullable().default(null),
|
|
318
326
|
whatsapp: StoreWhatsAppWidgetSchema.nullable().default(null),
|
|
319
327
|
});
|
|
320
|
-
export const LandingPageImageSchema =
|
|
328
|
+
export const LandingPageImageSchema = MediaImageSchema.extend({
|
|
321
329
|
id: z.string(),
|
|
322
|
-
src: z.string(),
|
|
323
330
|
altText: z.string().nullable(),
|
|
324
331
|
position: z.number().int(),
|
|
325
|
-
width: z.number().int().nullable().default(null),
|
|
326
|
-
height: z.number().int().nullable().default(null),
|
|
327
332
|
});
|
|
328
333
|
export const LandingPageSchema = z.object({
|
|
329
334
|
id: z.string(),
|
package/dist/seo.js
CHANGED
|
@@ -55,7 +55,7 @@ export function productStructuredData(product, options) {
|
|
|
55
55
|
? { "@type": "AggregateOffer", url: options.url, priceCurrency: product.currency, lowPrice: Math.min(...prices), highPrice: Math.max(...prices), offerCount: prices.length, availability }
|
|
56
56
|
: { "@type": "Offer", url: options.url, priceCurrency: product.currency, price: view.basePrice, availability, itemCondition: "https://schema.org/NewCondition" };
|
|
57
57
|
const sku = product.sku ?? (product.hasVariants ? initialVariant(product)?.sku : null) ?? null;
|
|
58
|
-
const images = [...product.images].sort((a, b) => a.position - b.position).map((image) => image.
|
|
58
|
+
const images = [...product.images].sort((a, b) => a.position - b.position).map((image) => image.url);
|
|
59
59
|
const rating = product.reviewStats && product.reviewStats.reviewCount > 0 ? product.reviewStats : null;
|
|
60
60
|
return {
|
|
61
61
|
"@context": "https://schema.org",
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { COUPON_REFUSAL_REASONS } from "./coupon.js";
|
|
2
2
|
import type { PRODUCT_SORTS, SHOPPER_ORDER_STAGES } from "./catalog.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import type { MediaDelivery, MediaImage } from "./utils/image.js";
|
|
4
5
|
import { ProductSchema, ProductListSchema, CategorySchema, ProductImageSchema, ProductVariantSchema, OfferSchema, QuantityPricingSchema, PageDocumentPayloadSchema } from "./schemas.js";
|
|
5
6
|
export type Product = z.infer<typeof ProductSchema>;
|
|
6
7
|
export type ProductList = z.infer<typeof ProductListSchema>;
|
|
@@ -67,7 +68,7 @@ export interface StoreConfig {
|
|
|
67
68
|
id: string;
|
|
68
69
|
name: string;
|
|
69
70
|
domain: string | null;
|
|
70
|
-
|
|
71
|
+
logo: MediaImage | null;
|
|
71
72
|
themeId: string;
|
|
72
73
|
/**
|
|
73
74
|
* @deprecated A store's colors and font are its theme's settings: declare
|
|
@@ -124,7 +125,10 @@ export interface StoreConfig {
|
|
|
124
125
|
currencySymbol: string;
|
|
125
126
|
metaTitle: string | null;
|
|
126
127
|
metaDescription: string | null;
|
|
127
|
-
|
|
128
|
+
/** The image links to the store show when shared. */
|
|
129
|
+
ogImage: MediaImage | null;
|
|
130
|
+
/** Where every image key is served from, and how it is resized: pass it to `mediaUrl`, `mediaImageUrl` and `pictureOf`. */
|
|
131
|
+
media: MediaDelivery;
|
|
128
132
|
/**
|
|
129
133
|
* @deprecated Always null. An announcement is a theme's own content: declare
|
|
130
134
|
* it as a theme setting and read `themeSettings`. Removed in 2.0.
|
|
@@ -256,14 +260,10 @@ export interface WilayaRates {
|
|
|
256
260
|
stopDesk: number;
|
|
257
261
|
}
|
|
258
262
|
/** One image in a landing page's ordered stack. */
|
|
259
|
-
export interface LandingPageImage {
|
|
263
|
+
export interface LandingPageImage extends MediaImage {
|
|
260
264
|
id: string;
|
|
261
|
-
src: string;
|
|
262
265
|
altText: string | null;
|
|
263
266
|
position: number;
|
|
264
|
-
/** Intrinsic dimensions (px), captured at upload — the page reserves the box. */
|
|
265
|
-
width: number | null;
|
|
266
|
-
height: number | null;
|
|
267
267
|
}
|
|
268
268
|
/**
|
|
269
269
|
* A published landing page — GET /store/landing-pages/{slug}.
|
|
@@ -475,6 +475,13 @@ export interface CreateOrderInput {
|
|
|
475
475
|
landingPageSlug?: string | undefined;
|
|
476
476
|
/** The code the shopper typed. An order whose code does not apply is refused whole (`couponRefusalOf`). */
|
|
477
477
|
couponCode?: string | undefined;
|
|
478
|
+
/**
|
|
479
|
+
* The checkout attempt's key, a UUID (`bindCheckoutKey`). The same key again
|
|
480
|
+
* answers with the order it placed, exactly as the first time; for another
|
|
481
|
+
* phone it fails with `CHECKOUT_KEY_IN_USE`. Without it, every call places
|
|
482
|
+
* an order.
|
|
483
|
+
*/
|
|
484
|
+
checkoutKey?: string | undefined;
|
|
478
485
|
}
|
|
479
486
|
/**
|
|
480
487
|
* The order's tracking destination — which Meta pixel it belongs to and
|
package/dist/utils/image.d.ts
CHANGED
|
@@ -1,88 +1,74 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The store's images: where a key is served, and how a photo is asked for at
|
|
3
|
+
* the size a page shows it.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* negotiation, and no-op fallback logic behind a simple interface.
|
|
5
|
+
* Every image the store's server answers is a `MediaImage` — its key and its
|
|
6
|
+
* URL — and the store's config carries its `MediaDelivery`: the origin every
|
|
7
|
+
* key is served from and how that origin resizes. These helpers take that
|
|
8
|
+
* delivery, so one theme works on every host a store can use.
|
|
9
9
|
*/
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
export declare const MEDIA_DELIVERY_KINDS: readonly ["imagekit", "cloudflare", "direct"];
|
|
11
|
+
/** How a store's images are resized: `imagekit` (`?tr=`), `cloudflare` (`/cdn-cgi/image/`), or `direct` (served as stored). */
|
|
12
|
+
export type MediaDeliveryKind = (typeof MEDIA_DELIVERY_KINDS)[number];
|
|
13
|
+
/** Where a store's images are served from: a key's URL is `origin`, a slash, and the key. */
|
|
14
|
+
export interface MediaDelivery {
|
|
15
|
+
kind: MediaDeliveryKind;
|
|
16
|
+
origin: string;
|
|
16
17
|
}
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* @example
|
|
26
|
-
* ```ts
|
|
27
|
-
* const url = optimizeImage(
|
|
28
|
-
* 'https://media.example.com/products/image.jpg',
|
|
29
|
-
* { width: 400, height: 400 },
|
|
30
|
-
* 'media.example.com'
|
|
31
|
-
* );
|
|
32
|
-
* // Returns: https://media.example.com/cdn-cgi/image/onerror=redirect,width=400,height=400,format=webp,quality=85,fit=cover/products/image.jpg
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export declare function optimizeImage(originalUrl: string, options: ImageResizeOptions, mediaDomain?: string): string;
|
|
36
|
-
/** What `mediaImageUrl` can ask Cloudflare for; an omitted value is left to Cloudflare's default. */
|
|
18
|
+
/** An image as the store's server answers it. */
|
|
19
|
+
export interface MediaImage {
|
|
20
|
+
key: string;
|
|
21
|
+
url: string;
|
|
22
|
+
width: number | null;
|
|
23
|
+
height: number | null;
|
|
24
|
+
}
|
|
25
|
+
/** How to show a photo; an omitted value is left to the host's default. */
|
|
37
26
|
export interface MediaImageParams {
|
|
38
27
|
width?: number;
|
|
39
28
|
height?: number;
|
|
29
|
+
/** Encoder quality, 1–100. */
|
|
40
30
|
quality?: number;
|
|
31
|
+
/** `auto` lets the host pick the best format the browser takes. */
|
|
41
32
|
format?: string;
|
|
33
|
+
/** CSS `object-fit` words: `cover` and `crop` fill the box, `contain` and `scale-down` fit inside it (`scale-down` never enlarges), `squeeze` stretches, `pad` letterboxes. */
|
|
42
34
|
fit?: "scale-down" | "contain" | "cover" | "crop" | "pad" | "squeeze";
|
|
43
35
|
}
|
|
36
|
+
/** Whether `value` can be a Media Key: a store folder, then segments of letters, digits, `.`, `_` and `-` that start with a letter or digit. */
|
|
37
|
+
export declare function isMediaKey(value: unknown): value is string;
|
|
44
38
|
/**
|
|
45
|
-
* The
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* domain's zone has Image Transformations on.
|
|
39
|
+
* The URL of a key in the store's media — what a theme's `image` field
|
|
40
|
+
* stores (`products/3f2a9c.webp`). The key is the image's identity; its URL
|
|
41
|
+
* depends on the store's delivery, so it is derived at render, never stored.
|
|
49
42
|
*
|
|
50
|
-
* `
|
|
51
|
-
* the original image instead of answering with an error.
|
|
52
|
-
*
|
|
53
|
-
* @returns `null` when there is no media domain, or the URL is not on it.
|
|
43
|
+
* @returns `null` without a delivery, or for a value that is not a Media Key.
|
|
54
44
|
*/
|
|
55
|
-
export declare function
|
|
45
|
+
export declare function mediaUrl(key: string, delivery: MediaDelivery | null | undefined): string | null;
|
|
56
46
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* so it is derived here, at render, never stored. Pass the result to
|
|
61
|
-
* `mediaImageUrl` or Astro's `<Image>` to resize it.
|
|
47
|
+
* A photo of the store's media at the size and format a page shows it, from
|
|
48
|
+
* the delivery's own resizer: ImageKit's `?tr=` or Cloudflare's
|
|
49
|
+
* `/cdn-cgi/image/` (which falls back to the original when a resize fails).
|
|
62
50
|
*
|
|
63
|
-
* @returns `null`
|
|
64
|
-
*
|
|
65
|
-
* makes an empty one), whitespace, control characters, a backslash, `?` or `#`.
|
|
51
|
+
* @returns `null` without a delivery, for a URL not served by it, or for a
|
|
52
|
+
* `direct` delivery, which does not resize — show the original then.
|
|
66
53
|
*/
|
|
67
|
-
export declare function
|
|
54
|
+
export declare function mediaImageUrl(url: string, params: MediaImageParams, delivery: MediaDelivery | null | undefined): string | null;
|
|
68
55
|
export interface MediaImageSrcsetOptions {
|
|
69
|
-
/** The store's
|
|
70
|
-
|
|
71
|
-
/** Height ÷ width: given, each size is cropped to it (`
|
|
56
|
+
/** The store's delivery; without one there is no srcset. */
|
|
57
|
+
delivery: MediaDelivery | null | undefined;
|
|
58
|
+
/** Height ÷ width: given, each size is cropped to it (`cover`); absent, the photo keeps its shape and is never enlarged (`scale-down`). */
|
|
72
59
|
ratio?: number;
|
|
73
|
-
/** Encoder quality, 1–100;
|
|
60
|
+
/** Encoder quality, 1–100; the host's default when absent. */
|
|
74
61
|
quality?: number;
|
|
75
62
|
}
|
|
76
63
|
/**
|
|
77
64
|
* The same photo at several widths, with width descriptors
|
|
78
65
|
* (`… 360w, … 720w`), for an `<img>` whose `sizes` says how wide it shows —
|
|
79
|
-
* a phone then downloads a phone-sized file
|
|
80
|
-
* best format the browser takes (`format=auto`).
|
|
66
|
+
* a phone then downloads a phone-sized file, in the best format it takes.
|
|
81
67
|
*
|
|
82
|
-
* @returns `null` when
|
|
68
|
+
* @returns `null` when the photo cannot be resized (see `mediaImageUrl`) or no
|
|
83
69
|
* width is a positive whole number.
|
|
84
70
|
*/
|
|
85
|
-
export declare function mediaImageSrcset(src: string, widths: readonly number[], options
|
|
71
|
+
export declare function mediaImageSrcset(src: string, widths: readonly number[], options: MediaImageSrcsetOptions): string | null;
|
|
86
72
|
/** An image a merchant picked, by its media key — what a theme's `image` field resolves to. */
|
|
87
73
|
export interface PickedImage {
|
|
88
74
|
key: string;
|
|
@@ -105,116 +91,11 @@ export interface Picture {
|
|
|
105
91
|
position: string | undefined;
|
|
106
92
|
}
|
|
107
93
|
/**
|
|
108
|
-
* A picked image as a theme draws it: its URL
|
|
109
|
-
*
|
|
110
|
-
*
|
|
94
|
+
* A picked image as a theme draws it: its URL in the store's media, its alt
|
|
95
|
+
* text (empty when the merchant wrote none), its size, and its focal point as
|
|
96
|
+
* `object-position`, so a cropped photo keeps what matters in view.
|
|
111
97
|
*
|
|
112
|
-
* @returns `null` when no image is picked, the key
|
|
113
|
-
*
|
|
114
|
-
*/
|
|
115
|
-
export declare function pictureOf(image: PickedImage | null | undefined, mediaDomain?: string): Picture | null;
|
|
116
|
-
/**
|
|
117
|
-
* Predefined image sizes for common use cases
|
|
98
|
+
* @returns `null` when no image is picked, the key is not a Media Key, or there
|
|
99
|
+
* is no delivery.
|
|
118
100
|
*/
|
|
119
|
-
export declare
|
|
120
|
-
readonly CARD: {
|
|
121
|
-
readonly width: 400;
|
|
122
|
-
readonly height: 400;
|
|
123
|
-
readonly quality: 85;
|
|
124
|
-
};
|
|
125
|
-
readonly GALLERY_MAIN: {
|
|
126
|
-
readonly width: 800;
|
|
127
|
-
readonly height: 800;
|
|
128
|
-
readonly quality: 90;
|
|
129
|
-
};
|
|
130
|
-
readonly GALLERY_THUMB: {
|
|
131
|
-
readonly width: 80;
|
|
132
|
-
readonly height: 80;
|
|
133
|
-
readonly quality: 80;
|
|
134
|
-
};
|
|
135
|
-
readonly HERO: {
|
|
136
|
-
readonly width: 1200;
|
|
137
|
-
readonly height: 600;
|
|
138
|
-
readonly quality: 90;
|
|
139
|
-
};
|
|
140
|
-
readonly CATEGORY: {
|
|
141
|
-
readonly width: 300;
|
|
142
|
-
readonly height: 200;
|
|
143
|
-
readonly quality: 85;
|
|
144
|
-
};
|
|
145
|
-
readonly LOGO: {
|
|
146
|
-
readonly width: 200;
|
|
147
|
-
readonly height: 80;
|
|
148
|
-
readonly quality: 90;
|
|
149
|
-
readonly fit: "contain";
|
|
150
|
-
};
|
|
151
|
-
};
|
|
152
|
-
/**
|
|
153
|
-
* Quick helper functions for common image sizes
|
|
154
|
-
*
|
|
155
|
-
* These take the media domain per call. Theme code usually binds it once with
|
|
156
|
-
* `createImageHelpers(mediaDomain)` and uses the returned helpers, so a call
|
|
157
|
-
* site can never forget the domain and silently ship an unoptimized image.
|
|
158
|
-
*/
|
|
159
|
-
export declare const getCardImage: (url: string, mediaDomain?: string) => string;
|
|
160
|
-
export declare const getGalleryImage: (url: string, mediaDomain?: string) => string;
|
|
161
|
-
export declare const getThumbnailImage: (url: string, mediaDomain?: string) => string;
|
|
162
|
-
export declare const getHeroImage: (url: string, mediaDomain?: string) => string;
|
|
163
|
-
export declare const getCategoryImage: (url: string, mediaDomain?: string) => string;
|
|
164
|
-
export declare const getLogoImage: (url: string, mediaDomain?: string) => string;
|
|
165
|
-
/**
|
|
166
|
-
* Generate responsive image srcset for different screen sizes
|
|
167
|
-
*
|
|
168
|
-
* @param originalUrl - The original image URL
|
|
169
|
-
* @param baseWidth - Base width for 1x display
|
|
170
|
-
* @param baseHeight - Base height for 1x display
|
|
171
|
-
* @param mediaDomain - Media domain
|
|
172
|
-
* @returns srcset string for responsive images
|
|
173
|
-
*
|
|
174
|
-
* @example
|
|
175
|
-
* ```ts
|
|
176
|
-
* const srcset = generateSrcSet(
|
|
177
|
-
* 'https://media.example.com/products/image.jpg',
|
|
178
|
-
* 400,
|
|
179
|
-
* 400,
|
|
180
|
-
* 'media.example.com'
|
|
181
|
-
* );
|
|
182
|
-
* // Returns: "url 1x, url 1.5x, url 2x"
|
|
183
|
-
* ```
|
|
184
|
-
*/
|
|
185
|
-
export declare function generateSrcSet(originalUrl: string, baseWidth: number, baseHeight: number, mediaDomain?: string): string;
|
|
186
|
-
/**
|
|
187
|
-
* Bind a media domain once and get the whole image toolkit back.
|
|
188
|
-
*
|
|
189
|
-
* The single binding point for theme code: a media domain is configured once
|
|
190
|
-
* (an env var, a store setting), and every helper then takes only the URL. A
|
|
191
|
-
* per-call domain still wins, so a theme with two media hosts can override.
|
|
192
|
-
*
|
|
193
|
-
* With no domain bound every helper is a pass-through — the correct behavior
|
|
194
|
-
* for a store that has no media domain configured (original R2 URLs).
|
|
195
|
-
*
|
|
196
|
-
* @param mediaDomain - Media domain (e.g., "media.example.com" or "https://media.example.com")
|
|
197
|
-
*
|
|
198
|
-
* @example
|
|
199
|
-
* ```ts
|
|
200
|
-
* const images = createImageHelpers(env.MEDIA_DOMAIN);
|
|
201
|
-
* images.getThumbnailImage(product.coverImage.src);
|
|
202
|
-
* images.getCardImage(url);
|
|
203
|
-
* images.generateSrcSet(url, 400, 400);
|
|
204
|
-
* ```
|
|
205
|
-
*/
|
|
206
|
-
export interface ImageHelpers {
|
|
207
|
-
/** `optimizeImage` with the media domain bound. */
|
|
208
|
-
optimizeImage: (originalUrl: string, options: ImageResizeOptions, mediaDomain?: string) => string;
|
|
209
|
-
/** `generateSrcSet` with the media domain bound. */
|
|
210
|
-
generateSrcSet: (originalUrl: string, baseWidth: number, baseHeight: number, mediaDomain?: string) => string;
|
|
211
|
-
/** The shared size presets, for callers that want the raw dimensions. */
|
|
212
|
-
IMAGE_SIZES: typeof IMAGE_SIZES;
|
|
213
|
-
getCardImage: (url: string) => string;
|
|
214
|
-
getGalleryImage: (url: string) => string;
|
|
215
|
-
getThumbnailImage: (url: string) => string;
|
|
216
|
-
getHeroImage: (url: string) => string;
|
|
217
|
-
getCategoryImage: (url: string) => string;
|
|
218
|
-
getLogoImage: (url: string) => string;
|
|
219
|
-
}
|
|
220
|
-
export declare function createImageHelpers(mediaDomain?: string): ImageHelpers;
|
|
101
|
+
export declare function pictureOf(image: PickedImage | null | undefined, delivery: MediaDelivery | null | undefined): Picture | null;
|