@tiendanube/nube-sdk-helper 0.0.1
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 +174 -0
- package/dist/index.cjs +449 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1167 -0
- package/dist/index.d.ts +1167 -0
- package/dist/index.js +373 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# `@tiendanube/nube-sdk-helper`
|
|
2
|
+
|
|
3
|
+
**Utility functions, type guards, and SDK instance management for building NubeSDK apps.**
|
|
4
|
+
|
|
5
|
+
## About
|
|
6
|
+
|
|
7
|
+
`@tiendanube/nube-sdk-helper` centralizes the repetitive patterns that NubeSDK
|
|
8
|
+
apps need: registering and accessing the SDK instance, reading state with
|
|
9
|
+
selectors, runtime type guards, page/checkout handling, rendering, and event
|
|
10
|
+
subscriptions. The goal is less boilerplate and stronger type safety.
|
|
11
|
+
|
|
12
|
+
Apps in NubeSDK run **inside isolated web workers**, without direct access to the
|
|
13
|
+
DOM. All helpers are designed for that environment and interact with the
|
|
14
|
+
platform exclusively through the SDK instance.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npm install @tiendanube/nube-sdk-helper @tiendanube/nube-sdk-types
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
> Note: `@tiendanube/nube-sdk-types` is a peer dependency and must be installed alongside this package.
|
|
23
|
+
|
|
24
|
+
## Instance management
|
|
25
|
+
|
|
26
|
+
The NubeSDK runtime passes the SDK instance only as the argument of your app
|
|
27
|
+
entry point (`App(nube)`). Register it once with `setNubeInstance` and every
|
|
28
|
+
other helper (`getCurrentState`, `ui`, `browser`, selectors, `onPage`, ...) can
|
|
29
|
+
access it without you having to thread `nube` through every function and
|
|
30
|
+
component.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import {
|
|
34
|
+
setNubeInstance,
|
|
35
|
+
getCurrentState,
|
|
36
|
+
getNubeInstance,
|
|
37
|
+
ui,
|
|
38
|
+
} from "@tiendanube/nube-sdk-helper";
|
|
39
|
+
import type { NubeSDK } from "@tiendanube/nube-sdk-types";
|
|
40
|
+
|
|
41
|
+
export function App(nube: NubeSDK) {
|
|
42
|
+
setNubeInstance(nube); // call this first
|
|
43
|
+
|
|
44
|
+
const state = getCurrentState();
|
|
45
|
+
ui.showToast(`You are on the ${state.location.page.type} page`);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- `setNubeInstance(nube)` — registers the instance (call once at the top of `App`).
|
|
50
|
+
- `getNubeInstance()` — returns the registered instance; throws a descriptive
|
|
51
|
+
error if you forgot to register it.
|
|
52
|
+
- `clearNubeInstance()` — clears the registered instance (useful in tests).
|
|
53
|
+
|
|
54
|
+
## State access
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import {
|
|
58
|
+
getCurrentState,
|
|
59
|
+
getCart,
|
|
60
|
+
getCartItems,
|
|
61
|
+
getPageType,
|
|
62
|
+
getCustomer,
|
|
63
|
+
getAppData,
|
|
64
|
+
getScriptParam,
|
|
65
|
+
} from "@tiendanube/nube-sdk-helper";
|
|
66
|
+
|
|
67
|
+
// Selectors read the current state by default; pass a state to keep them pure.
|
|
68
|
+
const items = getCartItems();
|
|
69
|
+
const pageType = getPageType();
|
|
70
|
+
const customer = getCustomer();
|
|
71
|
+
|
|
72
|
+
// App data injected by the runtime
|
|
73
|
+
const { id } = getAppData();
|
|
74
|
+
const variant = getScriptParam("variant"); // ?variant=... on the app script URL
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Pages and checkout
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { pageMatch, onPage, onCheckoutStep } from "@tiendanube/nube-sdk-helper";
|
|
81
|
+
|
|
82
|
+
// One-off dispatch on the current page:
|
|
83
|
+
pageMatch(getCurrentState(), {
|
|
84
|
+
product: (state, product) => console.log(product.name),
|
|
85
|
+
checkout: (state, checkout) => console.log(checkout.step),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Subscribe to navigation. Both return an unsubscribe function:
|
|
89
|
+
const stop = onPage({
|
|
90
|
+
product: (state, product) => trackProductView(product.id),
|
|
91
|
+
});
|
|
92
|
+
// stop(); // when you no longer need it
|
|
93
|
+
|
|
94
|
+
onCheckoutStep({
|
|
95
|
+
success: () => trackPurchase(),
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Events
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { onEvent, toastOn } from "@tiendanube/nube-sdk-helper";
|
|
103
|
+
|
|
104
|
+
// Thin wrapper around nube.on that returns an unsubscribe:
|
|
105
|
+
const off = onEvent("cart:update", (state) => {
|
|
106
|
+
console.log("items:", state.cart.items.length);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Show a toast whenever an event fires:
|
|
110
|
+
toastOn("cart:add:success", "Added to cart", "success");
|
|
111
|
+
toastOn("cart:update", (state) => `Cart: ${state.cart.items.length} items`);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Rendering
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { ui, forEachProduct } from "@tiendanube/nube-sdk-helper";
|
|
118
|
+
|
|
119
|
+
// Render the same component into many slots at once:
|
|
120
|
+
ui.renderAll(["corner_top_left", "corner_top_right"], { type: "txt", children: "Hi" });
|
|
121
|
+
|
|
122
|
+
// Render one component per product on the current page (keys are added automatically):
|
|
123
|
+
getNubeInstance().render(
|
|
124
|
+
"product_grid_item_image_bottom_right",
|
|
125
|
+
forEachProduct((product) => ({ type: "txt", children: product.name })),
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
ui.showToast("Done!", "success");
|
|
129
|
+
ui.clear("corner_top_right");
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Browser APIs
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { browser, navigate } from "@tiendanube/nube-sdk-helper";
|
|
136
|
+
|
|
137
|
+
await browser.asyncLocalStorage.setItem("key", "value");
|
|
138
|
+
navigate("/products/123");
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Type guards
|
|
142
|
+
|
|
143
|
+
Runtime checks that also narrow types for TypeScript:
|
|
144
|
+
|
|
145
|
+
- Pages: `isProductPage`, `isCategoryPage`, `isCheckoutPage`, `isHomePage`,
|
|
146
|
+
`isAllProductsPage`, `isSearchPage`
|
|
147
|
+
- Cart: `isCart`, `isCartItem`, `isCartValidationSuccess` / `Pending` / `Fail`
|
|
148
|
+
- Domain: `isStore`, `isCustomer`, `isPayment`, `isShipping`, `isShippingOption`,
|
|
149
|
+
`isAddress`, `isShippingAddress`, `isBillingAddress`
|
|
150
|
+
- Components / page data: `isNubeComponent`, `hasProductList`, `hasSections`,
|
|
151
|
+
`hasSingleProduct`, `isSectionWithProducts`
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { isProductPage } from "@tiendanube/nube-sdk-helper";
|
|
155
|
+
|
|
156
|
+
const { page } = getCurrentState().location;
|
|
157
|
+
if (isProductPage(page)) {
|
|
158
|
+
console.log(page.data.product.name);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## General utilities
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import { deepClone, debounce, throttle } from "@tiendanube/nube-sdk-helper";
|
|
166
|
+
|
|
167
|
+
const copy = deepClone(state); // uses structuredClone when available
|
|
168
|
+
const debounced = debounce((q: string) => search(q), 300);
|
|
169
|
+
const throttled = throttle(() => onScroll(), 100);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
browser: () => browser,
|
|
24
|
+
clearBrowserCache: () => clearBrowserCache,
|
|
25
|
+
clearNubeInstance: () => clearNubeInstance,
|
|
26
|
+
debounce: () => debounce,
|
|
27
|
+
deepClone: () => deepClone,
|
|
28
|
+
forEachProduct: () => forEachProduct,
|
|
29
|
+
getAppData: () => getAppData,
|
|
30
|
+
getCart: () => getCart,
|
|
31
|
+
getCartItems: () => getCartItems,
|
|
32
|
+
getCurrentState: () => getCurrentState,
|
|
33
|
+
getCustomer: () => getCustomer,
|
|
34
|
+
getNubeInstance: () => getNubeInstance,
|
|
35
|
+
getPageType: () => getPageType,
|
|
36
|
+
getProductsFromState: () => getProductsFromState,
|
|
37
|
+
getScriptParam: () => getScriptParam,
|
|
38
|
+
getScriptSearchParams: () => getScriptSearchParams,
|
|
39
|
+
getScriptURL: () => getScriptURL,
|
|
40
|
+
hasProductList: () => hasProductList,
|
|
41
|
+
hasSections: () => hasSections,
|
|
42
|
+
hasSingleProduct: () => hasSingleProduct,
|
|
43
|
+
isAddress: () => isAddress,
|
|
44
|
+
isAllProductsPage: () => isAllProductsPage,
|
|
45
|
+
isBillingAddress: () => isBillingAddress,
|
|
46
|
+
isCart: () => isCart,
|
|
47
|
+
isCartItem: () => isCartItem,
|
|
48
|
+
isCartValidationFail: () => isCartValidationFail,
|
|
49
|
+
isCartValidationPending: () => isCartValidationPending,
|
|
50
|
+
isCartValidationSuccess: () => isCartValidationSuccess,
|
|
51
|
+
isCategoryPage: () => isCategoryPage,
|
|
52
|
+
isCheckoutPage: () => isCheckoutPage,
|
|
53
|
+
isCustomer: () => isCustomer,
|
|
54
|
+
isHomePage: () => isHomePage,
|
|
55
|
+
isNubeComponent: () => isNubeComponent,
|
|
56
|
+
isPayment: () => isPayment,
|
|
57
|
+
isProductPage: () => isProductPage,
|
|
58
|
+
isSearchPage: () => isSearchPage,
|
|
59
|
+
isSectionWithProducts: () => isSectionWithProducts,
|
|
60
|
+
isShipping: () => isShipping,
|
|
61
|
+
isShippingAddress: () => isShippingAddress,
|
|
62
|
+
isShippingOption: () => isShippingOption,
|
|
63
|
+
isStore: () => isStore,
|
|
64
|
+
navigate: () => navigate,
|
|
65
|
+
onCheckoutStep: () => onCheckoutStep,
|
|
66
|
+
onEvent: () => onEvent,
|
|
67
|
+
onPage: () => onPage,
|
|
68
|
+
pageMatch: () => pageMatch,
|
|
69
|
+
setNubeInstance: () => setNubeInstance,
|
|
70
|
+
throttle: () => throttle,
|
|
71
|
+
toastOn: () => toastOn,
|
|
72
|
+
ui: () => ui
|
|
73
|
+
});
|
|
74
|
+
module.exports = __toCommonJS(index_exports);
|
|
75
|
+
|
|
76
|
+
// src/lib/instance.ts
|
|
77
|
+
var registeredInstance;
|
|
78
|
+
function readGlobalInstance() {
|
|
79
|
+
return typeof self !== "undefined" ? self.__SDK_INSTANCE__ : void 0;
|
|
80
|
+
}
|
|
81
|
+
function setNubeInstance(nube) {
|
|
82
|
+
registeredInstance = nube;
|
|
83
|
+
}
|
|
84
|
+
function getNubeInstance() {
|
|
85
|
+
const instance2 = registeredInstance ?? readGlobalInstance();
|
|
86
|
+
if (!instance2) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
"NubeSDK instance not registered. Call setNubeInstance(nube) at the start of your App(nube) entry point."
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return instance2;
|
|
92
|
+
}
|
|
93
|
+
function clearNubeInstance() {
|
|
94
|
+
registeredInstance = void 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/lib/browser.ts
|
|
98
|
+
var instance = null;
|
|
99
|
+
var browser = new Proxy({}, {
|
|
100
|
+
get(_, prop) {
|
|
101
|
+
if (instance === null) {
|
|
102
|
+
instance = getNubeInstance().getBrowserAPIs();
|
|
103
|
+
}
|
|
104
|
+
return instance[prop];
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
function navigate(route) {
|
|
108
|
+
browser.navigate(route);
|
|
109
|
+
}
|
|
110
|
+
function clearBrowserCache() {
|
|
111
|
+
instance = null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/lib/ui.ts
|
|
115
|
+
var ui = Object.freeze({
|
|
116
|
+
// Helpers for common components
|
|
117
|
+
showToast(message, variant = "info") {
|
|
118
|
+
const toast = {
|
|
119
|
+
type: "toastRoot",
|
|
120
|
+
variant,
|
|
121
|
+
children: [{ type: "toastTitle", children: message }]
|
|
122
|
+
};
|
|
123
|
+
getNubeInstance().render("corner_top_right", toast);
|
|
124
|
+
},
|
|
125
|
+
// Clear slot
|
|
126
|
+
clear(slot) {
|
|
127
|
+
getNubeInstance().clearSlot(slot);
|
|
128
|
+
},
|
|
129
|
+
render(slot, component) {
|
|
130
|
+
getNubeInstance().render(slot, component);
|
|
131
|
+
},
|
|
132
|
+
// Render the same component across multiple slots in a single call.
|
|
133
|
+
renderAll(slots, component) {
|
|
134
|
+
const nube = getNubeInstance();
|
|
135
|
+
for (const slot of slots) {
|
|
136
|
+
nube.render(slot, component);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// src/lib/events.ts
|
|
142
|
+
function onEvent(event, listener) {
|
|
143
|
+
const nube = getNubeInstance();
|
|
144
|
+
nube.on(event, listener);
|
|
145
|
+
return () => nube.off(event, listener);
|
|
146
|
+
}
|
|
147
|
+
function toastOn(event, message, variant) {
|
|
148
|
+
const listener = ((state) => {
|
|
149
|
+
const text = typeof message === "function" ? message(state) : message;
|
|
150
|
+
ui.showToast(text, variant);
|
|
151
|
+
});
|
|
152
|
+
return onEvent(event, listener);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/lib/getters.ts
|
|
156
|
+
function getCurrentState() {
|
|
157
|
+
return getNubeInstance().getState();
|
|
158
|
+
}
|
|
159
|
+
function getAppData() {
|
|
160
|
+
return self.__APP_DATA__;
|
|
161
|
+
}
|
|
162
|
+
var cachedScriptURL;
|
|
163
|
+
function getScriptURL() {
|
|
164
|
+
if (!cachedScriptURL) {
|
|
165
|
+
cachedScriptURL = Object.freeze(new URL(self.__APP_DATA__.script));
|
|
166
|
+
}
|
|
167
|
+
return cachedScriptURL;
|
|
168
|
+
}
|
|
169
|
+
function getScriptSearchParams() {
|
|
170
|
+
return getScriptURL().searchParams;
|
|
171
|
+
}
|
|
172
|
+
function getScriptParam(key) {
|
|
173
|
+
return getScriptSearchParams().get(key);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/internal/primitives.ts
|
|
177
|
+
function isObject(value) {
|
|
178
|
+
return typeof value === "object" && value !== null;
|
|
179
|
+
}
|
|
180
|
+
function isPlainObject(value) {
|
|
181
|
+
return isObject(value) && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/lib/guards/address.ts
|
|
185
|
+
function isAddress(value) {
|
|
186
|
+
return isPlainObject(value) && typeof value.zipcode === "string" && (value.first_name === null || typeof value.first_name === "string") && (value.last_name === null || typeof value.last_name === "string") && (value.address === null || typeof value.address === "string") && (value.number === null || typeof value.number === "string") && (value.floor === null || typeof value.floor === "string") && (value.locality === null || typeof value.locality === "string") && (value.city === null || typeof value.city === "string") && (value.state === null || typeof value.state === "string") && (value.country === null || typeof value.country === "string") && (value.phone === null || typeof value.phone === "string");
|
|
187
|
+
}
|
|
188
|
+
function isShippingAddress(value) {
|
|
189
|
+
return isPlainObject(value) && typeof value.zipcode === "string" && (value.first_name === null || typeof value.first_name === "string") && (value.last_name === null || typeof value.last_name === "string") && (value.address === null || typeof value.address === "string") && (value.number === null || typeof value.number === "string") && (value.floor === null || typeof value.floor === "string") && (value.locality === null || typeof value.locality === "string") && (value.city === null || typeof value.city === "string") && (value.state === null || typeof value.state === "string") && (value.country === null || typeof value.country === "string") && (value.phone === null || typeof value.phone === "string") && (value.between_street === null || typeof value.between_street === "string") && (value.reference === null || typeof value.reference === "string");
|
|
190
|
+
}
|
|
191
|
+
function isBillingAddress(value) {
|
|
192
|
+
return isPlainObject(value) && typeof value.zipcode === "string" && (value.first_name === null || typeof value.first_name === "string") && (value.last_name === null || typeof value.last_name === "string") && (value.address === null || typeof value.address === "string") && (value.number === null || typeof value.number === "string") && (value.floor === null || typeof value.floor === "string") && (value.locality === null || typeof value.locality === "string") && (value.city === null || typeof value.city === "string") && (value.state === null || typeof value.state === "string") && (value.country === null || typeof value.country === "string") && (value.phone === null || typeof value.phone === "string") && (value.id_number === null || typeof value.id_number === "string") && (value.customer_type === null || typeof value.customer_type === "string") && (value.business_name === null || typeof value.business_name === "string") && (value.trade_name === null || typeof value.trade_name === "string") && (value.state_registration === null || typeof value.state_registration === "string") && (value.fiscal_regime === null || typeof value.fiscal_regime === "string") && (value.invoice_use === null || typeof value.invoice_use === "string") && (value.document_type === null || typeof value.document_type === "string") && (value.business_activity === null || typeof value.business_activity === "string");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// src/lib/guards/cart.ts
|
|
196
|
+
function isCart(value) {
|
|
197
|
+
return isPlainObject(value) && typeof value.id === "string" && isPlainObject(value.validation) && typeof value.validation.status === "string" && Array.isArray(value.items) && isPlainObject(value.prices) && typeof value.prices.subtotal === "number" && typeof value.prices.total === "number" && isPlainObject(value.coupon);
|
|
198
|
+
}
|
|
199
|
+
function isCartItem(value) {
|
|
200
|
+
return isPlainObject(value) && typeof value.id === "number" && typeof value.name === "string" && typeof value.price === "string" && typeof value.quantity === "number" && typeof value.free_shipping === "boolean" && typeof value.product_id === "number" && typeof value.variant_id === "number" && typeof value.thumbnail === "string" && typeof value.variant_values === "string" && typeof value.url === "string" && typeof value.is_ahora_12_eligible === "boolean";
|
|
201
|
+
}
|
|
202
|
+
function isCartValidationSuccess(validation) {
|
|
203
|
+
return validation.status === "success";
|
|
204
|
+
}
|
|
205
|
+
function isCartValidationPending(validation) {
|
|
206
|
+
return validation.status === "pending";
|
|
207
|
+
}
|
|
208
|
+
function isCartValidationFail(validation) {
|
|
209
|
+
return validation.status === "fail";
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// src/lib/guards/components.ts
|
|
213
|
+
function isNubeComponent(value) {
|
|
214
|
+
return typeof value === "string" || isPlainObject(value) && typeof value.type === "string";
|
|
215
|
+
}
|
|
216
|
+
function hasProductList(data) {
|
|
217
|
+
return isObject(data) && "products" in data && Array.isArray(data.products);
|
|
218
|
+
}
|
|
219
|
+
function hasSections(data) {
|
|
220
|
+
return isObject(data) && "sections" in data && Array.isArray(data.sections);
|
|
221
|
+
}
|
|
222
|
+
function isSectionWithProducts(item) {
|
|
223
|
+
return isObject(item) && "products" in item && Array.isArray(item.products);
|
|
224
|
+
}
|
|
225
|
+
function hasSingleProduct(data) {
|
|
226
|
+
return isObject(data) && "product" in data && isObject(data.product) && "id" in data.product;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// src/lib/guards/domain.ts
|
|
230
|
+
function isStore(value) {
|
|
231
|
+
return isPlainObject(value) && typeof value.id === "number" && typeof value.name === "string" && typeof value.domain === "string" && typeof value.currency === "string" && typeof value.language === "string";
|
|
232
|
+
}
|
|
233
|
+
function isCustomer(value) {
|
|
234
|
+
return isPlainObject(value) && (value.id === null || typeof value.id === "number") && isPlainObject(value.contact) && isPlainObject(value.shipping_address) && isPlainObject(value.billing_address);
|
|
235
|
+
}
|
|
236
|
+
function isPayment(value) {
|
|
237
|
+
return isPlainObject(value) && (value.status === null || typeof value.status === "string") && (value.selected === null || isPlainObject(value.selected));
|
|
238
|
+
}
|
|
239
|
+
function isShipping(value) {
|
|
240
|
+
return isPlainObject(value) && (value.selected === null || typeof value.selected === "string") && (value.options === void 0 || Array.isArray(value.options)) && (value.custom_labels === void 0 || isPlainObject(value.custom_labels));
|
|
241
|
+
}
|
|
242
|
+
function isShippingOption(value) {
|
|
243
|
+
return isPlainObject(value) && typeof value.id === "string" && typeof value.price === "number" && typeof value.currency === "string" && typeof value.phone_required === "boolean" && typeof value.id_required === "boolean" && typeof value.accepts_cod === "boolean" && typeof value.free_shipping_eligible === "boolean" && isPlainObject(value.extra) && typeof value.hidden === "boolean" && typeof value.shippable === "boolean";
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/lib/guards/pages.ts
|
|
247
|
+
function isProductPage(page) {
|
|
248
|
+
return page.type === "product";
|
|
249
|
+
}
|
|
250
|
+
function isCategoryPage(page) {
|
|
251
|
+
return page.type === "category";
|
|
252
|
+
}
|
|
253
|
+
function isCheckoutPage(page) {
|
|
254
|
+
return page.type === "checkout";
|
|
255
|
+
}
|
|
256
|
+
function isAllProductsPage(page) {
|
|
257
|
+
return page.type === "products";
|
|
258
|
+
}
|
|
259
|
+
function isSearchPage(page) {
|
|
260
|
+
return page.type === "search";
|
|
261
|
+
}
|
|
262
|
+
function isHomePage(page) {
|
|
263
|
+
return page.type === "home";
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// src/lib/page-match.ts
|
|
267
|
+
function pageMatch(state, handlers) {
|
|
268
|
+
const { page } = state.location;
|
|
269
|
+
if (isProductPage(page)) {
|
|
270
|
+
handlers.product?.(state, page.data.product);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (isCategoryPage(page)) {
|
|
274
|
+
handlers.category?.(state, page.data);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (isCheckoutPage(page)) {
|
|
278
|
+
handlers.checkout?.(state, page.data);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (isHomePage(page)) {
|
|
282
|
+
handlers.home?.(state, page.data);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function onPage(handlers) {
|
|
287
|
+
const nube = getNubeInstance();
|
|
288
|
+
const currentState = nube.getState();
|
|
289
|
+
pageMatch(currentState, handlers);
|
|
290
|
+
const listener = (state) => pageMatch(state, handlers);
|
|
291
|
+
nube.on("location:updated", listener);
|
|
292
|
+
return () => nube.off("location:updated", listener);
|
|
293
|
+
}
|
|
294
|
+
function onCheckoutStep(handlers) {
|
|
295
|
+
const nube = getNubeInstance();
|
|
296
|
+
const currentState = nube.getState();
|
|
297
|
+
const currentPage = currentState.location.page;
|
|
298
|
+
if (currentPage.type === "checkout") {
|
|
299
|
+
handlers[currentPage?.data?.step]?.(currentState);
|
|
300
|
+
}
|
|
301
|
+
const listener = (state) => {
|
|
302
|
+
const { page } = state.location;
|
|
303
|
+
if (page.type !== "checkout") return;
|
|
304
|
+
const step = page.data.step;
|
|
305
|
+
handlers[step]?.(state);
|
|
306
|
+
};
|
|
307
|
+
nube.on("checkout:ready", listener);
|
|
308
|
+
return () => nube.off("checkout:ready", listener);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/lib/render.ts
|
|
312
|
+
function getProductsFromState(state) {
|
|
313
|
+
const { page } = state.location;
|
|
314
|
+
if (!page || !("data" in page) || !page.data) {
|
|
315
|
+
return [];
|
|
316
|
+
}
|
|
317
|
+
const products = [];
|
|
318
|
+
if (hasProductList(page.data)) {
|
|
319
|
+
products.push(...page.data.products);
|
|
320
|
+
}
|
|
321
|
+
if (hasSections(page.data)) {
|
|
322
|
+
for (const section of page.data.sections) {
|
|
323
|
+
if (isSectionWithProducts(section)) {
|
|
324
|
+
products.push(...section.products);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (hasSingleProduct(page.data)) {
|
|
329
|
+
products.push(page.data.product);
|
|
330
|
+
}
|
|
331
|
+
return products;
|
|
332
|
+
}
|
|
333
|
+
function forEachProduct(renderFactory) {
|
|
334
|
+
return (state) => {
|
|
335
|
+
const products = getProductsFromState(state);
|
|
336
|
+
if (!products.length) return [];
|
|
337
|
+
return products.reduce((acc, product) => {
|
|
338
|
+
const component = renderFactory(product);
|
|
339
|
+
if (component) {
|
|
340
|
+
acc.push(Object.assign({}, component, { key: product.id }));
|
|
341
|
+
}
|
|
342
|
+
return acc;
|
|
343
|
+
}, []);
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// src/lib/selectors.ts
|
|
348
|
+
function getCart(state = getCurrentState()) {
|
|
349
|
+
return state.cart;
|
|
350
|
+
}
|
|
351
|
+
function getCartItems(state = getCurrentState()) {
|
|
352
|
+
return state.cart.items;
|
|
353
|
+
}
|
|
354
|
+
function getPageType(state = getCurrentState()) {
|
|
355
|
+
return state.location.page.type;
|
|
356
|
+
}
|
|
357
|
+
function getCustomer(state = getCurrentState()) {
|
|
358
|
+
return state.customer;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/lib/utils.ts
|
|
362
|
+
function deepClone(obj) {
|
|
363
|
+
if (obj === null || typeof obj !== "object") {
|
|
364
|
+
return obj;
|
|
365
|
+
}
|
|
366
|
+
if (typeof structuredClone === "function") {
|
|
367
|
+
return structuredClone(obj);
|
|
368
|
+
}
|
|
369
|
+
return JSON.parse(JSON.stringify(obj));
|
|
370
|
+
}
|
|
371
|
+
function debounce(func, wait) {
|
|
372
|
+
let timeout;
|
|
373
|
+
return (...args) => {
|
|
374
|
+
const later = () => {
|
|
375
|
+
timeout = void 0;
|
|
376
|
+
func(...args);
|
|
377
|
+
};
|
|
378
|
+
if (timeout) {
|
|
379
|
+
clearTimeout(timeout);
|
|
380
|
+
}
|
|
381
|
+
timeout = setTimeout(later, wait);
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function throttle(func, limit) {
|
|
385
|
+
let inThrottle;
|
|
386
|
+
return (...args) => {
|
|
387
|
+
if (!inThrottle) {
|
|
388
|
+
func(...args);
|
|
389
|
+
inThrottle = true;
|
|
390
|
+
setTimeout(() => {
|
|
391
|
+
inThrottle = false;
|
|
392
|
+
}, limit);
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
397
|
+
0 && (module.exports = {
|
|
398
|
+
browser,
|
|
399
|
+
clearBrowserCache,
|
|
400
|
+
clearNubeInstance,
|
|
401
|
+
debounce,
|
|
402
|
+
deepClone,
|
|
403
|
+
forEachProduct,
|
|
404
|
+
getAppData,
|
|
405
|
+
getCart,
|
|
406
|
+
getCartItems,
|
|
407
|
+
getCurrentState,
|
|
408
|
+
getCustomer,
|
|
409
|
+
getNubeInstance,
|
|
410
|
+
getPageType,
|
|
411
|
+
getProductsFromState,
|
|
412
|
+
getScriptParam,
|
|
413
|
+
getScriptSearchParams,
|
|
414
|
+
getScriptURL,
|
|
415
|
+
hasProductList,
|
|
416
|
+
hasSections,
|
|
417
|
+
hasSingleProduct,
|
|
418
|
+
isAddress,
|
|
419
|
+
isAllProductsPage,
|
|
420
|
+
isBillingAddress,
|
|
421
|
+
isCart,
|
|
422
|
+
isCartItem,
|
|
423
|
+
isCartValidationFail,
|
|
424
|
+
isCartValidationPending,
|
|
425
|
+
isCartValidationSuccess,
|
|
426
|
+
isCategoryPage,
|
|
427
|
+
isCheckoutPage,
|
|
428
|
+
isCustomer,
|
|
429
|
+
isHomePage,
|
|
430
|
+
isNubeComponent,
|
|
431
|
+
isPayment,
|
|
432
|
+
isProductPage,
|
|
433
|
+
isSearchPage,
|
|
434
|
+
isSectionWithProducts,
|
|
435
|
+
isShipping,
|
|
436
|
+
isShippingAddress,
|
|
437
|
+
isShippingOption,
|
|
438
|
+
isStore,
|
|
439
|
+
navigate,
|
|
440
|
+
onCheckoutStep,
|
|
441
|
+
onEvent,
|
|
442
|
+
onPage,
|
|
443
|
+
pageMatch,
|
|
444
|
+
setNubeInstance,
|
|
445
|
+
throttle,
|
|
446
|
+
toastOn,
|
|
447
|
+
ui
|
|
448
|
+
});
|
|
449
|
+
//# sourceMappingURL=index.cjs.map
|