@nosto/nosto-react 0.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/LICENSE +29 -0
- package/README.md +295 -0
- package/dist/index.es.client.js +505 -0
- package/dist/index.umd.client.js +9 -0
- package/package.json +60 -0
- package/src/components/Category/index.tsx +32 -0
- package/src/components/Checkout/index.tsx +29 -0
- package/src/components/Fohofo/index.tsx +29 -0
- package/src/components/Home/index.tsx +29 -0
- package/src/components/Order/index.tsx +38 -0
- package/src/components/Other/index.tsx +29 -0
- package/src/components/Placement/index.tsx +25 -0
- package/src/components/Product/index.tsx +150 -0
- package/src/components/Provider/context.ts +12 -0
- package/src/components/Provider/index.tsx +35 -0
- package/src/components/Search/index.tsx +32 -0
- package/src/components/Session/index.tsx +33 -0
- package/src/index.client.ts +31 -0
- package/src/snakeize.d.ts +1 -0
- package/src/types.ts +76 -0
- package/src/utils/stringinate.ts +16 -0
- package/src/vite-env.d.ts +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
const NostoHome: React.FC = () => {
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
window.nostojs((api) => {
|
|
7
|
+
api
|
|
8
|
+
.defaultSession()
|
|
9
|
+
.setResponseMode("HTML")
|
|
10
|
+
.viewFrontPage()
|
|
11
|
+
.setPlacements(api.placements.getPlacements())
|
|
12
|
+
.load()
|
|
13
|
+
.then((data: object) => {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
api.placements.injectCampaigns(data.recommendations);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<div className="nosto_page_type" style={{ display: "none" }}>
|
|
23
|
+
front
|
|
24
|
+
</div>
|
|
25
|
+
</>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default NostoHome;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Purchase } from "../../types";
|
|
2
|
+
import React, { useEffect } from "react";
|
|
3
|
+
import snakeize from "snakeize";
|
|
4
|
+
|
|
5
|
+
export interface OrderProps {
|
|
6
|
+
purchase: Purchase;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const NostoOrder: React.FC<{ order: OrderProps }> = ({ order }) => {
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
window.nostojs((api) => {
|
|
13
|
+
api
|
|
14
|
+
.defaultSession()
|
|
15
|
+
.setResponseMode("HTML")
|
|
16
|
+
.addOrder(snakeize(order))
|
|
17
|
+
.setPlacements(api.placements.getPlacements())
|
|
18
|
+
.load()
|
|
19
|
+
.then((data: object) => {
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
api.placements.injectCampaigns(data.recommendations);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}, []);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<div className="nosto_page_type" style={{ display: "none" }}>
|
|
29
|
+
order
|
|
30
|
+
</div>
|
|
31
|
+
<div className="nosto_order" style={{ display: "none" }}>
|
|
32
|
+
{order.purchase.number}
|
|
33
|
+
</div>
|
|
34
|
+
</>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default NostoOrder;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
const NostoOther: React.FC = () => {
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
window.nostojs((api) => {
|
|
7
|
+
api
|
|
8
|
+
.defaultSession()
|
|
9
|
+
.setResponseMode("HTML")
|
|
10
|
+
.viewOther()
|
|
11
|
+
.setPlacements(api.placements.getPlacements())
|
|
12
|
+
.load()
|
|
13
|
+
.then((data: object) => {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
api.placements.injectCampaigns(data.recommendations);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<div className="nosto_page_type" style={{ display: "none" }}>
|
|
23
|
+
other
|
|
24
|
+
</div>
|
|
25
|
+
</>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default NostoOther;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React, { MouseEvent } from "react";
|
|
2
|
+
|
|
3
|
+
export interface PlacementProps {
|
|
4
|
+
id: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const NostoPlacement: React.FC<PlacementProps> = ({ id }) => {
|
|
8
|
+
const handleClick = (e: MouseEvent) => {
|
|
9
|
+
// noinspection TypeScriptUnresolvedFunction
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
const targetLink = e.target.closest("a");
|
|
12
|
+
if (!targetLink) {
|
|
13
|
+
return;
|
|
14
|
+
} else {
|
|
15
|
+
e.preventDefault();
|
|
16
|
+
location.href = targetLink.href
|
|
17
|
+
.toString()
|
|
18
|
+
.replace(new URL(targetLink.href).origin, "");
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return <div className="nosto_element" onClick={handleClick} id={id} />;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default NostoPlacement;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { Product } from "../../types";
|
|
2
|
+
import stringinate from "../../utils/stringinate";
|
|
3
|
+
import React, { useEffect } from "react";
|
|
4
|
+
import snakeize from "snakeize";
|
|
5
|
+
|
|
6
|
+
const NostoProduct: React.FC<{ product: string; tagging: Product }> = ({
|
|
7
|
+
product,
|
|
8
|
+
tagging,
|
|
9
|
+
}) => {
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
window.nostojs((api) => {
|
|
13
|
+
api
|
|
14
|
+
.defaultSession()
|
|
15
|
+
.setResponseMode("HTML")
|
|
16
|
+
.viewProduct(snakeize(stringinate(tagging)))
|
|
17
|
+
.setPlacements(api.placements.getPlacements())
|
|
18
|
+
.load()
|
|
19
|
+
.then((data: object) => {
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
api.placements.injectCampaigns(data.recommendations);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}, []);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<div className="nosto_page_type" style={{ display: "none" }}>
|
|
29
|
+
product
|
|
30
|
+
</div>
|
|
31
|
+
<div className="nosto_product" style={{ display: "none" }}>
|
|
32
|
+
{tagging.variationId && (
|
|
33
|
+
<span className="variation_id">{tagging.variationId}</span>
|
|
34
|
+
)}
|
|
35
|
+
{tagging.productId && (
|
|
36
|
+
<span className="product_id">{tagging.productId}</span>
|
|
37
|
+
)}
|
|
38
|
+
{tagging.name && <span className="name">{tagging.name}</span>}
|
|
39
|
+
{tagging.url && <span className="url">{tagging.url.toString()}</span>}
|
|
40
|
+
{tagging.imageUrl && (
|
|
41
|
+
<span className="image_url">{tagging.imageUrl.toString()}</span>
|
|
42
|
+
)}
|
|
43
|
+
{tagging.availability && (
|
|
44
|
+
<span className="availability">{tagging.availability}</span>
|
|
45
|
+
)}
|
|
46
|
+
{tagging.price && <span className="price">{tagging.price}</span>}
|
|
47
|
+
{tagging.listPrice && (
|
|
48
|
+
<span className="list_price">{tagging.listPrice}</span>
|
|
49
|
+
)}
|
|
50
|
+
{tagging.priceCurrencyCode && (
|
|
51
|
+
<span className="price_currency_code">
|
|
52
|
+
{tagging.priceCurrencyCode}
|
|
53
|
+
</span>
|
|
54
|
+
)}
|
|
55
|
+
{tagging.brand && <span className="brand">{tagging.brand}</span>}
|
|
56
|
+
{tagging.description && (
|
|
57
|
+
<span className="description">{tagging.description}</span>
|
|
58
|
+
)}
|
|
59
|
+
{tagging.googleCategory && (
|
|
60
|
+
<span className="description">{tagging.googleCategory}</span>
|
|
61
|
+
)}
|
|
62
|
+
{tagging.condition && (
|
|
63
|
+
<span className="condition">{tagging.condition}</span>
|
|
64
|
+
)}
|
|
65
|
+
{tagging.gender && <span className="gender">{tagging.gender}</span>}
|
|
66
|
+
{tagging.ageGroup && (
|
|
67
|
+
<span className="age_group">{tagging.ageGroup}</span>
|
|
68
|
+
)}
|
|
69
|
+
{tagging.gtin && <span className="gtin">{tagging.gtin}</span>}
|
|
70
|
+
{tagging.category &&
|
|
71
|
+
tagging.category.map((category, index) => (
|
|
72
|
+
<span className="category" key={index}>
|
|
73
|
+
{category}
|
|
74
|
+
</span>
|
|
75
|
+
))}
|
|
76
|
+
{tagging.tags1 &&
|
|
77
|
+
tagging.tags1.map((tag, index) => (
|
|
78
|
+
<span className="tag1" key={index}>
|
|
79
|
+
{tag}
|
|
80
|
+
</span>
|
|
81
|
+
))}
|
|
82
|
+
{tagging.tags2 &&
|
|
83
|
+
tagging.tags2.map((tag, index) => (
|
|
84
|
+
<span className="tag2" key={index}>
|
|
85
|
+
{tag}
|
|
86
|
+
</span>
|
|
87
|
+
))}
|
|
88
|
+
{tagging.tags3 &&
|
|
89
|
+
tagging.tags3.map((tag, index) => (
|
|
90
|
+
<span className="tag3" key={index}>
|
|
91
|
+
{tag}
|
|
92
|
+
</span>
|
|
93
|
+
))}
|
|
94
|
+
{tagging.ratingValue && (
|
|
95
|
+
<span className="rating_value">{tagging.ratingValue}</span>
|
|
96
|
+
)}
|
|
97
|
+
{tagging.reviewCount && (
|
|
98
|
+
<span className="review_count">{tagging.reviewCount}</span>
|
|
99
|
+
)}
|
|
100
|
+
{tagging.alternateImageUrls &&
|
|
101
|
+
tagging.alternateImageUrls.map((url, index) => (
|
|
102
|
+
<span className="alternate_image_url" key={index}>
|
|
103
|
+
{url.toString()}
|
|
104
|
+
</span>
|
|
105
|
+
))}
|
|
106
|
+
{tagging.customFields &&
|
|
107
|
+
Object.keys(tagging.customFields).map(
|
|
108
|
+
(field, index) =>
|
|
109
|
+
tagging.customFields &&
|
|
110
|
+
tagging.customFields[field] && (
|
|
111
|
+
<span className={field} key={index}>
|
|
112
|
+
{tagging.customFields[field]}
|
|
113
|
+
</span>
|
|
114
|
+
)
|
|
115
|
+
)}
|
|
116
|
+
{tagging.skus &&
|
|
117
|
+
tagging.skus.map((sku, index) => (
|
|
118
|
+
<span className="nosto_sku" key={index}>
|
|
119
|
+
{sku.id && <span className="product_id">{sku.id}</span>}
|
|
120
|
+
{sku.name && <span className="name">{sku.name}</span>}
|
|
121
|
+
{sku.price && <span className="price">{sku.price}</span>}
|
|
122
|
+
{sku.listPrice && (
|
|
123
|
+
<span className="list_price">{sku.listPrice}</span>
|
|
124
|
+
)}
|
|
125
|
+
{sku.url && <span className="url">{sku.url.toString()}</span>}
|
|
126
|
+
{sku.imageUrl && (
|
|
127
|
+
<span className="image_url">{sku.imageUrl.toString()}</span>
|
|
128
|
+
)}
|
|
129
|
+
{sku.gtin && <span className="gtin">{sku.gtin}</span>}
|
|
130
|
+
{sku.availability && (
|
|
131
|
+
<span className="availability">{sku.availability}</span>
|
|
132
|
+
)}
|
|
133
|
+
{sku.customFields &&
|
|
134
|
+
Object.keys(sku.customFields).map(
|
|
135
|
+
(field, index) =>
|
|
136
|
+
sku.customFields &&
|
|
137
|
+
sku.customFields[field] && (
|
|
138
|
+
<span className={field} key={index}>
|
|
139
|
+
{sku.customFields[field]}
|
|
140
|
+
</span>
|
|
141
|
+
)
|
|
142
|
+
)}
|
|
143
|
+
</span>
|
|
144
|
+
))}
|
|
145
|
+
</div>
|
|
146
|
+
</>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export default NostoProduct;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
|
|
3
|
+
export interface NostoInterface {
|
|
4
|
+
account: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/* tslint:disable:no-empty */
|
|
8
|
+
export const NostoContext = createContext<NostoInterface>({
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
account: undefined
|
|
11
|
+
});
|
|
12
|
+
/* tslint:enable:no-empty */
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import { NostoContext } from "./context";
|
|
3
|
+
|
|
4
|
+
interface NostoProviderProps {
|
|
5
|
+
account: string;
|
|
6
|
+
host: string;
|
|
7
|
+
children: React.ReactElement;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const NostoProvider: React.FC<NostoProviderProps> = ({
|
|
11
|
+
account,
|
|
12
|
+
host,
|
|
13
|
+
children,
|
|
14
|
+
}) => {
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const script = document.createElement("script");
|
|
17
|
+
script.type = "text/javascript";
|
|
18
|
+
script.src = "//" + (host || "connect.nosto.com") + "/include/" + account;
|
|
19
|
+
script.async = true;
|
|
20
|
+
document.head.appendChild(script);
|
|
21
|
+
|
|
22
|
+
window.nostojs = (cb: Function) =>
|
|
23
|
+
(window.nostojs.q = window.nostojs.q || []).push(cb);
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
window.nostojs((api) => api.setAutoLoad(false));
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<NostoContext.Provider value={{ account }}>
|
|
30
|
+
{children}
|
|
31
|
+
</NostoContext.Provider>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default NostoProvider;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
const NostoSearch: React.FC<{ query: string }> = ({ query }) => {
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
window.nostojs((api) => {
|
|
7
|
+
api
|
|
8
|
+
.defaultSession()
|
|
9
|
+
.setResponseMode("HTML")
|
|
10
|
+
.viewSearch(query)
|
|
11
|
+
.setPlacements(api.placements.getPlacements())
|
|
12
|
+
.load()
|
|
13
|
+
.then((data: object) => {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
api.placements.injectCampaigns(data.recommendations);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<div className="nosto_page_type" style={{ display: "none" }}>
|
|
23
|
+
search
|
|
24
|
+
</div>
|
|
25
|
+
<div className="nosto_search" style={{ display: "none" }}>
|
|
26
|
+
{query}
|
|
27
|
+
</div>
|
|
28
|
+
</>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default NostoSearch;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import snakeize from "snakeize";
|
|
3
|
+
|
|
4
|
+
import useDeepCompareEffect from "use-deep-compare-effect";
|
|
5
|
+
import { Cart, Customer } from "../../types";
|
|
6
|
+
|
|
7
|
+
interface NostoSessionProps {
|
|
8
|
+
cart: Cart;
|
|
9
|
+
customer: Customer;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const NostoSession: React.FC<NostoSessionProps> = ({ cart, customer }) => {
|
|
13
|
+
useDeepCompareEffect(() => {
|
|
14
|
+
const currentUser = customer ? customer : undefined;
|
|
15
|
+
console.debug(currentUser);
|
|
16
|
+
const currentCart = cart ? cart : undefined;
|
|
17
|
+
console.debug(currentCart);
|
|
18
|
+
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
window.nostojs((api) => {
|
|
21
|
+
api
|
|
22
|
+
.defaultSession()
|
|
23
|
+
.setResponseMode("HTML")
|
|
24
|
+
.setCart(snakeize(currentCart))
|
|
25
|
+
.viewOther()
|
|
26
|
+
.load();
|
|
27
|
+
});
|
|
28
|
+
}, [cart || [], customer || {}]);
|
|
29
|
+
|
|
30
|
+
return <div />;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default NostoSession;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
// noinspection JSUnusedGlobalSymbols
|
|
3
|
+
interface Window {
|
|
4
|
+
nostojs: any;
|
|
5
|
+
nosto: any;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export * from "./types";
|
|
10
|
+
// noinspection JSUnusedGlobalSymbols
|
|
11
|
+
export { default as Nosto404 } from "./components/Fohofo";
|
|
12
|
+
// noinspection JSUnusedGlobalSymbols
|
|
13
|
+
export { default as NostoOther } from "./components/Other";
|
|
14
|
+
// noinspection JSUnusedGlobalSymbols
|
|
15
|
+
export { default as NostoCheckout } from "./components/Checkout";
|
|
16
|
+
// noinspection JSUnusedGlobalSymbols
|
|
17
|
+
export { default as NostoProduct } from "./components/Product";
|
|
18
|
+
// noinspection JSUnusedGlobalSymbols
|
|
19
|
+
export { default as NostoCategory } from "./components/Category";
|
|
20
|
+
// noinspection JSUnusedGlobalSymbols
|
|
21
|
+
export { default as NostoSearch } from "./components/Search";
|
|
22
|
+
// noinspection JSUnusedGlobalSymbols
|
|
23
|
+
export { default as NostoOrder } from "./components/Order";
|
|
24
|
+
// noinspection JSUnusedGlobalSymbols
|
|
25
|
+
export { default as NostoHome } from "./components/Home";
|
|
26
|
+
// noinspection JSUnusedGlobalSymbols
|
|
27
|
+
export { default as NostoPlacement } from "./components/Placement";
|
|
28
|
+
// noinspection JSUnusedGlobalSymbols
|
|
29
|
+
export { default as NostoProvider } from "./components/Provider";
|
|
30
|
+
// noinspection JSUnusedGlobalSymbols
|
|
31
|
+
export { default as NostoSession } from "./components/Session";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module "snakeize";
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export interface Item {
|
|
2
|
+
name: string;
|
|
3
|
+
price_currency_code: string;
|
|
4
|
+
product_id: string;
|
|
5
|
+
quantity: number;
|
|
6
|
+
sku_id: string;
|
|
7
|
+
unit_price: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Cart {
|
|
11
|
+
items: Item[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface Customer {
|
|
15
|
+
customer_reference: string;
|
|
16
|
+
email: string;
|
|
17
|
+
first_name: string;
|
|
18
|
+
last_name: string;
|
|
19
|
+
newsletter: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface Buyer {
|
|
23
|
+
first_name: string;
|
|
24
|
+
last_name: string;
|
|
25
|
+
email: string;
|
|
26
|
+
type: string;
|
|
27
|
+
newsletter: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface Purchase {
|
|
31
|
+
number: string;
|
|
32
|
+
info: Buyer;
|
|
33
|
+
items: Item[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface SKU {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
price: number;
|
|
40
|
+
listPrice?: number;
|
|
41
|
+
url: URL;
|
|
42
|
+
imageUrl: URL;
|
|
43
|
+
gtin?: string;
|
|
44
|
+
availability: 'InStock' | 'OutOfStock';
|
|
45
|
+
customFields?: { [key: string]: string };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface Product {
|
|
49
|
+
alternateImageUrls?: URL[];
|
|
50
|
+
availability: 'InStock' | 'OutOfStock';
|
|
51
|
+
brand?: string;
|
|
52
|
+
category: string[];
|
|
53
|
+
categoryIds?: string[];
|
|
54
|
+
description: string;
|
|
55
|
+
googleCategory?: string;
|
|
56
|
+
condition?: string;
|
|
57
|
+
gender?: string;
|
|
58
|
+
ageGroup?: string;
|
|
59
|
+
gtin?: string;
|
|
60
|
+
imageUrl: URL;
|
|
61
|
+
listPrice?: number;
|
|
62
|
+
name: string;
|
|
63
|
+
price: number;
|
|
64
|
+
ratingValue?: number;
|
|
65
|
+
reviewCount?: number;
|
|
66
|
+
priceCurrencyCode: string;
|
|
67
|
+
productId: string;
|
|
68
|
+
tags1?: string[];
|
|
69
|
+
tags2?: string[];
|
|
70
|
+
tags3?: string[];
|
|
71
|
+
thumbUrl?: URL;
|
|
72
|
+
url: URL;
|
|
73
|
+
customFields?: { [key: string]: string };
|
|
74
|
+
variationId?: string;
|
|
75
|
+
skus?: SKU[];
|
|
76
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default function stringinate(obj: {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
}): { [key: string]: any } {
|
|
4
|
+
Object.keys(obj).forEach((property) => {
|
|
5
|
+
if (obj[property] instanceof URL) {
|
|
6
|
+
obj[property] = obj[property].toString();
|
|
7
|
+
}
|
|
8
|
+
if (typeof obj[property] === "object") {
|
|
9
|
+
stringinate(obj[property]);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
obj[property] = obj[property];
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return obj;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|