@wocart/storefront 2.2.0 → 3.1.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 +138 -0
- package/USAGE.md +189 -95
- package/dist/answer-readers.js +16 -43
- package/dist/astro.d.ts +6 -2
- package/dist/astro.js +3 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/products.d.ts +2 -3
- package/dist/client/products.js +2 -3
- package/dist/endpoints/revalidate-endpoint.d.ts +37 -0
- package/dist/endpoints/revalidate-endpoint.js +32 -0
- package/dist/endpoints/storefront-routes.js +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.js +4 -2
- package/dist/locale-routing.d.ts +11 -20
- package/dist/locale-routing.js +28 -8
- package/dist/middleware.d.ts +6 -26
- package/dist/middleware.js +0 -9
- package/dist/product-view.d.ts +0 -8
- package/dist/product-view.js +0 -17
- package/dist/revalidate.d.ts +6 -0
- package/dist/revalidate.js +6 -0
- package/dist/routes.d.ts +44 -27
- package/dist/routes.js +54 -13
- package/dist/schemas.d.ts +144 -222
- package/dist/schemas.js +77 -137
- package/dist/seo.js +2 -2
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/dist/store-request.d.ts +5 -4
- package/dist/store-request.js +1 -1
- package/dist/storefront-middleware.d.ts +88 -0
- package/dist/storefront-middleware.js +37 -0
- package/dist/thank-you.d.ts +32 -0
- package/dist/thank-you.js +33 -0
- package/dist/types.d.ts +76 -111
- package/dist/unavailable-store.d.ts +23 -0
- package/dist/unavailable-store.js +58 -0
- package/dist/variant-picker.d.ts +6 -2
- package/dist/variant-picker.js +6 -9
- package/dist/whatsapp.d.ts +59 -6
- package/dist/whatsapp.js +28 -10
- package/package.json +1 -1
package/dist/routes.d.ts
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The storefront's page types and their public paths.
|
|
3
|
-
*
|
|
4
|
-
* A page type is what a URL *means* — a product, a category, a store page, a
|
|
5
|
-
* landing page — and the path is where it lives. The paths are a platform
|
|
6
|
-
* contract, not a theme decision: the platform builds them without running
|
|
7
|
-
* the theme (the dashboard shows a page's public link, the server names the
|
|
8
|
-
* landing page in a conversion's source URL), so a theme renders each page
|
|
9
|
-
* type it supports at its path and builds every link to one with
|
|
10
|
-
* `storefrontPath` — never a hand-written string. Any other route is the
|
|
11
|
-
* theme's own (`/about`, `/offers/summer` …): Astro's file routing owns those,
|
|
12
|
-
* and nothing here constrains them.
|
|
13
|
-
*
|
|
14
|
-
* Language prefixes are applied on top: `localizeHref(storefrontPath(…),
|
|
15
|
-
* locale, routing)`.
|
|
16
|
-
*/
|
|
17
1
|
import type { WidgetSurfaces } from "./types.js";
|
|
18
2
|
/** Each page type's public path; `:handle` / `:slug` mark its one parameter. */
|
|
19
3
|
export declare const STOREFRONT_PAGE_PATHS: {
|
|
@@ -28,6 +12,10 @@ export declare const STOREFRONT_PAGE_PATHS: {
|
|
|
28
12
|
readonly thankYou: "/thank-you";
|
|
29
13
|
/** Where a shopper follows an order by its number and phone; `?order=<number>` fills the number in. */
|
|
30
14
|
readonly trackOrder: "/track-order";
|
|
15
|
+
/** The store's products matching a query; `?q=<words>` is the query. */
|
|
16
|
+
readonly search: "/search";
|
|
17
|
+
/** How to reach the store: its WhatsApp, phone, email and address. */
|
|
18
|
+
readonly contact: "/contact";
|
|
31
19
|
};
|
|
32
20
|
/** What a storefront URL means. */
|
|
33
21
|
export type StorefrontPageType = keyof typeof STOREFRONT_PAGE_PATHS;
|
|
@@ -48,6 +36,39 @@ export interface StorefrontPageMatch {
|
|
|
48
36
|
* not a path to render.
|
|
49
37
|
*/
|
|
50
38
|
export declare function storefrontPath<T extends StorefrontPageType>(type: T, params?: StorefrontPathParams<T>): string;
|
|
39
|
+
/**
|
|
40
|
+
* Where a theme mounts each of `createStorefrontRoutes`' routes
|
|
41
|
+
* (`src/pages/api/…`), and where its browser scripts call them: one table,
|
|
42
|
+
* keyed like `StorefrontRoutes`, so the route files and the scripts never
|
|
43
|
+
* drift. Defaults, not requirements: every browser helper still takes its
|
|
44
|
+
* `endpoint`. `:wilayaId` and `:productId` mark a route's one parameter.
|
|
45
|
+
* `orderStatus` has no path here: a theme follows an order through its
|
|
46
|
+
* `orderStatus` action, not a route.
|
|
47
|
+
*/
|
|
48
|
+
export declare const STOREFRONT_API_PATHS: {
|
|
49
|
+
readonly otpSend: "/api/otp/send";
|
|
50
|
+
readonly otpVerify: "/api/otp/verify";
|
|
51
|
+
readonly cartValidate: "/api/cart/validate";
|
|
52
|
+
readonly abandonedUpsert: "/api/abandoned/upsert";
|
|
53
|
+
readonly abandonedConvert: "/api/abandoned/convert";
|
|
54
|
+
readonly communes: "/api/communes/:wilayaId";
|
|
55
|
+
readonly reviewsList: "/api/reviews/:productId";
|
|
56
|
+
readonly reviewEligibility: "/api/reviews/eligibility";
|
|
57
|
+
readonly reviewUpload: "/api/reviews/upload";
|
|
58
|
+
readonly reviewSubmit: "/api/reviews/submit";
|
|
59
|
+
};
|
|
60
|
+
/** A storefront route of `createStorefrontRoutes`. */
|
|
61
|
+
export type StorefrontApiName = keyof typeof STOREFRONT_API_PATHS;
|
|
62
|
+
/** The parameter a route's path needs: `{ wilayaId }` for the communes, `{ productId }` for a product's reviews, nothing otherwise. */
|
|
63
|
+
export type StorefrontApiParams<N extends StorefrontApiName> = ParamOf<(typeof STOREFRONT_API_PATHS)[N]> extends never ? Record<string, never> : {
|
|
64
|
+
[K in ParamOf<(typeof STOREFRONT_API_PATHS)[N]>]: string | number;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* A storefront route's same-origin path, its parameter encoded:
|
|
68
|
+
* `storefrontApiPath("communes", { wilayaId: 16 })` → `/api/communes/16`.
|
|
69
|
+
* Throws when the parameter is missing.
|
|
70
|
+
*/
|
|
71
|
+
export declare function storefrontApiPath<N extends StorefrontApiName>(name: N, params?: StorefrontApiParams<N>): string;
|
|
51
72
|
/**
|
|
52
73
|
* Which page type a pathname is, and its parameter (decoded) — or null for
|
|
53
74
|
* any other path. Exact matches only: `/products/` is the catalog,
|
|
@@ -56,19 +77,15 @@ export declare function storefrontPath<T extends StorefrontPageType>(type: T, pa
|
|
|
56
77
|
* language prefix (`resolveLocalePath` gives it).
|
|
57
78
|
*/
|
|
58
79
|
export declare function matchStorefrontPath(rawPathname: string): StorefrontPageMatch | null;
|
|
59
|
-
/** One route with a parameter or a fixed path of its own, and the widget surface that renders it. */
|
|
60
|
-
export interface StorefrontRoute {
|
|
61
|
-
/** Path pattern; `:handle` and `:slug` mark the single path parameter. */
|
|
62
|
-
readonly path: string;
|
|
63
|
-
/** The `surfaces` key this route belongs to. */
|
|
64
|
-
readonly surface: keyof WidgetSurfaces;
|
|
65
|
-
}
|
|
66
80
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
81
|
+
* The page types that exist in the store's primary language only. A landing
|
|
82
|
+
* page is one campaign — a stack of images and one order form, written once
|
|
83
|
+
* for the ads that point at it — so it has no `/fr/lp/…` address, no language
|
|
84
|
+
* menu and no alternate links.
|
|
70
85
|
*/
|
|
71
|
-
export declare const
|
|
86
|
+
export declare const SINGLE_LANGUAGE_PAGE_TYPES: readonly StorefrontPageType[];
|
|
87
|
+
/** Whether a pathname (without its language prefix) is a page that exists in the primary language only. */
|
|
88
|
+
export declare function isSingleLanguagePage(rawPathname: string): boolean;
|
|
72
89
|
/**
|
|
73
90
|
* Whether the widget belongs on a pathname: the merchant answers "which
|
|
74
91
|
* surfaces" (`surfaces[surface]`); this answers which surface a pathname *is*,
|
package/dist/routes.js
CHANGED
|
@@ -11,6 +11,10 @@ export const STOREFRONT_PAGE_PATHS = {
|
|
|
11
11
|
thankYou: "/thank-you",
|
|
12
12
|
/** Where a shopper follows an order by its number and phone; `?order=<number>` fills the number in. */
|
|
13
13
|
trackOrder: "/track-order",
|
|
14
|
+
/** The store's products matching a query; `?q=<words>` is the query. */
|
|
15
|
+
search: "/search",
|
|
16
|
+
/** How to reach the store: its WhatsApp, phone, email and address. */
|
|
17
|
+
contact: "/contact",
|
|
14
18
|
};
|
|
15
19
|
/**
|
|
16
20
|
* The public path of a page type, its parameter encoded:
|
|
@@ -19,13 +23,45 @@ export const STOREFRONT_PAGE_PATHS = {
|
|
|
19
23
|
* not a path to render.
|
|
20
24
|
*/
|
|
21
25
|
export function storefrontPath(type, params) {
|
|
22
|
-
return STOREFRONT_PAGE_PATHS[type]
|
|
26
|
+
return fillPath(STOREFRONT_PAGE_PATHS[type], `storefrontPath("${type}")`, params);
|
|
27
|
+
}
|
|
28
|
+
function fillPath(template, caller, params) {
|
|
29
|
+
return template.replace(/:([a-zA-Z]+)/g, (_, name) => {
|
|
23
30
|
const value = params?.[name];
|
|
24
|
-
if (
|
|
25
|
-
throw new Error(
|
|
26
|
-
return encodeURIComponent(value);
|
|
31
|
+
if (value === undefined || value === "")
|
|
32
|
+
throw new Error(`${caller} needs "${name}"`);
|
|
33
|
+
return encodeURIComponent(String(value));
|
|
27
34
|
});
|
|
28
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Where a theme mounts each of `createStorefrontRoutes`' routes
|
|
38
|
+
* (`src/pages/api/…`), and where its browser scripts call them: one table,
|
|
39
|
+
* keyed like `StorefrontRoutes`, so the route files and the scripts never
|
|
40
|
+
* drift. Defaults, not requirements: every browser helper still takes its
|
|
41
|
+
* `endpoint`. `:wilayaId` and `:productId` mark a route's one parameter.
|
|
42
|
+
* `orderStatus` has no path here: a theme follows an order through its
|
|
43
|
+
* `orderStatus` action, not a route.
|
|
44
|
+
*/
|
|
45
|
+
export const STOREFRONT_API_PATHS = {
|
|
46
|
+
otpSend: "/api/otp/send",
|
|
47
|
+
otpVerify: "/api/otp/verify",
|
|
48
|
+
cartValidate: "/api/cart/validate",
|
|
49
|
+
abandonedUpsert: "/api/abandoned/upsert",
|
|
50
|
+
abandonedConvert: "/api/abandoned/convert",
|
|
51
|
+
communes: "/api/communes/:wilayaId",
|
|
52
|
+
reviewsList: "/api/reviews/:productId",
|
|
53
|
+
reviewEligibility: "/api/reviews/eligibility",
|
|
54
|
+
reviewUpload: "/api/reviews/upload",
|
|
55
|
+
reviewSubmit: "/api/reviews/submit",
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* A storefront route's same-origin path, its parameter encoded:
|
|
59
|
+
* `storefrontApiPath("communes", { wilayaId: 16 })` → `/api/communes/16`.
|
|
60
|
+
* Throws when the parameter is missing.
|
|
61
|
+
*/
|
|
62
|
+
export function storefrontApiPath(name, params) {
|
|
63
|
+
return fillPath(STOREFRONT_API_PATHS[name], `storefrontApiPath("${name}")`, params);
|
|
64
|
+
}
|
|
29
65
|
const MATCHERS = Object.entries(STOREFRONT_PAGE_PATHS).map(([type, path]) => {
|
|
30
66
|
const names = [];
|
|
31
67
|
const source = path.replace(/:([a-z]+)/g, (_, name) => {
|
|
@@ -56,6 +92,18 @@ export function matchStorefrontPath(rawPathname) {
|
|
|
56
92
|
}
|
|
57
93
|
return null;
|
|
58
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* The page types that exist in the store's primary language only. A landing
|
|
97
|
+
* page is one campaign — a stack of images and one order form, written once
|
|
98
|
+
* for the ads that point at it — so it has no `/fr/lp/…` address, no language
|
|
99
|
+
* menu and no alternate links.
|
|
100
|
+
*/
|
|
101
|
+
export const SINGLE_LANGUAGE_PAGE_TYPES = ["landing"];
|
|
102
|
+
/** Whether a pathname (without its language prefix) is a page that exists in the primary language only. */
|
|
103
|
+
export function isSingleLanguagePage(rawPathname) {
|
|
104
|
+
const match = matchStorefrontPath(rawPathname);
|
|
105
|
+
return match !== null && SINGLE_LANGUAGE_PAGE_TYPES.includes(match.type);
|
|
106
|
+
}
|
|
59
107
|
/** The WhatsApp widget surface each page type belongs to (the home surface is the root). */
|
|
60
108
|
const WIDGET_SURFACE = {
|
|
61
109
|
home: "home",
|
|
@@ -68,16 +116,9 @@ const WIDGET_SURFACE = {
|
|
|
68
116
|
checkout: "checkout",
|
|
69
117
|
thankYou: "thankYou",
|
|
70
118
|
trackOrder: "pages",
|
|
119
|
+
search: "pages",
|
|
120
|
+
contact: "pages",
|
|
71
121
|
};
|
|
72
|
-
/**
|
|
73
|
-
* @deprecated Use `STOREFRONT_PAGE_PATHS` (every page type, the home and the
|
|
74
|
-
* catalog index included) with `storefrontPath` and `matchStorefrontPath`.
|
|
75
|
-
* Kept equal to what it always listed.
|
|
76
|
-
*/
|
|
77
|
-
export const STOREFRONT_ROUTES = ["product", "category", "page", "landing", "checkout", "thankYou"].map((type) => ({
|
|
78
|
-
path: STOREFRONT_PAGE_PATHS[type],
|
|
79
|
-
surface: WIDGET_SURFACE[type],
|
|
80
|
-
}));
|
|
81
122
|
/**
|
|
82
123
|
* Whether the widget belongs on a pathname: the merchant answers "which
|
|
83
124
|
* surfaces" (`surfaces[surface]`); this answers which surface a pathname *is*,
|