@teamnovu/kit-shopware-composables 0.0.3 → 0.0.4
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/api-types/storeApiSchema.localhost.http +1 -1
- package/dist/helpers/checkout/index.d.ts +5 -0
- package/dist/helpers/checkout/useAddresses.d.ts +210 -0
- package/dist/helpers/checkout/useOrderDetails.d.ts +186 -0
- package/dist/helpers/checkout/useOrderPayment.d.ts +73 -0
- package/dist/helpers/checkout/usePaymentMethods.d.ts +155 -0
- package/dist/helpers/checkout/useShippingMethods.d.ts +173 -0
- package/dist/helpers/general/index.d.ts +2 -0
- package/dist/{usePagination.d.ts → helpers/general/usePagination.d.ts} +1 -1
- package/dist/{general → helpers/general}/useSeoUrl.d.ts +1 -1
- package/dist/helpers/index.d.ts +4 -0
- package/dist/helpers/product/index.d.ts +2 -0
- package/dist/helpers/product/useProductPrice.d.ts +61 -0
- package/dist/{products → helpers/product}/useProductVariantForOptions.d.ts +1 -1
- package/dist/helpers/user/index.d.ts +2 -0
- package/dist/helpers/user/useIsLoggedIn.d.ts +2 -0
- package/dist/helpers/user/useUser.d.ts +167 -0
- package/dist/index.d.ts +3 -221
- package/dist/index.mjs +851 -222
- package/dist/inject.d.ts +2 -2
- package/dist/keys.d.ts +32 -0
- package/dist/query/address/index.d.ts +3 -0
- package/dist/query/address/useCreateCustomerAddressMutation.d.ts +166 -0
- package/dist/query/address/useDeleteCustomerAddressMutation.d.ts +5 -0
- package/dist/query/address/useListAddressQuery.d.ts +48 -0
- package/dist/query/cart/index.d.ts +4 -0
- package/dist/query/cart/useAddLineItemMutation.d.ts +131 -0
- package/dist/query/cart/useReadCartQuery.d.ts +108 -0
- package/dist/query/cart/useRemoveLineItemMutation.d.ts +136 -0
- package/dist/query/cart/useUpdateLineItemMutation.d.ts +131 -0
- package/dist/query/checkout/index.d.ts +2 -0
- package/dist/query/checkout/useCheckout.d.ts +1 -0
- package/dist/query/checkout/useCreateOrderMutation.d.ts +281 -0
- package/dist/query/context/index.d.ts +2 -0
- package/dist/query/context/useReadContextQuery.d.ts +153 -0
- package/dist/query/context/useUpdateContextMutation.d.ts +60 -0
- package/dist/query/customer/index.d.ts +6 -0
- package/dist/query/customer/useChangeEmailMutation.d.ts +15 -0
- package/dist/query/customer/useChangeProfileMutation.d.ts +15 -0
- package/dist/query/customer/useLoginCustomerMutation.d.ts +30 -0
- package/dist/query/customer/useLogoutCustomerMutation.d.ts +15 -0
- package/dist/query/customer/useReadCustomerQuery.d.ts +220 -0
- package/dist/query/customer/useRegisterCustomerMutation.d.ts +266 -0
- package/dist/query/index.d.ts +10 -0
- package/dist/query/order/index.d.ts +1 -0
- package/dist/query/order/useReadOrderQuery.d.ts +44 -0
- package/dist/query/payment/index.d.ts +3 -0
- package/dist/query/payment/useHandlePaymentMutation.d.ts +15 -0
- package/dist/query/payment/useOrderSetPaymentMutation.d.ts +15 -0
- package/dist/query/payment/useReadPaymentMethodQuery.d.ts +31 -0
- package/dist/query/products/index.d.ts +3 -0
- package/dist/query/products/useReadCategoryListQuery.d.ts +48 -0
- package/dist/query/products/useReadCompactProductListingQuery.d.ts +35 -0
- package/dist/query/products/useReadCustomProductDetailQuery.d.ts +67 -0
- package/dist/query/shipping/index.d.ts +1 -0
- package/dist/query/shipping/useReadShippingMethodQuery.d.ts +55 -0
- package/dist/query/types/index.d.ts +2 -0
- package/dist/query/types/operations.d.ts +5 -0
- package/dist/query/types/query.d.ts +17 -0
- package/dist/util/index.d.ts +3 -0
- package/dist/util/unrefOptions.d.ts +4 -0
- package/dist/util/useOptimistic.d.ts +12 -0
- package/docs/index.md +457 -0
- package/docs/info.json +3 -0
- package/package.json +5 -1
- package/src/helpers/checkout/index.ts +5 -0
- package/src/helpers/checkout/useAddresses.ts +57 -0
- package/src/helpers/checkout/useOrderDetails.ts +94 -0
- package/src/helpers/checkout/useOrderPayment.ts +28 -0
- package/src/helpers/checkout/usePaymentMethods.ts +35 -0
- package/src/helpers/checkout/useShippingMethods.ts +35 -0
- package/src/helpers/general/index.ts +2 -0
- package/src/helpers/index.ts +4 -0
- package/src/helpers/product/index.ts +2 -0
- package/src/{products → helpers/product}/useProductPrice.ts +1 -43
- package/src/helpers/user/index.ts +2 -0
- package/src/helpers/user/useIsLoggedIn.ts +10 -0
- package/src/helpers/user/useUser.ts +53 -0
- package/src/index.ts +4 -29
- package/src/inject.ts +3 -3
- package/src/keys.ts +57 -0
- package/src/query/address/index.ts +3 -0
- package/src/query/address/useCreateCustomerAddressMutation.ts +32 -0
- package/src/query/address/useDeleteCustomerAddressMutation.ts +32 -0
- package/src/query/address/useListAddressQuery.ts +29 -0
- package/src/query/cart/index.ts +4 -0
- package/src/query/cart/useAddLineItemMutation.ts +45 -0
- package/src/query/cart/useReadCartQuery.ts +28 -0
- package/src/query/cart/useRemoveLineItemMutation.ts +32 -0
- package/src/query/cart/useUpdateLineItemMutation.ts +45 -0
- package/src/query/checkout/index.ts +2 -0
- package/src/query/checkout/useCheckout.ts +2 -0
- package/src/query/checkout/useCreateOrderMutation.ts +35 -0
- package/src/query/context/index.ts +2 -0
- package/src/query/context/useReadContextQuery.ts +19 -0
- package/src/query/context/useUpdateContextMutation.ts +36 -0
- package/src/query/customer/index.ts +6 -0
- package/src/query/customer/useChangeEmailMutation.ts +32 -0
- package/src/query/customer/useChangeProfileMutation.ts +32 -0
- package/src/query/customer/useLoginCustomerMutation.ts +42 -0
- package/src/query/customer/useLogoutCustomerMutation.ts +32 -0
- package/src/query/customer/useReadCustomerQuery.ts +27 -0
- package/src/query/customer/useRegisterCustomerMutation.ts +32 -0
- package/src/query/index.ts +10 -0
- package/src/query/order/index.ts +1 -0
- package/src/query/order/useReadOrderQuery.ts +33 -0
- package/src/query/payment/index.ts +3 -0
- package/src/query/payment/useHandlePaymentMutation.ts +27 -0
- package/src/query/payment/useOrderSetPaymentMutation.ts +32 -0
- package/src/query/payment/useReadPaymentMethodQuery.ts +30 -0
- package/src/query/products/index.ts +3 -0
- package/src/query/products/useReadCategoryListQuery.ts +28 -0
- package/src/query/products/useReadCompactProductListingQuery.ts +41 -0
- package/src/query/products/useReadCustomProductDetailQuery.ts +41 -0
- package/src/query/shipping/index.ts +1 -0
- package/src/query/shipping/useReadShippingMethodQuery.ts +29 -0
- package/src/query/types/index.ts +2 -0
- package/src/query/types/operations.ts +6 -0
- package/src/query/types/query.ts +39 -0
- package/src/util/index.ts +3 -0
- package/src/util/unrefOptions.ts +19 -0
- package/src/util/useOptimistic.ts +49 -0
- package/tsconfig.json +5 -2
- package/dist/cart/useCartAddItemMutation.d.ts +0 -12
- package/dist/cart/useCartQueryOptions.d.ts +0 -9
- package/dist/cart/useCartRemoveItemMutation.d.ts +0 -7
- package/dist/cart/useCartUpdateItemMutation.d.ts +0 -12
- package/dist/context/useContextOptions.d.ts +0 -9
- package/dist/context/useContextUpdate.d.ts +0 -4
- package/dist/products/useCategoryQueryOptions.d.ts +0 -17
- package/dist/products/useProductListingQueryOptions.d.ts +0 -19
- package/dist/products/useProductListingQueryOptions.test.d.ts +0 -1
- package/dist/products/useProductPrice.d.ts +0 -49
- package/dist/products/useProductQueryOptions.d.ts +0 -19
- package/dist/types/query.d.ts +0 -7
- package/src/cart/useCartAddItemMutation.ts +0 -48
- package/src/cart/useCartQueryOptions.ts +0 -19
- package/src/cart/useCartRemoveItemMutation.ts +0 -32
- package/src/cart/useCartUpdateItemMutation.ts +0 -48
- package/src/context/useContextOptions.ts +0 -16
- package/src/context/useContextUpdate.ts +0 -16
- package/src/products/useCategoryQueryOptions.ts +0 -25
- package/src/products/useProductListingQueryOptions.test.ts +0 -24
- package/src/products/useProductListingQueryOptions.ts +0 -29
- package/src/products/useProductQueryOptions.ts +0 -29
- package/src/types/query.ts +0 -18
- /package/src/{usePagination.ts → helpers/general/usePagination.ts} +0 -0
- /package/src/{general → helpers/general}/useSeoUrl.ts +0 -0
- /package/src/{products → helpers/product}/useProductVariantForOptions.ts +0 -0
package/docs/index.md
ADDED
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
# Shopware Composables
|
|
2
|
+
|
|
3
|
+
A comprehensive collection of Vue 3 composables for Shopware Store API integration with TanStack Query for state management and caching.
|
|
4
|
+
|
|
5
|
+
Install with `npm i @teamnovu/kit-shopware-composables`
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- ✅ **Vue 3 Composition API** - Built for Vue 3 with full TypeScript support
|
|
10
|
+
- ✅ **TanStack Query Integration** - Powerful caching, background updates, and query management
|
|
11
|
+
- ✅ **Type-safe Operations** - Generated types from Shopware API schema
|
|
12
|
+
- ✅ **Modular Architecture** - Import only what you need
|
|
13
|
+
- ✅ **Optimistic Updates** - Smooth UX with optimistic mutation handling
|
|
14
|
+
- ✅ **Docker Development** - Ready-to-use Shopware development environment
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import {
|
|
20
|
+
useReadProductListingQuery,
|
|
21
|
+
useReadCartQuery,
|
|
22
|
+
useAddLineItemMutation,
|
|
23
|
+
usePaymentMethods
|
|
24
|
+
} from '@teamnovu/kit-shopware-composables'
|
|
25
|
+
|
|
26
|
+
export default defineComponent({
|
|
27
|
+
setup() {
|
|
28
|
+
// Query products
|
|
29
|
+
const { data: products, isLoading } = useReadProductListingQuery('category-seo-url')
|
|
30
|
+
|
|
31
|
+
// Manage cart
|
|
32
|
+
const { data: cart } = useReadCartQuery()
|
|
33
|
+
const addToCart = useAddLineItemMutation()
|
|
34
|
+
|
|
35
|
+
// Checkout helpers
|
|
36
|
+
const { paymentMethods, setPaymentMethod } = usePaymentMethods()
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
products,
|
|
40
|
+
isLoading,
|
|
41
|
+
cart,
|
|
42
|
+
addToCart,
|
|
43
|
+
paymentMethods,
|
|
44
|
+
setPaymentMethod
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Setup & Configuration
|
|
51
|
+
|
|
52
|
+
### 1. Client Injection
|
|
53
|
+
|
|
54
|
+
Provide the Shopware client to your Vue app:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { createApp } from 'vue'
|
|
58
|
+
import { ShopwareClient } from '@teamnovu/kit-shopware-api-client'
|
|
59
|
+
import { provideShopwareQueryClient } from '@teamnovu/kit-shopware-composables'
|
|
60
|
+
|
|
61
|
+
const app = createApp(App)
|
|
62
|
+
|
|
63
|
+
const client = new ShopwareClient({
|
|
64
|
+
baseURL: 'https://your-shopware-store.com',
|
|
65
|
+
apiKey: 'your-api-key'
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
provideShopwareQueryClient(client)
|
|
69
|
+
app.mount('#app')
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 2. TanStack Query Setup
|
|
73
|
+
|
|
74
|
+
Install and configure TanStack Query:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm install @tanstack/vue-query
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { VueQueryPlugin } from '@tanstack/vue-query'
|
|
82
|
+
|
|
83
|
+
app.use(VueQueryPlugin)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Query Composables
|
|
87
|
+
|
|
88
|
+
### Product Queries
|
|
89
|
+
|
|
90
|
+
#### useReadCompactProductListingQuery
|
|
91
|
+
Query products by category or listing criteria:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const { data, isLoading, error } = useReadCompactProductListingQuery('category-seo-url', {
|
|
95
|
+
query: {
|
|
96
|
+
limit: 20,
|
|
97
|
+
page: 1,
|
|
98
|
+
'filter[price][gte]': 10
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### useReadCustomProductDetailQuery
|
|
104
|
+
Get detailed product information:
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const { data: product } = useReadCustomProductDetailQuery('product-seo-url')
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### useReadCategoryListQuery
|
|
111
|
+
Fetch category navigation:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const { data: categories } = useReadCategoryListQuery()
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Cart Queries & Mutations
|
|
118
|
+
|
|
119
|
+
#### useReadCartQuery
|
|
120
|
+
Get current cart state:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
const { data: cart, refetch } = useReadCartQuery()
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### useAddLineItemMutation
|
|
127
|
+
Add products to cart:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const addToCart = useAddLineItemMutation()
|
|
131
|
+
|
|
132
|
+
const handleAddToCart = () => {
|
|
133
|
+
addToCart.mutate({
|
|
134
|
+
items: [{
|
|
135
|
+
id: 'product-id',
|
|
136
|
+
quantity: 1,
|
|
137
|
+
type: 'product'
|
|
138
|
+
}]
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### useUpdateLineItemMutation
|
|
144
|
+
Update cart item quantities:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const updateItem = useUpdateLineItemMutation()
|
|
148
|
+
|
|
149
|
+
updateItem.mutate({
|
|
150
|
+
items: [{
|
|
151
|
+
id: 'line-item-id',
|
|
152
|
+
quantity: 3
|
|
153
|
+
}]
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
#### useRemoveLineItemMutation
|
|
158
|
+
Remove items from cart:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const removeItem = useRemoveLineItemMutation()
|
|
162
|
+
|
|
163
|
+
removeItem.mutate({
|
|
164
|
+
ids: ['line-item-id']
|
|
165
|
+
})
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Customer Queries & Mutations
|
|
169
|
+
|
|
170
|
+
#### useReadCustomerQuery
|
|
171
|
+
Get current customer data:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const { data: customer } = useReadCustomerQuery()
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### useLoginCustomerMutation
|
|
178
|
+
Handle customer login:
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
const login = useLoginCustomerMutation()
|
|
182
|
+
|
|
183
|
+
login.mutate({
|
|
184
|
+
email: 'user@example.com',
|
|
185
|
+
password: 'password'
|
|
186
|
+
})
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Address Management
|
|
190
|
+
|
|
191
|
+
#### useListAddressQuery
|
|
192
|
+
Fetch customer addresses:
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
const { data: addresses } = useListAddressQuery()
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Context & Settings
|
|
199
|
+
|
|
200
|
+
#### useReadContextQuery
|
|
201
|
+
Get current store context (currency, language, etc.):
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
const { data: context } = useReadContextQuery()
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### useUpdateContextMutation
|
|
208
|
+
Update store context:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
const updateContext = useUpdateContextMutation()
|
|
212
|
+
|
|
213
|
+
updateContext.mutate({
|
|
214
|
+
currencyId: 'eur-currency-id',
|
|
215
|
+
languageId: 'en-language-id'
|
|
216
|
+
})
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Helper Composables
|
|
220
|
+
|
|
221
|
+
### Checkout Helpers
|
|
222
|
+
|
|
223
|
+
#### usePaymentMethods
|
|
224
|
+
Manage payment methods:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
const {
|
|
228
|
+
paymentMethods, // Available payment methods
|
|
229
|
+
activePaymentMethod, // Currently selected method
|
|
230
|
+
setPaymentMethod, // Function to change method
|
|
231
|
+
isSaving // Loading state
|
|
232
|
+
} = usePaymentMethods()
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### useShippingMethods
|
|
236
|
+
Manage shipping methods:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const {
|
|
240
|
+
shippingMethods,
|
|
241
|
+
activeShippingMethod,
|
|
242
|
+
setShippingMethod,
|
|
243
|
+
isSaving
|
|
244
|
+
} = useShippingMethods()
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
#### useAddresses
|
|
248
|
+
Manage customer addresses:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
const {
|
|
252
|
+
addresses,
|
|
253
|
+
billingAddress,
|
|
254
|
+
shippingAddress,
|
|
255
|
+
setBillingAddress,
|
|
256
|
+
setShippingAddress,
|
|
257
|
+
isSaving
|
|
258
|
+
} = useAddresses()
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Product Helpers
|
|
262
|
+
|
|
263
|
+
#### useProductPrice
|
|
264
|
+
Calculate product pricing:
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
const {
|
|
268
|
+
price, // Calculated price object
|
|
269
|
+
displayPrice, // Formatted display price
|
|
270
|
+
wasPrice, // Original price (if on sale)
|
|
271
|
+
percentage // Discount percentage
|
|
272
|
+
} = useProductPrice(product, quantity)
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
#### useProductVariantForOptions
|
|
276
|
+
Handle product variants:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
const {
|
|
280
|
+
variant, // Selected variant
|
|
281
|
+
options, // Available options
|
|
282
|
+
selectOption // Function to select option
|
|
283
|
+
} = useProductVariantForOptions(product, selectedOptions)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### General Helpers
|
|
287
|
+
|
|
288
|
+
#### usePagination
|
|
289
|
+
Handle paginated results:
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
const {
|
|
293
|
+
page,
|
|
294
|
+
limit,
|
|
295
|
+
total,
|
|
296
|
+
totalPages,
|
|
297
|
+
nextPage,
|
|
298
|
+
prevPage,
|
|
299
|
+
goToPage
|
|
300
|
+
} = usePagination(initialPage, initialLimit)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### useSeoUrl
|
|
304
|
+
Handle SEO URL transformations:
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
const { seoUrl, canonicalUrl } = useSeoUrl(path)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### useIsLoggedIn
|
|
311
|
+
Check authentication status:
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
const { isLoggedIn, customer } = useIsLoggedIn()
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Utility Functions
|
|
318
|
+
|
|
319
|
+
### useOptimistic
|
|
320
|
+
Handle optimistic updates:
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const {
|
|
324
|
+
optimisticValue,
|
|
325
|
+
updateOptimistic
|
|
326
|
+
} = useOptimistic(initialValue)
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### unrefOptions
|
|
330
|
+
Utility for unreferencing reactive options:
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
const unrefdOptions = unrefOptions(maybeReactiveOptions)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Development Setup
|
|
337
|
+
|
|
338
|
+
### Docker Environment
|
|
339
|
+
|
|
340
|
+
The package includes a complete Docker setup for Shopware development:
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
# Generate API types
|
|
344
|
+
npm run gen-types
|
|
345
|
+
|
|
346
|
+
# Start development environment
|
|
347
|
+
cd docker && docker-compose up
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Type Generation
|
|
351
|
+
|
|
352
|
+
Generate TypeScript types from your Shopware instance:
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
npm run gen-types
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
This will:
|
|
359
|
+
1. Fetch the OpenAPI schema from your Shopware store
|
|
360
|
+
2. Generate TypeScript types in `api-types/`
|
|
361
|
+
3. Update operation definitions
|
|
362
|
+
|
|
363
|
+
## Best Practices
|
|
364
|
+
|
|
365
|
+
### Query Keys
|
|
366
|
+
Query keys are automatically generated and cached. Use the provided key factories for consistency:
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { productKeys, cartKeys, customerKeys } from '@teamnovu/kit-shopware-composables'
|
|
370
|
+
|
|
371
|
+
// Access query keys for manual cache management
|
|
372
|
+
queryClient.invalidateQueries(productKeys.lists())
|
|
373
|
+
queryClient.setQueryData(cartKeys.get(), newCartData)
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Error Handling
|
|
377
|
+
Handle errors consistently across queries:
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
const { data, error, isError } = useReadProductListingQuery('category')
|
|
381
|
+
|
|
382
|
+
if (isError && error instanceof ShopwareApiError) {
|
|
383
|
+
console.error('Shopware API Error:', error.status, error.response)
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Loading States
|
|
388
|
+
Leverage TanStack Query's built-in loading states:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
const { data, isLoading, isFetching, isStale } = useReadCartQuery()
|
|
392
|
+
|
|
393
|
+
// isLoading: First load
|
|
394
|
+
// isFetching: Any fetch (including background refetch)
|
|
395
|
+
// isStale: Data is outdated
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## Integration Examples
|
|
399
|
+
|
|
400
|
+
### E-commerce Product List
|
|
401
|
+
|
|
402
|
+
```vue
|
|
403
|
+
<template>
|
|
404
|
+
<div>
|
|
405
|
+
<div v-if="isLoading">Loading...</div>
|
|
406
|
+
<div v-else-if="error">Error: {{ error.message }}</div>
|
|
407
|
+
<div v-else>
|
|
408
|
+
<ProductCard
|
|
409
|
+
v-for="product in products?.elements"
|
|
410
|
+
:key="product.id"
|
|
411
|
+
:product="product"
|
|
412
|
+
@add-to-cart="handleAddToCart"
|
|
413
|
+
/>
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
416
|
+
</template>
|
|
417
|
+
|
|
418
|
+
<script setup>
|
|
419
|
+
import { useReadCompactProductListingQuery, useAddLineItemMutation } from '@teamnovu/kit-shopware-composables'
|
|
420
|
+
|
|
421
|
+
const { data: products, isLoading, error } = useReadCompactProductListingQuery('category-seo-url')
|
|
422
|
+
const addToCart = useAddLineItemMutation()
|
|
423
|
+
|
|
424
|
+
const handleAddToCart = (productId) => {
|
|
425
|
+
addToCart.mutate({
|
|
426
|
+
items: [{ id: productId, quantity: 1, type: 'product' }]
|
|
427
|
+
})
|
|
428
|
+
}
|
|
429
|
+
</script>
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Checkout Flow
|
|
433
|
+
|
|
434
|
+
```vue
|
|
435
|
+
<script setup>
|
|
436
|
+
import {
|
|
437
|
+
useReadCartQuery,
|
|
438
|
+
usePaymentMethods,
|
|
439
|
+
useShippingMethods,
|
|
440
|
+
useCheckout
|
|
441
|
+
} from '@teamnovu/kit-shopware-composables'
|
|
442
|
+
|
|
443
|
+
const { data: cart } = useReadCartQuery()
|
|
444
|
+
const { paymentMethods, setPaymentMethod } = usePaymentMethods()
|
|
445
|
+
const { shippingMethods, setShippingMethod } = useShippingMethods()
|
|
446
|
+
const { checkout, isCheckingOut } = useCheckout()
|
|
447
|
+
|
|
448
|
+
const handleCheckout = async () => {
|
|
449
|
+
try {
|
|
450
|
+
const order = await checkout()
|
|
451
|
+
// Handle successful checkout
|
|
452
|
+
} catch (error) {
|
|
453
|
+
// Handle checkout error
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
</script>
|
|
457
|
+
```
|
package/docs/info.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamnovu/kit-shopware-composables",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "A collection of composables for the Shopware API",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
"./operations": {
|
|
14
|
+
"types": "./dist/types/operations.d.ts"
|
|
12
15
|
}
|
|
13
16
|
},
|
|
14
17
|
"peerDependencies": {
|
|
@@ -24,6 +27,7 @@
|
|
|
24
27
|
"author": "Elias Bernhaut",
|
|
25
28
|
"homepage": "https://kit.novu.ch/packages/shopware-composables/",
|
|
26
29
|
"dependencies": {
|
|
30
|
+
"@vueuse/core": "^13.3.0",
|
|
27
31
|
"vite": "^6.2.5"
|
|
28
32
|
},
|
|
29
33
|
"devDependencies": {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Schemas } from '#store-types'
|
|
2
|
+
import { until } from '@vueuse/core'
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
import { useListAddressQuery } from '../../query/address/useListAddressQuery'
|
|
5
|
+
import { useReadContextQuery } from '../../query/context/useReadContextQuery'
|
|
6
|
+
import { useUpdateContextMutation } from '../../query/context/useUpdateContextMutation'
|
|
7
|
+
|
|
8
|
+
export function useCheckoutAddresses() {
|
|
9
|
+
const contextUpdateMutation = useUpdateContextMutation()
|
|
10
|
+
|
|
11
|
+
const contextQuery = useReadContextQuery()
|
|
12
|
+
const addressListQuery = useListAddressQuery()
|
|
13
|
+
|
|
14
|
+
const isSaving = computed(() => contextQuery.isFetching.value || contextUpdateMutation.isPending.value)
|
|
15
|
+
|
|
16
|
+
const setBillingAddress = async (address: Schemas['CustomerAddress']) => {
|
|
17
|
+
await contextUpdateMutation.mutateAsync({
|
|
18
|
+
billingAddressId: address.id,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
await until(isSaving).toBe(false)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const setShippingAddress = async (address: Schemas['CustomerAddress']) => {
|
|
25
|
+
await contextUpdateMutation.mutateAsync({
|
|
26
|
+
shippingAddressId: address.id,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
await until(isSaving).toBe(false)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const activeBillingAddress = computed(() => contextQuery.data.value?.customer?.activeBillingAddress)
|
|
33
|
+
const activeShippingAddress = computed(() => contextQuery.data.value?.customer?.activeShippingAddress)
|
|
34
|
+
|
|
35
|
+
const inactiveBillingAddresses = computed(() =>
|
|
36
|
+
addressListQuery.data.value?.elements.filter(
|
|
37
|
+
address => address.id !== activeBillingAddress.value?.id,
|
|
38
|
+
) ?? [])
|
|
39
|
+
|
|
40
|
+
const inactiveShippingAddresses = computed(() =>
|
|
41
|
+
addressListQuery.data.value?.elements.filter(
|
|
42
|
+
address => address.id !== activeBillingAddress.value?.id,
|
|
43
|
+
) ?? [])
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
contextUpdateMutation,
|
|
47
|
+
contextQuery,
|
|
48
|
+
addressListQuery,
|
|
49
|
+
setBillingAddress,
|
|
50
|
+
setShippingAddress,
|
|
51
|
+
isSaving,
|
|
52
|
+
activeBillingAddress,
|
|
53
|
+
activeShippingAddress,
|
|
54
|
+
inactiveBillingAddresses,
|
|
55
|
+
inactiveShippingAddresses,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { MaybeRef } from 'vue'
|
|
2
|
+
import { computed, unref } from 'vue'
|
|
3
|
+
import { useReadOrderQuery } from '../../query/order'
|
|
4
|
+
import { Schemas } from '../../query/types'
|
|
5
|
+
|
|
6
|
+
export function useOrderDetails(
|
|
7
|
+
orderId: MaybeRef<string>,
|
|
8
|
+
criteria?: Schemas['Criteria'],
|
|
9
|
+
) {
|
|
10
|
+
// Create reactive order query options
|
|
11
|
+
const orderQueryOptions = computed(() => {
|
|
12
|
+
const id = unref(orderId)
|
|
13
|
+
if (!id) return undefined
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
body: {
|
|
17
|
+
filter: [
|
|
18
|
+
{
|
|
19
|
+
type: 'equals',
|
|
20
|
+
field: 'id',
|
|
21
|
+
value: id,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
...criteria,
|
|
25
|
+
checkPromotion: true,
|
|
26
|
+
} as Schemas['Criteria'],
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// Create order query
|
|
31
|
+
const orderQuery = useReadOrderQuery(orderQueryOptions.value)
|
|
32
|
+
|
|
33
|
+
// Computed properties based on order data
|
|
34
|
+
const order = computed(() => orderQuery.data?.value?.orders?.elements?.[0])
|
|
35
|
+
|
|
36
|
+
const paymentChangeableList = computed(() => {
|
|
37
|
+
return orderQuery.data?.value?.paymentChangeable || {}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const status = computed(() => order.value?.stateMachineState?.translated?.name)
|
|
41
|
+
const statusTechnicalName = computed(() => order.value?.stateMachineState?.technicalName)
|
|
42
|
+
const total = computed(() => order.value?.price?.totalPrice)
|
|
43
|
+
const subtotal = computed(() => order.value?.price?.positionPrice)
|
|
44
|
+
const shippingCosts = computed(() => order.value?.shippingTotal)
|
|
45
|
+
|
|
46
|
+
const personalDetails = computed(() => ({
|
|
47
|
+
email: order.value?.orderCustomer?.email,
|
|
48
|
+
firstName: order.value?.orderCustomer?.firstName,
|
|
49
|
+
lastName: order.value?.orderCustomer?.lastName,
|
|
50
|
+
}))
|
|
51
|
+
|
|
52
|
+
const billingAddress = computed(() =>
|
|
53
|
+
order.value?.addresses?.find(
|
|
54
|
+
({ id }: { id: string }) => id === order.value?.billingAddressId,
|
|
55
|
+
))
|
|
56
|
+
|
|
57
|
+
const shippingAddress = computed(
|
|
58
|
+
() => order.value?.deliveries?.[0]?.shippingOrderAddress,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const paymentMethod = computed(() => {
|
|
62
|
+
const transactions = order.value?.transactions
|
|
63
|
+
if (!transactions?.length) return undefined
|
|
64
|
+
return transactions.at(-1)?.paymentMethod
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
const shippingMethod = computed(() => {
|
|
68
|
+
const deliveries = order.value?.deliveries
|
|
69
|
+
if (!deliveries?.length) return undefined
|
|
70
|
+
return deliveries.at(-1)?.shippingMethod
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const paymentChangeable = computed(() => {
|
|
74
|
+
const id = unref(orderId)
|
|
75
|
+
return paymentChangeableList.value?.[id] ?? false
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
order,
|
|
80
|
+
status,
|
|
81
|
+
statusTechnicalName,
|
|
82
|
+
total,
|
|
83
|
+
subtotal,
|
|
84
|
+
shippingCosts,
|
|
85
|
+
shippingAddress,
|
|
86
|
+
billingAddress,
|
|
87
|
+
personalDetails,
|
|
88
|
+
shippingMethod,
|
|
89
|
+
paymentMethod,
|
|
90
|
+
paymentChangeable,
|
|
91
|
+
orderQuery,
|
|
92
|
+
orderSetPaymentMutation,
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { MaybeRef } from 'vue'
|
|
2
|
+
import { computed, unref } from 'vue'
|
|
3
|
+
import { Schemas } from '../../query/types'
|
|
4
|
+
|
|
5
|
+
export function useOrderPayment(
|
|
6
|
+
order: MaybeRef<Schemas['Order'] | null | undefined>,
|
|
7
|
+
) {
|
|
8
|
+
const activeTransaction = computed(() =>
|
|
9
|
+
unref(order)?.transactions?.find(t => t.paymentMethod?.active === true))
|
|
10
|
+
|
|
11
|
+
const paymentMethod = computed(() => activeTransaction.value?.paymentMethod)
|
|
12
|
+
const state = computed(() => activeTransaction.value?.stateMachineState)
|
|
13
|
+
|
|
14
|
+
const isAsynchronous = computed(
|
|
15
|
+
() =>
|
|
16
|
+
// @ts-expect-error - This property does not seem to be declared in the typescript types
|
|
17
|
+
activeTransaction.value?.paymentMethod?.asynchronous
|
|
18
|
+
&& activeTransaction.value?.paymentMethod?.afterOrderEnabled,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
isAsynchronous,
|
|
23
|
+
activeTransaction,
|
|
24
|
+
state,
|
|
25
|
+
paymentMethod,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { computed } from 'vue'
|
|
2
|
+
import { useReadPaymentMethodQuery } from '../../query'
|
|
3
|
+
import { useReadContextQuery } from '../../query/context/useReadContextQuery'
|
|
4
|
+
import { useUpdateContextMutation } from '../../query/context/useUpdateContextMutation'
|
|
5
|
+
|
|
6
|
+
export function usePaymentMethods() {
|
|
7
|
+
const contextQuery = useReadContextQuery()
|
|
8
|
+
const contextUpdateMutation = useUpdateContextMutation()
|
|
9
|
+
const paymentMethodsQuery = useReadPaymentMethodQuery({
|
|
10
|
+
query: {
|
|
11
|
+
onlyActive: true,
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const isSaving = computed(() => contextUpdateMutation.isPending.value)
|
|
16
|
+
|
|
17
|
+
const setPaymentMethod = async (paymentMethodId: string) => {
|
|
18
|
+
return contextUpdateMutation.mutateAsync({
|
|
19
|
+
paymentMethodId,
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const activePaymentMethod = computed(() => contextQuery.data?.value?.paymentMethod)
|
|
24
|
+
const paymentMethods = computed(() => paymentMethodsQuery.data?.value?.elements)
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
contextUpdateMutation,
|
|
28
|
+
contextQuery,
|
|
29
|
+
paymentMethodsQuery,
|
|
30
|
+
activePaymentMethod,
|
|
31
|
+
setPaymentMethod,
|
|
32
|
+
isSaving,
|
|
33
|
+
paymentMethods,
|
|
34
|
+
}
|
|
35
|
+
}
|