@wocart/storefront 1.19.0 → 1.21.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 +91 -0
- package/USAGE.md +317 -4
- package/dist/abandoned-checkout.d.ts +45 -0
- package/dist/abandoned-checkout.js +81 -3
- package/dist/answer-readers.d.ts +11 -4
- package/dist/answer-readers.js +114 -0
- package/dist/astro.d.ts +4 -0
- package/dist/astro.js +2 -0
- package/dist/basket.d.ts +11 -1
- package/dist/basket.js +17 -0
- package/dist/catalog.d.ts +24 -0
- package/dist/catalog.js +33 -0
- package/dist/client/orders.d.ts +10 -1
- package/dist/client/orders.js +8 -1
- package/dist/client/products.d.ts +13 -3
- package/dist/client/products.js +35 -12
- package/dist/coupon.d.ts +16 -1
- package/dist/coupon.js +37 -0
- package/dist/endpoints/storefront-routes.d.ts +8 -2
- package/dist/endpoints/storefront-routes.js +9 -2
- package/dist/index.d.ts +15 -7
- package/dist/index.js +9 -4
- package/dist/operations.d.ts +4 -0
- package/dist/operations.js +4 -0
- package/dist/order-lookup.d.ts +51 -0
- package/dist/order-lookup.js +44 -0
- package/dist/order-number.d.ts +9 -0
- package/dist/order-number.js +11 -0
- package/dist/product-view.d.ts +8 -0
- package/dist/product-view.js +26 -4
- package/dist/quote.d.ts +27 -0
- package/dist/quote.js +43 -0
- package/dist/review-capture.d.ts +77 -0
- package/dist/review-capture.js +172 -0
- package/dist/review-media.d.ts +8 -75
- package/dist/review-media.js +7 -170
- package/dist/review-session.d.ts +97 -0
- package/dist/review-session.js +157 -0
- package/dist/reviews.d.ts +33 -0
- package/dist/reviews.js +41 -0
- package/dist/routes.d.ts +2 -0
- package/dist/routes.js +3 -0
- package/dist/schemas.d.ts +98 -0
- package/dist/schemas.js +31 -0
- package/dist/seo.d.ts +47 -0
- package/dist/seo.js +87 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +1 -0
- package/dist/sitemap.d.ts +22 -0
- package/dist/sitemap.js +51 -0
- package/dist/store-request.d.ts +96 -0
- package/dist/store-request.js +102 -0
- package/dist/types.d.ts +50 -2
- package/dist/utils/image.d.ts +48 -0
- package/dist/utils/image.js +51 -0
- package/package.json +1 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { COUPON_REFUSAL_REASONS } from "./coupon.js";
|
|
2
|
+
import type { PRODUCT_SORTS, SHOPPER_ORDER_STAGES } from "./catalog.js";
|
|
1
3
|
import { z } from "zod";
|
|
2
4
|
import { ProductSchema, ProductListSchema, CategorySchema, ProductImageSchema, ProductVariantSchema, OfferSchema, QuantityPricingSchema, PageDocumentPayloadSchema } from "./schemas.js";
|
|
3
5
|
export type Product = z.infer<typeof ProductSchema>;
|
|
@@ -221,6 +223,10 @@ export interface StoreCollection {
|
|
|
221
223
|
/** In the client's language when the store translated it, else the primary. */
|
|
222
224
|
title: string;
|
|
223
225
|
description: string | null;
|
|
226
|
+
/** How many products a shopper sees in it; absent from a server that predates it. */
|
|
227
|
+
productCount?: number | null | undefined;
|
|
228
|
+
/** Its first listed product's first photo, until a merchant can pick one; absent from a server that predates it. */
|
|
229
|
+
image?: ProductImage | null | undefined;
|
|
224
230
|
}
|
|
225
231
|
/** A navigation menu — GET /store/menus/{handle}. */
|
|
226
232
|
export interface StoreMenu {
|
|
@@ -366,7 +372,7 @@ export interface CartValidation {
|
|
|
366
372
|
* Why a code does not apply. Open: a server may name a reason this SDK has not
|
|
367
373
|
* seen yet, and a theme then shows its general sentence.
|
|
368
374
|
*/
|
|
369
|
-
export type CouponRefusalReason =
|
|
375
|
+
export type CouponRefusalReason = (typeof COUPON_REFUSAL_REASONS)[number] | (string & {});
|
|
370
376
|
export interface CouponRefusal {
|
|
371
377
|
reason: CouponRefusalReason;
|
|
372
378
|
/** The dinars (`below_minimum_subtotal`) or items (`below_minimum_quantity`) still missing. */
|
|
@@ -480,6 +486,39 @@ export interface OrderTracking {
|
|
|
480
486
|
pixelId: string | null;
|
|
481
487
|
event: "Purchase" | "Lead" | null;
|
|
482
488
|
}
|
|
489
|
+
/**
|
|
490
|
+
* Where an order is, in a shopper's words: `placed` (not confirmed yet),
|
|
491
|
+
* `confirmed`, `preparing`, `shipped`, `out_for_delivery`, `delivered`,
|
|
492
|
+
* `returned` (refused at the door) or `cancelled`. Open: a newer server may
|
|
493
|
+
* name another step, which a theme shows with its general words.
|
|
494
|
+
*/
|
|
495
|
+
export type ShopperOrderStage = (typeof SHOPPER_ORDER_STAGES)[number] | (string & {});
|
|
496
|
+
/** What `orders.status()` answers: what a shopper may know of their order, never its address or notes. */
|
|
497
|
+
export interface ShopperOrderStatus {
|
|
498
|
+
orderNumber: string;
|
|
499
|
+
/** When it was placed (ISO 8601). */
|
|
500
|
+
placedAt: string;
|
|
501
|
+
stage: ShopperOrderStage;
|
|
502
|
+
deliveryType: "home" | "stop_desk";
|
|
503
|
+
/** As sold, in the catalog's language. */
|
|
504
|
+
lines: {
|
|
505
|
+
name: string;
|
|
506
|
+
variantLabel: string | null;
|
|
507
|
+
quantity: number;
|
|
508
|
+
}[];
|
|
509
|
+
/** What the shopper pays on delivery. */
|
|
510
|
+
total: number;
|
|
511
|
+
/** The carrier's tracking number once the parcel is with it; null before, or with the store's own driver. */
|
|
512
|
+
tracking: {
|
|
513
|
+
number: string;
|
|
514
|
+
carrier: string | null;
|
|
515
|
+
} | null;
|
|
516
|
+
}
|
|
517
|
+
/** What `orders.status()` sends: the order's number and the phone it was placed with. */
|
|
518
|
+
export interface ShopperOrderProof {
|
|
519
|
+
orderNumber: string;
|
|
520
|
+
phone: string;
|
|
521
|
+
}
|
|
483
522
|
/** POST /store/otp/send success payload. */
|
|
484
523
|
export type OtpSendResult = {
|
|
485
524
|
status: "sent";
|
|
@@ -581,16 +620,25 @@ export interface ProductListFilters {
|
|
|
581
620
|
onSale?: boolean;
|
|
582
621
|
/** @deprecated Use `collection: "featured"`. */
|
|
583
622
|
featured?: boolean;
|
|
623
|
+
/**
|
|
624
|
+
* The order. Absent: the listing's own — a collection's, a search's best
|
|
625
|
+
* match first, else newest. A server that predates sorting ignores it.
|
|
626
|
+
*/
|
|
627
|
+
sort?: ProductSort;
|
|
584
628
|
/** Server-side cap; the server clamps anything larger. */
|
|
585
629
|
limit?: number;
|
|
586
630
|
/** Products to skip — with `limit`, pages through the whole catalog. */
|
|
587
631
|
offset?: number;
|
|
588
632
|
}
|
|
589
|
-
/**
|
|
633
|
+
/** How a listing can be ordered: `PRODUCT_SORTS`. */
|
|
634
|
+
export type ProductSort = (typeof PRODUCT_SORTS)[number];
|
|
635
|
+
/** One page of products from `products.page()` or `products.search()`. */
|
|
590
636
|
export interface ProductPage {
|
|
591
637
|
items: ProductList[];
|
|
592
638
|
/** True when another page follows this one. */
|
|
593
639
|
hasNext: boolean;
|
|
640
|
+
/** How many products the whole listing holds, across its pages; null from a server that predates counts. */
|
|
641
|
+
total: number | null;
|
|
594
642
|
}
|
|
595
643
|
/** `products.reviews.list()` paging — named for the same reason. */
|
|
596
644
|
export interface ReviewListPagination {
|
package/dist/utils/image.d.ts
CHANGED
|
@@ -65,6 +65,54 @@ export declare function mediaImageUrl(originalUrl: string, params: MediaImagePar
|
|
|
65
65
|
* makes an empty one), whitespace, control characters, a backslash, `?` or `#`.
|
|
66
66
|
*/
|
|
67
67
|
export declare function mediaUrl(key: string, mediaDomain?: string): string | null;
|
|
68
|
+
export interface MediaImageSrcsetOptions {
|
|
69
|
+
/** The store's media domain; without one there is no srcset. */
|
|
70
|
+
mediaDomain?: string;
|
|
71
|
+
/** Height ÷ width: given, each size is cropped to it (`fit=cover`); absent, the photo keeps its shape (`fit=scale-down`). */
|
|
72
|
+
ratio?: number;
|
|
73
|
+
/** Encoder quality, 1–100; Cloudflare's default when absent. */
|
|
74
|
+
quality?: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The same photo at several widths, with width descriptors
|
|
78
|
+
* (`… 360w, … 720w`), for an `<img>` whose `sizes` says how wide it shows —
|
|
79
|
+
* a phone then downloads a phone-sized file. Each size is converted to the
|
|
80
|
+
* best format the browser takes (`format=auto`).
|
|
81
|
+
*
|
|
82
|
+
* @returns `null` when there is no media domain, the URL is not on it, or no
|
|
83
|
+
* width is a positive whole number.
|
|
84
|
+
*/
|
|
85
|
+
export declare function mediaImageSrcset(src: string, widths: readonly number[], options?: MediaImageSrcsetOptions): string | null;
|
|
86
|
+
/** An image a merchant picked, by its media key — what a theme's `image` field resolves to. */
|
|
87
|
+
export interface PickedImage {
|
|
88
|
+
key: string;
|
|
89
|
+
alt?: string;
|
|
90
|
+
width?: number;
|
|
91
|
+
height?: number;
|
|
92
|
+
/** The point to keep in view when the photo is cropped, each axis 0–1. */
|
|
93
|
+
focal?: {
|
|
94
|
+
x: number;
|
|
95
|
+
y: number;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** A picked image ready for an `<img>`: its URL, its text alternative, its size, and where a crop centres. */
|
|
99
|
+
export interface Picture {
|
|
100
|
+
src: string;
|
|
101
|
+
alt: string;
|
|
102
|
+
width: number | undefined;
|
|
103
|
+
height: number | undefined;
|
|
104
|
+
/** CSS `object-position` from the focal point (`30% 70%`); undefined without one. */
|
|
105
|
+
position: string | undefined;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* A picked image as a theme draws it: its URL on the store's media domain,
|
|
109
|
+
* its alt text (empty when the merchant wrote none), its size, and its focal
|
|
110
|
+
* point as `object-position`, so a cropped photo keeps what matters in view.
|
|
111
|
+
*
|
|
112
|
+
* @returns `null` when no image is picked, the key cannot name an object, or
|
|
113
|
+
* the store has no media domain.
|
|
114
|
+
*/
|
|
115
|
+
export declare function pictureOf(image: PickedImage | null | undefined, mediaDomain?: string): Picture | null;
|
|
68
116
|
/**
|
|
69
117
|
* Predefined image sizes for common use cases
|
|
70
118
|
*/
|
package/dist/utils/image.js
CHANGED
|
@@ -93,6 +93,57 @@ export function mediaUrl(key, mediaDomain) {
|
|
|
93
93
|
const origin = mediaOriginOf(mediaDomain);
|
|
94
94
|
return origin === null ? null : `${origin}/${segments.map(encodeURIComponent).join("/")}`;
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* The same photo at several widths, with width descriptors
|
|
98
|
+
* (`… 360w, … 720w`), for an `<img>` whose `sizes` says how wide it shows —
|
|
99
|
+
* a phone then downloads a phone-sized file. Each size is converted to the
|
|
100
|
+
* best format the browser takes (`format=auto`).
|
|
101
|
+
*
|
|
102
|
+
* @returns `null` when there is no media domain, the URL is not on it, or no
|
|
103
|
+
* width is a positive whole number.
|
|
104
|
+
*/
|
|
105
|
+
export function mediaImageSrcset(src, widths, options = {}) {
|
|
106
|
+
const sizes = [...new Set(widths.filter((width) => Number.isInteger(width) && width > 0))].sort((a, b) => a - b);
|
|
107
|
+
if (sizes.length === 0)
|
|
108
|
+
return null;
|
|
109
|
+
const { ratio, quality, mediaDomain } = options;
|
|
110
|
+
const cropped = ratio !== undefined && Number.isFinite(ratio) && ratio > 0;
|
|
111
|
+
const encoding = quality === undefined ? {} : { quality };
|
|
112
|
+
const entries = [];
|
|
113
|
+
for (const width of sizes) {
|
|
114
|
+
const url = mediaImageUrl(src, cropped
|
|
115
|
+
? { width, height: Math.max(1, Math.round(width * ratio)), fit: "cover", format: "auto", ...encoding }
|
|
116
|
+
: { width, fit: "scale-down", format: "auto", ...encoding }, mediaDomain);
|
|
117
|
+
if (url === null)
|
|
118
|
+
return null;
|
|
119
|
+
entries.push(`${url} ${width}w`);
|
|
120
|
+
}
|
|
121
|
+
return entries.join(", ");
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* A picked image as a theme draws it: its URL on the store's media domain,
|
|
125
|
+
* its alt text (empty when the merchant wrote none), its size, and its focal
|
|
126
|
+
* point as `object-position`, so a cropped photo keeps what matters in view.
|
|
127
|
+
*
|
|
128
|
+
* @returns `null` when no image is picked, the key cannot name an object, or
|
|
129
|
+
* the store has no media domain.
|
|
130
|
+
*/
|
|
131
|
+
export function pictureOf(image, mediaDomain) {
|
|
132
|
+
if (!image)
|
|
133
|
+
return null;
|
|
134
|
+
const src = mediaUrl(image.key, mediaDomain);
|
|
135
|
+
if (src === null)
|
|
136
|
+
return null;
|
|
137
|
+
const percent = (value) => `${Math.round(Math.min(1, Math.max(0, value)) * 100)}%`;
|
|
138
|
+
const focal = image.focal;
|
|
139
|
+
return {
|
|
140
|
+
src,
|
|
141
|
+
alt: image.alt ?? "",
|
|
142
|
+
width: image.width,
|
|
143
|
+
height: image.height,
|
|
144
|
+
position: focal && Number.isFinite(focal.x) && Number.isFinite(focal.y) ? `${percent(focal.x)} ${percent(focal.y)}` : undefined,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
96
147
|
/**
|
|
97
148
|
* Predefined image sizes for common use cases
|
|
98
149
|
*/
|
package/package.json
CHANGED