@dutchiesdk/ecommerce-extensions-sdk 0.8.3 → 0.9.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/README.md +21 -46
- package/dist/context/ecommerce-data-bridge.cjs +1 -1
- package/dist/esm/context/ecommerce-data-bridge.js +1 -1
- package/dist/esm/types/actions.d.ts +26 -25
- package/dist/esm/types/data.d.ts +6 -5
- package/dist/types/actions.d.ts +26 -25
- package/dist/types/data.d.ts +6 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ const ProductList = () => {
|
|
|
103
103
|
|
|
104
104
|
### `CommerceComponentsDataInterface`
|
|
105
105
|
|
|
106
|
-
The main interface providing access to all platform data and functionality.
|
|
106
|
+
The main interface providing access to all platform data and functionality. [Full interface can be found here](./src/types/interface.ts).
|
|
107
107
|
|
|
108
108
|
```typescript
|
|
109
109
|
interface CommerceComponentsDataInterface {
|
|
@@ -120,17 +120,17 @@ interface CommerceComponentsDataInterface {
|
|
|
120
120
|
|
|
121
121
|
### `RemoteBoundaryComponent`
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
type RemoteBoundaryComponent = React.FC & {
|
|
127
|
-
DataBridgeVersion: string;
|
|
128
|
-
};
|
|
129
|
-
```
|
|
123
|
+
All extension components that integrate with the Dutchie platform should satisfy the `RemoteBoundaryComponent` type.
|
|
130
124
|
|
|
131
125
|
**Example:**
|
|
132
126
|
|
|
133
127
|
```tsx
|
|
128
|
+
import {
|
|
129
|
+
RemoteBoundaryComponent,
|
|
130
|
+
useDataBridge,
|
|
131
|
+
DataBridgeVersion,
|
|
132
|
+
} from "@dutchie/ecommerce-extensions-sdk";
|
|
133
|
+
|
|
134
134
|
const MyCustomHeader: RemoteBoundaryComponent = () => {
|
|
135
135
|
const { location, user, actions } = useDataBridge();
|
|
136
136
|
|
|
@@ -146,7 +146,7 @@ const MyCustomHeader: RemoteBoundaryComponent = () => {
|
|
|
146
146
|
);
|
|
147
147
|
};
|
|
148
148
|
|
|
149
|
-
MyCustomHeader.DataBridgeVersion =
|
|
149
|
+
MyCustomHeader.DataBridgeVersion = DataBridgeVersion;
|
|
150
150
|
```
|
|
151
151
|
|
|
152
152
|
## Actions API
|
|
@@ -189,26 +189,26 @@ const currentLocations = await dataLoaders.locations(); // Current context locat
|
|
|
189
189
|
|
|
190
190
|
## Best Practices
|
|
191
191
|
|
|
192
|
-
###
|
|
192
|
+
### Data Loading
|
|
193
193
|
|
|
194
|
-
|
|
194
|
+
When using the `useDataBridge()` hook in a component, always handle loading states:
|
|
195
195
|
|
|
196
196
|
```tsx
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const { data, isLoading } = useAsyncLoader(dataLoaders.products);
|
|
197
|
+
const MyComponent = () => {
|
|
198
|
+
const { dataLoaders } = useDataBridge();
|
|
199
|
+
const { data, isLoading } = useAsyncLoader(dataLoaders.products);
|
|
201
200
|
|
|
202
|
-
|
|
203
|
-
|
|
201
|
+
if (isLoading) return <LoadingSpinner />;
|
|
202
|
+
if (!data) return <EmptyProducts message="No products found" />;
|
|
204
203
|
|
|
205
|
-
|
|
206
|
-
} catch (error) {
|
|
207
|
-
return <ErrorFallback error={error} />;
|
|
208
|
-
}
|
|
204
|
+
return <ProductList products={data} />;
|
|
209
205
|
};
|
|
210
206
|
```
|
|
211
207
|
|
|
208
|
+
### Error Handling
|
|
209
|
+
|
|
210
|
+
Any uncaught errors will be caught by a Dutchie error boundary, and the fallback will be rendered.
|
|
211
|
+
|
|
212
212
|
### TypeScript Best Practices
|
|
213
213
|
|
|
214
214
|
Leverage the provided types for better development experience:
|
|
@@ -292,31 +292,6 @@ test("renders extension correctly", () => {
|
|
|
292
292
|
});
|
|
293
293
|
```
|
|
294
294
|
|
|
295
|
-
### Performance Optimization
|
|
296
|
-
|
|
297
|
-
Use `React.memo` and `useMemo` for expensive operations:
|
|
298
|
-
|
|
299
|
-
```tsx
|
|
300
|
-
const ProductCard = React.memo(({ product, onAddToCart }) => {
|
|
301
|
-
const formattedPrice = React.useMemo(
|
|
302
|
-
() =>
|
|
303
|
-
new Intl.NumberFormat("en-US", {
|
|
304
|
-
style: "currency",
|
|
305
|
-
currency: "USD",
|
|
306
|
-
}).format(product.price),
|
|
307
|
-
[product.price]
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
return (
|
|
311
|
-
<div className="product-card">
|
|
312
|
-
<h3>{product.name}</h3>
|
|
313
|
-
<p>{formattedPrice}</p>
|
|
314
|
-
<button onClick={() => onAddToCart(product.id, 1)}>Add to Cart</button>
|
|
315
|
-
</div>
|
|
316
|
-
);
|
|
317
|
-
});
|
|
318
|
-
```
|
|
319
|
-
|
|
320
295
|
## Core Concepts
|
|
321
296
|
|
|
322
297
|
The Dutchie Ecommerce Extensions SDK is built around several key concepts:
|
|
@@ -30,7 +30,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
30
30
|
useDataBridge: ()=>useDataBridge
|
|
31
31
|
});
|
|
32
32
|
const external_react_namespaceObject = require("react");
|
|
33
|
-
const DataBridgeVersion = '0.
|
|
33
|
+
const DataBridgeVersion = '0.9.0';
|
|
34
34
|
const DataBridgeContext = (0, external_react_namespaceObject.createContext)(void 0);
|
|
35
35
|
const useDataBridge = ()=>{
|
|
36
36
|
const context = (0, external_react_namespaceObject.useContext)(DataBridgeContext);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createContext, useContext, useEffect, useState } from "react";
|
|
2
|
-
const DataBridgeVersion = '0.
|
|
2
|
+
const DataBridgeVersion = '0.9.0';
|
|
3
3
|
const DataBridgeContext = createContext(void 0);
|
|
4
4
|
const useDataBridge = ()=>{
|
|
5
5
|
const context = useContext(DataBridgeContext);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CartItem } from './data';
|
|
1
2
|
type AuthenticationActions = {
|
|
2
3
|
/**
|
|
3
4
|
* Navigate to login
|
|
@@ -8,13 +9,15 @@ type AuthenticationActions = {
|
|
|
8
9
|
*/
|
|
9
10
|
goToRegister: () => void;
|
|
10
11
|
};
|
|
12
|
+
type GoToIdOrCnameParameters = {
|
|
13
|
+
id?: string;
|
|
14
|
+
cname?: string;
|
|
15
|
+
};
|
|
11
16
|
type CartActions = {
|
|
12
17
|
/**
|
|
13
18
|
* Add product to cart
|
|
14
|
-
* @param productId - The product ID
|
|
15
|
-
* @param quantity - The quantity
|
|
16
19
|
*/
|
|
17
|
-
addToCart: (
|
|
20
|
+
addToCart: (item: CartItem) => Promise<void>;
|
|
18
21
|
/**
|
|
19
22
|
* Clear cart
|
|
20
23
|
*/
|
|
@@ -29,19 +32,23 @@ type CartActions = {
|
|
|
29
32
|
goToCheckout: () => void;
|
|
30
33
|
/**
|
|
31
34
|
* Remove product from cart
|
|
32
|
-
* @param productId - The product ID
|
|
33
35
|
*/
|
|
34
|
-
removeFromCart: (
|
|
36
|
+
removeFromCart: (item: CartItem) => void;
|
|
35
37
|
/**
|
|
36
38
|
* Show cart sidebar/modal
|
|
37
39
|
*/
|
|
38
40
|
showCart: () => void;
|
|
39
41
|
/**
|
|
40
42
|
* Update product quantity in cart
|
|
41
|
-
* @param
|
|
42
|
-
* @param
|
|
43
|
+
* @param existingItem - The existing item
|
|
44
|
+
* @param newItem - The new item
|
|
45
|
+
*/
|
|
46
|
+
updateCartItem: (existingItem: CartItem, newItem: CartItem) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Update pricing type
|
|
49
|
+
* @param pricingType - The pricing type
|
|
43
50
|
*/
|
|
44
|
-
|
|
51
|
+
updatePricingType: (pricingType: 'med' | 'rec') => void;
|
|
45
52
|
};
|
|
46
53
|
type ComponentActions = {
|
|
47
54
|
/**
|
|
@@ -60,33 +67,27 @@ type ComponentActions = {
|
|
|
60
67
|
};
|
|
61
68
|
type DetailPageActions = {
|
|
62
69
|
/**
|
|
63
|
-
* Navigate to
|
|
64
|
-
* @param categoryId - The category ID
|
|
65
|
-
* @param categoryCname - The category CNAME
|
|
70
|
+
* Navigate to brand page
|
|
66
71
|
*/
|
|
67
|
-
|
|
72
|
+
goToBrand: (params: GoToIdOrCnameParameters) => void;
|
|
68
73
|
/**
|
|
69
|
-
* Navigate to
|
|
74
|
+
* Navigate to category page. Only one parameter is required.
|
|
70
75
|
*/
|
|
71
|
-
|
|
76
|
+
goToCategory: (params: GoToIdOrCnameParameters) => void;
|
|
72
77
|
/**
|
|
73
|
-
* Navigate to
|
|
74
|
-
* @param productId - The product ID
|
|
75
|
-
* @param productCname - The product CNAME
|
|
78
|
+
* Navigate to collection page. Only one parameter is required.
|
|
76
79
|
*/
|
|
77
|
-
|
|
80
|
+
goToCollection: (params: GoToIdOrCnameParameters) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Navigate to product details. Only one parameter is required.
|
|
83
|
+
*/
|
|
84
|
+
goToProductDetails: (params: GoToIdOrCnameParameters) => void;
|
|
78
85
|
};
|
|
79
86
|
type ListPageActions = {
|
|
80
87
|
/**
|
|
81
88
|
* Navigate to brand list
|
|
82
|
-
* @param brandId - The brand ID
|
|
83
|
-
* @param brandCname - The brand CNAME
|
|
84
|
-
*/
|
|
85
|
-
goToBrandList: (brandId?: string, brandCname?: string) => void;
|
|
86
|
-
/**
|
|
87
|
-
* Navigate to collection list
|
|
88
89
|
*/
|
|
89
|
-
|
|
90
|
+
goToBrandList: () => void;
|
|
90
91
|
/**
|
|
91
92
|
* Navigate to product list
|
|
92
93
|
* @param categoryId - The category ID
|
package/dist/esm/types/data.d.ts
CHANGED
|
@@ -4,7 +4,12 @@ export type Brand = {
|
|
|
4
4
|
name: string;
|
|
5
5
|
};
|
|
6
6
|
export type CartItem = {
|
|
7
|
+
/**
|
|
8
|
+
* Generally, use [option] instead. This is advanced use only.
|
|
9
|
+
*/
|
|
10
|
+
additionalOption?: string;
|
|
7
11
|
name: string;
|
|
12
|
+
option?: string;
|
|
8
13
|
price: number;
|
|
9
14
|
productId: string;
|
|
10
15
|
quantity: number;
|
|
@@ -134,11 +139,7 @@ export type DataLoaders = {
|
|
|
134
139
|
*/
|
|
135
140
|
collections: () => Promise<Collection[] | []>;
|
|
136
141
|
/**
|
|
137
|
-
* All dispensary locations
|
|
138
|
-
*/
|
|
139
|
-
getAllLocations: () => Promise<Dispensary[] | []>;
|
|
140
|
-
/**
|
|
141
|
-
* Current context locations
|
|
142
|
+
* All dispensary locations of the chain
|
|
142
143
|
*/
|
|
143
144
|
locations: () => Promise<Dispensary[] | []>;
|
|
144
145
|
/**
|
package/dist/types/actions.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CartItem } from './data';
|
|
1
2
|
type AuthenticationActions = {
|
|
2
3
|
/**
|
|
3
4
|
* Navigate to login
|
|
@@ -8,13 +9,15 @@ type AuthenticationActions = {
|
|
|
8
9
|
*/
|
|
9
10
|
goToRegister: () => void;
|
|
10
11
|
};
|
|
12
|
+
type GoToIdOrCnameParameters = {
|
|
13
|
+
id?: string;
|
|
14
|
+
cname?: string;
|
|
15
|
+
};
|
|
11
16
|
type CartActions = {
|
|
12
17
|
/**
|
|
13
18
|
* Add product to cart
|
|
14
|
-
* @param productId - The product ID
|
|
15
|
-
* @param quantity - The quantity
|
|
16
19
|
*/
|
|
17
|
-
addToCart: (
|
|
20
|
+
addToCart: (item: CartItem) => Promise<void>;
|
|
18
21
|
/**
|
|
19
22
|
* Clear cart
|
|
20
23
|
*/
|
|
@@ -29,19 +32,23 @@ type CartActions = {
|
|
|
29
32
|
goToCheckout: () => void;
|
|
30
33
|
/**
|
|
31
34
|
* Remove product from cart
|
|
32
|
-
* @param productId - The product ID
|
|
33
35
|
*/
|
|
34
|
-
removeFromCart: (
|
|
36
|
+
removeFromCart: (item: CartItem) => void;
|
|
35
37
|
/**
|
|
36
38
|
* Show cart sidebar/modal
|
|
37
39
|
*/
|
|
38
40
|
showCart: () => void;
|
|
39
41
|
/**
|
|
40
42
|
* Update product quantity in cart
|
|
41
|
-
* @param
|
|
42
|
-
* @param
|
|
43
|
+
* @param existingItem - The existing item
|
|
44
|
+
* @param newItem - The new item
|
|
45
|
+
*/
|
|
46
|
+
updateCartItem: (existingItem: CartItem, newItem: CartItem) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Update pricing type
|
|
49
|
+
* @param pricingType - The pricing type
|
|
43
50
|
*/
|
|
44
|
-
|
|
51
|
+
updatePricingType: (pricingType: 'med' | 'rec') => void;
|
|
45
52
|
};
|
|
46
53
|
type ComponentActions = {
|
|
47
54
|
/**
|
|
@@ -60,33 +67,27 @@ type ComponentActions = {
|
|
|
60
67
|
};
|
|
61
68
|
type DetailPageActions = {
|
|
62
69
|
/**
|
|
63
|
-
* Navigate to
|
|
64
|
-
* @param categoryId - The category ID
|
|
65
|
-
* @param categoryCname - The category CNAME
|
|
70
|
+
* Navigate to brand page
|
|
66
71
|
*/
|
|
67
|
-
|
|
72
|
+
goToBrand: (params: GoToIdOrCnameParameters) => void;
|
|
68
73
|
/**
|
|
69
|
-
* Navigate to
|
|
74
|
+
* Navigate to category page. Only one parameter is required.
|
|
70
75
|
*/
|
|
71
|
-
|
|
76
|
+
goToCategory: (params: GoToIdOrCnameParameters) => void;
|
|
72
77
|
/**
|
|
73
|
-
* Navigate to
|
|
74
|
-
* @param productId - The product ID
|
|
75
|
-
* @param productCname - The product CNAME
|
|
78
|
+
* Navigate to collection page. Only one parameter is required.
|
|
76
79
|
*/
|
|
77
|
-
|
|
80
|
+
goToCollection: (params: GoToIdOrCnameParameters) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Navigate to product details. Only one parameter is required.
|
|
83
|
+
*/
|
|
84
|
+
goToProductDetails: (params: GoToIdOrCnameParameters) => void;
|
|
78
85
|
};
|
|
79
86
|
type ListPageActions = {
|
|
80
87
|
/**
|
|
81
88
|
* Navigate to brand list
|
|
82
|
-
* @param brandId - The brand ID
|
|
83
|
-
* @param brandCname - The brand CNAME
|
|
84
|
-
*/
|
|
85
|
-
goToBrandList: (brandId?: string, brandCname?: string) => void;
|
|
86
|
-
/**
|
|
87
|
-
* Navigate to collection list
|
|
88
89
|
*/
|
|
89
|
-
|
|
90
|
+
goToBrandList: () => void;
|
|
90
91
|
/**
|
|
91
92
|
* Navigate to product list
|
|
92
93
|
* @param categoryId - The category ID
|
package/dist/types/data.d.ts
CHANGED
|
@@ -4,7 +4,12 @@ export type Brand = {
|
|
|
4
4
|
name: string;
|
|
5
5
|
};
|
|
6
6
|
export type CartItem = {
|
|
7
|
+
/**
|
|
8
|
+
* Generally, use [option] instead. This is advanced use only.
|
|
9
|
+
*/
|
|
10
|
+
additionalOption?: string;
|
|
7
11
|
name: string;
|
|
12
|
+
option?: string;
|
|
8
13
|
price: number;
|
|
9
14
|
productId: string;
|
|
10
15
|
quantity: number;
|
|
@@ -134,11 +139,7 @@ export type DataLoaders = {
|
|
|
134
139
|
*/
|
|
135
140
|
collections: () => Promise<Collection[] | []>;
|
|
136
141
|
/**
|
|
137
|
-
* All dispensary locations
|
|
138
|
-
*/
|
|
139
|
-
getAllLocations: () => Promise<Dispensary[] | []>;
|
|
140
|
-
/**
|
|
141
|
-
* Current context locations
|
|
142
|
+
* All dispensary locations of the chain
|
|
142
143
|
*/
|
|
143
144
|
locations: () => Promise<Dispensary[] | []>;
|
|
144
145
|
/**
|