@kasuvia/sdk 0.0.8 → 0.0.9

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.
Files changed (176) hide show
  1. package/README.md +42 -15
  2. package/dist/AddressAutocomplete-CjcqPElD.d.mts +46 -0
  3. package/dist/AddressAutocomplete-CvJHuRkf.d.ts +46 -0
  4. package/dist/components/index.d.mts +497 -0
  5. package/dist/components/index.d.ts +497 -0
  6. package/dist/components/index.js +4217 -0
  7. package/dist/components/index.js.map +1 -0
  8. package/dist/components/index.mjs +4194 -0
  9. package/dist/components/index.mjs.map +1 -0
  10. package/dist/config/server.d.mts +26 -0
  11. package/dist/config/server.d.ts +26 -0
  12. package/dist/config/server.js +38 -0
  13. package/dist/config/server.js.map +1 -0
  14. package/dist/config/server.mjs +13 -0
  15. package/dist/config/server.mjs.map +1 -0
  16. package/dist/hooks/index.d.mts +393 -160
  17. package/dist/hooks/index.d.ts +393 -160
  18. package/dist/hooks/index.js +2792 -2137
  19. package/dist/hooks/index.js.map +1 -1
  20. package/dist/hooks/index.mjs +2734 -2121
  21. package/dist/hooks/index.mjs.map +1 -1
  22. package/dist/index-CNW_LINy.d.mts +578 -0
  23. package/dist/index-CNW_LINy.d.ts +578 -0
  24. package/dist/{index-C1chUA3P.d.mts → index-F7N6UItS.d.mts} +1 -1
  25. package/dist/{index-C1chUA3P.d.ts → index-F7N6UItS.d.ts} +1 -1
  26. package/dist/index-NkI10J_E.d.mts +40 -0
  27. package/dist/index-NkI10J_E.d.ts +40 -0
  28. package/dist/index.d.mts +20437 -103
  29. package/dist/index.d.ts +20437 -103
  30. package/dist/index.js +2111 -1802
  31. package/dist/index.js.map +1 -1
  32. package/dist/index.mjs +2006 -1786
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/media.service-Cx7dQjzX.d.mts +1393 -0
  35. package/dist/media.service-mrBFJ2UQ.d.ts +1393 -0
  36. package/dist/services/index.d.mts +908 -2
  37. package/dist/services/index.d.ts +908 -2
  38. package/dist/services/index.js +1492 -1686
  39. package/dist/services/index.js.map +1 -1
  40. package/dist/services/index.mjs +1431 -1670
  41. package/dist/services/index.mjs.map +1 -1
  42. package/package.json +46 -6
  43. package/src/components/bespoke/BespokeAvailabilityBadge.tsx +32 -0
  44. package/src/components/bespoke/BespokeProgressTracker.tsx +58 -0
  45. package/src/components/bespoke/index.ts +3 -0
  46. package/src/components/booking/SlotPicker.tsx +97 -0
  47. package/src/components/booking/index.ts +1 -0
  48. package/src/components/cart/CartItem.tsx +81 -0
  49. package/src/components/cart/CartSidebar.tsx +115 -0
  50. package/src/components/cart/CartTypeMismatchBanner.tsx +55 -0
  51. package/src/components/cart/index.ts +3 -0
  52. package/src/components/index.ts +8 -0
  53. package/src/components/orders/DeliverableReviewer.tsx +139 -0
  54. package/src/components/orders/index.ts +1 -0
  55. package/src/components/product/ProductCard.tsx +350 -0
  56. package/src/components/product/ProductGrid.tsx +84 -0
  57. package/src/components/product/index.ts +2 -0
  58. package/src/components/shared/AddressAutocomplete.tsx +212 -0
  59. package/src/components/shared/AnalyticsScripts.tsx +56 -0
  60. package/src/components/shared/CookieConsentBanner.tsx +98 -0
  61. package/src/components/shared/ImageEditorModal.tsx +1066 -0
  62. package/src/components/shared/ImageViewerModal.tsx +598 -0
  63. package/src/components/shared/LucideReactIcon.tsx +52 -0
  64. package/src/components/shared/MapPinDrop.tsx +101 -0
  65. package/src/components/shared/MultiSelectPicker.tsx +193 -0
  66. package/src/components/shared/OfflineBanner.tsx +46 -0
  67. package/src/components/shared/SearchableInput.tsx +153 -0
  68. package/src/components/shared/SearchablePopover.tsx +166 -0
  69. package/src/components/shared/SmartImage.tsx +311 -0
  70. package/src/components/shared/TruncatedValue.tsx +27 -0
  71. package/src/components/shared/UnsavedChangesGuard.tsx +138 -0
  72. package/src/components/shared/index.ts +15 -0
  73. package/src/components/skeletons/CardSkeleton.tsx +26 -0
  74. package/src/components/skeletons/CartItemSkeleton.tsx +26 -0
  75. package/src/components/skeletons/OrderItemSkeleton.tsx +26 -0
  76. package/src/components/skeletons/ProductCardSkeleton.tsx +26 -0
  77. package/src/components/skeletons/TableSkeleton.tsx +42 -0
  78. package/src/components/skeletons/index.ts +5 -0
  79. package/src/config/index.ts +22 -4
  80. package/src/config/server.ts +45 -0
  81. package/src/context/sdk-context.tsx +5 -2
  82. package/src/generated/auth-openapi.ts +2935 -0
  83. package/src/generated/cart-openapi.ts +652 -0
  84. package/src/generated/cms-openapi.ts +1668 -0
  85. package/src/generated/crm-openapi.ts +986 -0
  86. package/src/generated/graphql.ts +126 -0
  87. package/src/generated/index.ts +11 -0
  88. package/src/generated/media-openapi.ts +613 -0
  89. package/src/generated/notification-openapi.ts +862 -0
  90. package/src/generated/payment-openapi.ts +2713 -0
  91. package/src/generated/store-openapi.ts +9510 -0
  92. package/src/graphql/operations/collections.graphql +32 -0
  93. package/src/graphql/operations/products.graphql +197 -0
  94. package/src/graphql/operations/wishlist.graphql +25 -0
  95. package/src/hooks/index.ts +9 -2
  96. package/src/hooks/use-auth.ts +163 -69
  97. package/src/hooks/use-bespoke-availability.ts +39 -22
  98. package/src/hooks/use-business-config.ts +51 -0
  99. package/src/hooks/use-cart.ts +310 -238
  100. package/src/hooks/use-cms.ts +107 -127
  101. package/src/hooks/use-collections.ts +35 -55
  102. package/src/hooks/use-consultations.ts +9 -136
  103. package/src/hooks/use-countries.ts +19 -28
  104. package/src/hooks/use-currencies.ts +8 -20
  105. package/src/hooks/use-customer-address.ts +64 -0
  106. package/src/hooks/use-feedback.ts +34 -0
  107. package/src/hooks/use-languages.ts +26 -39
  108. package/src/hooks/use-media-upload.ts +23 -0
  109. package/src/hooks/use-notification-stream.ts +88 -0
  110. package/src/hooks/use-notifications.ts +163 -0
  111. package/src/hooks/use-order-stream.ts +29 -29
  112. package/src/hooks/use-orders.ts +91 -73
  113. package/src/hooks/use-payment.ts +116 -84
  114. package/src/hooks/use-products.ts +65 -269
  115. package/src/hooks/use-push-notifications.ts +122 -0
  116. package/src/hooks/use-reviews.ts +175 -0
  117. package/src/hooks/use-service-booking.ts +109 -132
  118. package/src/hooks/use-states.ts +16 -30
  119. package/src/hooks/use-wishlist.ts +44 -69
  120. package/src/index.ts +15 -11
  121. package/src/services/auth.service.ts +422 -132
  122. package/src/services/bespoke.service.ts +69 -10
  123. package/src/services/cart.service.ts +155 -186
  124. package/src/services/cms.service.ts +41 -50
  125. package/src/services/collection.service.ts +25 -63
  126. package/src/services/config.service.ts +10 -21
  127. package/src/services/consultation.service.ts +36 -93
  128. package/src/services/feedback.service.ts +76 -0
  129. package/src/services/index.ts +7 -1
  130. package/src/services/legal.service.ts +62 -0
  131. package/src/services/logistics.service.ts +235 -53
  132. package/src/services/media.service.ts +115 -0
  133. package/src/services/notifications.service.ts +204 -20
  134. package/src/services/order.service.ts +498 -127
  135. package/src/services/payment.service.ts +149 -100
  136. package/src/services/product.service.ts +157 -814
  137. package/src/services/review.service.ts +211 -0
  138. package/src/services/service-booking.service.ts +198 -99
  139. package/src/services/wishlist.service.ts +27 -74
  140. package/src/types/auth/index.ts +161 -18
  141. package/src/types/business/index.ts +9 -1
  142. package/src/types/cms/index.ts +91 -6
  143. package/src/types/cms/legal.ts +18 -0
  144. package/src/types/consultations/index.ts +60 -68
  145. package/src/types/index.ts +5 -3
  146. package/src/types/media/index.ts +35 -3
  147. package/src/types/payments/index.ts +80 -16
  148. package/src/types/reviews/index.ts +116 -0
  149. package/src/types/services/index.ts +113 -38
  150. package/src/types/store/checkout.ts +53 -0
  151. package/src/types/store/index.ts +273 -52
  152. package/src/types/store/invoice.ts +31 -0
  153. package/src/types/store/shipping.ts +84 -3
  154. package/src/types/ui/index.ts +1 -1
  155. package/src/utils/checkout.ts +19 -3
  156. package/src/utils/cookieConsent.ts +34 -0
  157. package/src/utils/format.ts +408 -0
  158. package/src/utils/geolocation.ts +134 -0
  159. package/src/utils/graphql-url.ts +47 -0
  160. package/src/utils/guest-session.ts +59 -0
  161. package/src/utils/http-client.ts +147 -0
  162. package/src/utils/index.ts +11 -4
  163. package/src/utils/status-colors.ts +79 -0
  164. package/src/utils/token-refresh.ts +115 -0
  165. package/src/utils/validators.ts +13 -0
  166. package/src/utils/youtube.ts +18 -0
  167. package/dist/index-C5YO9gTl.d.mts +0 -507
  168. package/dist/index-C5YO9gTl.d.ts +0 -507
  169. package/dist/index-CefG7_xq.d.mts +0 -793
  170. package/dist/index-DeHCf3zI.d.ts +0 -793
  171. package/src/graphql/collections.graphql.ts +0 -48
  172. package/src/graphql/index.ts +0 -7
  173. package/src/graphql/products.graphql.ts +0 -860
  174. package/src/graphql/wishlist.graphql.ts +0 -34
  175. package/src/hooks/use-consultation-stream.ts +0 -142
  176. package/src/types/bespoke/index.ts +0 -39
@@ -11,170 +11,147 @@ import {
11
11
  getAppointments,
12
12
  getAppointment,
13
13
  cancelAppointment,
14
- getDeliverables,
15
- approveDeliverable,
16
- requestRevision,
14
+ rescheduleAppointment,
15
+ disputeAppointment,
16
+ confirmAppointmentCompletion,
17
+ getMilestones,
18
+ approveMilestone,
17
19
  } from '../services/service-booking.service'
18
20
  import type { SdkConfig } from '../config'
19
21
  import type {
22
+ ServiceAppointment,
20
23
  ServiceAppointmentCreatePayload,
24
+ CancelAppointmentPayload,
25
+ RescheduleAppointmentPayload,
26
+ DisputeAppointmentPayload,
27
+ ConfirmAppointmentPayload,
28
+ ApproveMilestonePayload,
21
29
  } from '../types/services'
22
- import { logger } from '../utils'
23
30
  import { useSdkContext, resolveHookArgs } from '../context/sdk-context'
24
31
 
25
32
  export function useAvailableSlots(
26
- arg1?: SdkConfig | string,
27
- arg2?: string,
28
- arg3?: string,
29
- arg4?: string
33
+ config: SdkConfig | undefined,
34
+ productId: string | undefined,
35
+ date: string | undefined,
36
+ params?: { staffId?: string; locationId?: string; customerLatitude?: number; customerLongitude?: number }
30
37
  ) {
31
38
  const ctx = useSdkContext()
32
- const isArg1Config = typeof arg1 === 'object' && arg1 !== null && 'businessId' in arg1
33
- const explicitConfig = isArg1Config ? (arg1 as SdkConfig) : undefined
34
- const product_id = isArg1Config ? arg2 : (typeof arg1 === 'string' ? arg1 : undefined)
35
- const date_from = isArg1Config ? arg3 : (typeof arg2 === 'string' ? arg2 : undefined)
36
- const date_to = isArg1Config ? arg4 : (typeof arg3 === 'string' ? arg3 : undefined)
37
-
38
- try {
39
- const { config: cfg } = resolveHookArgs(explicitConfig, undefined, ctx)
40
- return useQuery({
41
- queryKey: ["available-slots", product_id, date_from, date_to],
42
- queryFn: () => getAvailableSlots(cfg, product_id!, date_from!, date_to!),
43
- enabled: !!product_id && !!date_from && !!date_to,
44
- })
45
- } catch (error) {
46
- logger.warn('[useAvailableSlots] Called outside QueryClientProvider, returning undefined')
47
- return { data: undefined, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: undefined }) } as any
48
- }
39
+ const { config: cfg } = resolveHookArgs(config, undefined, ctx)
40
+ return useQuery({
41
+ queryKey: ["available-slots", productId, date, params?.staffId, params?.locationId],
42
+ queryFn: () => getAvailableSlots(cfg, productId!, date!, params),
43
+ enabled: !!productId && !!date,
44
+ })
49
45
  }
50
46
 
51
47
  export function useBookAppointment(config?: SdkConfig, accessToken?: string | null) {
52
48
  const ctx = useSdkContext()
53
- try {
54
- const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
55
- const queryClient = useQueryClient()
56
- return useMutation({
57
- mutationFn: (payload: ServiceAppointmentCreatePayload) =>
58
- token ? bookAppointment(cfg, token, payload) : Promise.reject('No access token'),
59
- onSuccess: () => {
60
- queryClient.invalidateQueries({ queryKey: ["appointments"] })
61
- },
62
- })
63
- } catch (error) {
64
- logger.warn('[useBookAppointment] Called outside QueryClientProvider, returning no-op mutation')
65
- return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
66
- }
49
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
50
+ const queryClient = useQueryClient()
51
+ return useMutation({
52
+ mutationFn: (payload: ServiceAppointmentCreatePayload) =>
53
+ token ? bookAppointment(cfg, token, payload) : Promise.reject(new Error('No access token available')),
54
+ onSuccess: () => {
55
+ queryClient.invalidateQueries({ queryKey: ["appointments"] })
56
+ },
57
+ })
67
58
  }
68
59
 
69
- export function useAppointments(config?: SdkConfig, accessToken?: string | null) {
60
+ export function useAppointments(
61
+ config?: SdkConfig,
62
+ accessToken?: string | null,
63
+ params?: { status?: ServiceAppointment['status']; page?: number; page_size?: number }
64
+ ) {
70
65
  const ctx = useSdkContext()
71
- try {
72
- const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
73
- return useQuery({
74
- queryKey: ["appointments"],
75
- queryFn: () => token ? getAppointments(cfg, token) : Promise.resolve([]),
76
- enabled: !!token,
77
- })
78
- } catch (error) {
79
- logger.warn('[useAppointments] Called outside QueryClientProvider, returning empty list')
80
- return { data: undefined, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: undefined }) } as any
81
- }
66
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
67
+ return useQuery({
68
+ queryKey: ["appointments", params?.status, params?.page, params?.page_size],
69
+ queryFn: () => token ? getAppointments(cfg, token, params) : Promise.reject(new Error('No access token available')),
70
+ enabled: !!token,
71
+ })
82
72
  }
83
73
 
84
- export function useAppointment(arg1?: SdkConfig | string, arg2?: string | null, arg3?: string) {
74
+ export function useAppointment(config: SdkConfig | undefined, accessToken: string | null | undefined, id: string | undefined) {
85
75
  const ctx = useSdkContext()
86
- const isArg1Config = typeof arg1 === 'object' && arg1 !== null && 'businessId' in arg1
87
- const explicitConfig = isArg1Config ? (arg1 as SdkConfig) : undefined
88
- const explicitToken = isArg1Config ? (arg2 as string | null) : undefined
89
- const id = isArg1Config ? arg3 : (typeof arg1 === 'string' ? arg1 : undefined)
90
-
91
- try {
92
- const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
93
- return useQuery({
94
- queryKey: ["appointment", id],
95
- queryFn: () => token && id ? getAppointment(cfg, token, id) : Promise.resolve(undefined),
96
- enabled: !!id && !!token,
97
- })
98
- } catch (error) {
99
- logger.warn('[useAppointment] Called outside QueryClientProvider, returning undefined')
100
- return { data: undefined, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: undefined }) } as any
101
- }
76
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
77
+ return useQuery({
78
+ queryKey: ["appointment", id],
79
+ queryFn: () => token && id ? getAppointment(cfg, token, id) : Promise.reject(new Error('Missing appointment ID or access token')),
80
+ enabled: !!id && !!token,
81
+ })
102
82
  }
103
83
 
104
84
  export function useCancelAppointment(config?: SdkConfig, accessToken?: string | null) {
105
85
  const ctx = useSdkContext()
106
- try {
107
- const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
108
- const queryClient = useQueryClient()
109
- return useMutation({
110
- mutationFn: (id: string) =>
111
- token ? cancelAppointment(cfg, token, id) : Promise.reject('No access token'),
112
- onSuccess: () => {
113
- queryClient.invalidateQueries({ queryKey: ["appointments"] })
114
- },
115
- })
116
- } catch (error) {
117
- logger.warn('[useCancelAppointment] Called outside QueryClientProvider, returning no-op mutation')
118
- return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
119
- }
86
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
87
+ const queryClient = useQueryClient()
88
+ return useMutation({
89
+ mutationFn: ({ id, payload }: { id: string; payload?: CancelAppointmentPayload }) =>
90
+ token ? cancelAppointment(cfg, token, id, payload) : Promise.reject(new Error('No access token available')),
91
+ onSuccess: () => {
92
+ queryClient.invalidateQueries({ queryKey: ["appointments"] })
93
+ },
94
+ })
95
+ }
96
+
97
+ export function useRescheduleAppointment(config?: SdkConfig, accessToken?: string | null) {
98
+ const ctx = useSdkContext()
99
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
100
+ const queryClient = useQueryClient()
101
+ return useMutation({
102
+ mutationFn: ({ id, payload }: { id: string; payload: RescheduleAppointmentPayload }) =>
103
+ token ? rescheduleAppointment(cfg, token, id, payload) : Promise.reject(new Error('No access token available')),
104
+ onSuccess: () => {
105
+ queryClient.invalidateQueries({ queryKey: ["appointments"] })
106
+ },
107
+ })
120
108
  }
121
109
 
122
- export function useDeliverables(arg1?: SdkConfig | string, arg2?: string | null, arg3?: string) {
110
+ export function useDisputeAppointment(config?: SdkConfig, accessToken?: string | null) {
123
111
  const ctx = useSdkContext()
124
- const isArg1Config = typeof arg1 === 'object' && arg1 !== null && 'businessId' in arg1
125
- const explicitConfig = isArg1Config ? (arg1 as SdkConfig) : undefined
126
- const explicitToken = isArg1Config ? (arg2 as string | null) : undefined
127
- const order_id = isArg1Config ? arg3 : (typeof arg1 === 'string' ? arg1 : undefined)
112
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
113
+ const queryClient = useQueryClient()
114
+ return useMutation({
115
+ mutationFn: ({ id, payload }: { id: string; payload: DisputeAppointmentPayload }) =>
116
+ token ? disputeAppointment(cfg, token, id, payload) : Promise.reject(new Error('No access token available')),
117
+ onSuccess: () => {
118
+ queryClient.invalidateQueries({ queryKey: ["appointments"] })
119
+ },
120
+ })
121
+ }
128
122
 
129
- try {
130
- const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
131
- return useQuery({
132
- queryKey: ["deliverables", order_id],
133
- queryFn: () => token && order_id ? getDeliverables(cfg, token, order_id) : Promise.resolve([]),
134
- enabled: !!order_id && !!token,
135
- })
136
- } catch (error) {
137
- logger.warn('[useDeliverables] Called outside QueryClientProvider, returning empty list')
138
- return { data: undefined, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: undefined }) } as any
139
- }
123
+ export function useConfirmAppointmentCompletion(config?: SdkConfig, accessToken?: string | null) {
124
+ const ctx = useSdkContext()
125
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
126
+ const queryClient = useQueryClient()
127
+ return useMutation({
128
+ mutationFn: ({ id, payload }: { id: string; payload?: ConfirmAppointmentPayload }) =>
129
+ token ? confirmAppointmentCompletion(cfg, token, id, payload) : Promise.reject(new Error('No access token available')),
130
+ onSuccess: () => {
131
+ queryClient.invalidateQueries({ queryKey: ["appointments"] })
132
+ },
133
+ })
140
134
  }
141
135
 
142
- export function useApproveDeliverable(config?: SdkConfig, accessToken?: string | null, order_id?: string, deliverable_id?: string) {
136
+ export function useMilestones(config: SdkConfig | undefined, accessToken: string | null | undefined, bookingId: string | undefined) {
143
137
  const ctx = useSdkContext()
144
- try {
145
- const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
146
- const queryClient = useQueryClient()
147
- return useMutation({
148
- mutationFn: () =>
149
- token && order_id && deliverable_id
150
- ? approveDeliverable(cfg, token, order_id, deliverable_id)
151
- : Promise.reject('No access token'),
152
- onSuccess: () => {
153
- queryClient.invalidateQueries({ queryKey: ["deliverables", order_id] })
154
- },
155
- })
156
- } catch (error) {
157
- logger.warn('[useApproveDeliverable] Called outside QueryClientProvider, returning no-op mutation')
158
- return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
159
- }
138
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
139
+ return useQuery({
140
+ queryKey: ["milestones", bookingId],
141
+ queryFn: () => token && bookingId ? getMilestones(cfg, token, bookingId) : Promise.reject(new Error('Missing booking ID or access token')),
142
+ enabled: !!bookingId && !!token,
143
+ })
160
144
  }
161
145
 
162
- export function useRequestRevision(config?: SdkConfig, accessToken?: string | null, order_id?: string, deliverable_id?: string) {
146
+ export function useApproveMilestone(config?: SdkConfig, accessToken?: string | null) {
163
147
  const ctx = useSdkContext()
164
- try {
165
- const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
166
- const queryClient = useQueryClient()
167
- return useMutation({
168
- mutationFn: (feedback: string) =>
169
- token && order_id && deliverable_id
170
- ? requestRevision(cfg, token, order_id, deliverable_id, feedback)
171
- : Promise.reject('No access token'),
172
- onSuccess: () => {
173
- queryClient.invalidateQueries({ queryKey: ["deliverables", order_id] })
174
- },
175
- })
176
- } catch (error) {
177
- logger.warn('[useRequestRevision] Called outside QueryClientProvider, returning no-op mutation')
178
- return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
179
- }
148
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
149
+ const queryClient = useQueryClient()
150
+ return useMutation({
151
+ mutationFn: ({ bookingId, milestoneId, payload }: { bookingId: string; milestoneId: string; payload?: ApproveMilestonePayload }) =>
152
+ token ? approveMilestone(cfg, token, bookingId, milestoneId, payload) : Promise.reject(new Error('No access token available')),
153
+ onSuccess: (_data, variables) => {
154
+ queryClient.invalidateQueries({ queryKey: ["milestones", variables.bookingId] })
155
+ },
156
+ })
180
157
  }
@@ -7,42 +7,28 @@
7
7
  import { useQuery } from '@tanstack/react-query'
8
8
  import type { SdkConfig } from '../config'
9
9
  import type { State } from '../types/ui'
10
- import { logger } from '../utils'
11
10
  import { useSdkContext, resolveHookArgs } from '../context/sdk-context'
11
+ import { apiRequest, storefrontHeaders } from '../utils/http-client'
12
12
 
13
+ /** Raw fetch() -> apiRequest, same fix as use-countries.ts. */
13
14
  export async function getStates(config: SdkConfig, countryIso: string): Promise<State[]> {
14
- if (!countryIso) return []
15
- const response = await fetch(`${config.backendUrls.auth}/auth/countries/?iso=${countryIso}`, {
16
- headers: {
17
- "X-Storefront-Key": config.storefrontApiKey,
18
- "X-Business-ID": config.businessId,
19
- },
15
+ if (!countryIso) throw new Error('Country ISO is required to fetch states')
16
+ return apiRequest<State[]>(`${config.backendUrls.auth}/auth/countries/${encodeURIComponent(countryIso)}/states/`, {
17
+ headers: storefrontHeaders(config),
18
+ fallbackErrorMessage: 'Failed to fetch states',
20
19
  })
21
- if (!response.ok) throw new Error('Failed to fetch states')
22
- return response.json()
23
20
  }
24
21
 
25
22
  export function useStates(countryIso: string, config?: SdkConfig) {
26
23
  const ctx = useSdkContext()
27
- try {
28
- const { config: cfg } = resolveHookArgs(config, undefined, ctx)
29
- return useQuery({
30
- queryKey: ['states', countryIso],
31
- queryFn: () => getStates(cfg, countryIso),
32
- enabled: !!countryIso,
33
- retry: 1,
34
- refetchOnWindowFocus: false,
35
- refetchOnReconnect: false,
36
- staleTime: 24 * 60 * 60 * 1000,
37
- })
38
- } catch (error) {
39
- logger.warn('[useStates] Called outside QueryClientProvider, returning empty list')
40
- return {
41
- data: [],
42
- isLoading: false,
43
- error: null,
44
- isFetching: false,
45
- refetch: () => Promise.resolve({ data: [] }),
46
- } as any
47
- }
24
+ const { config: cfg } = resolveHookArgs(config, undefined, ctx)
25
+ return useQuery({
26
+ queryKey: ['states', countryIso],
27
+ queryFn: () => getStates(cfg, countryIso),
28
+ enabled: !!countryIso,
29
+ retry: 1,
30
+ refetchOnWindowFocus: false,
31
+ refetchOnReconnect: false,
32
+ staleTime: 24 * 60 * 60 * 1000,
33
+ })
48
34
  }
@@ -29,18 +29,13 @@ export function useWishlist(arg1?: SdkConfig | { page?: number; pageSize?: numbe
29
29
  const explicitToken = isArg1Config ? arg2 : undefined
30
30
  const params = isArg1Config ? arg3 : (arg1 as { page?: number; pageSize?: number } | undefined)
31
31
 
32
- try {
33
- const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
34
- return useQuery({
35
- queryKey: [...wishlistKeys.list(), params],
36
- queryFn: () => token ? getWishlist(cfg, token, params) : Promise.resolve(undefined),
37
- enabled: !!token,
38
- ...getCacheTier('medium'),
39
- })
40
- } catch (error) {
41
- console.warn('[useWishlist] Called outside QueryClientProvider, returning empty wishlist')
42
- return { data: undefined, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: undefined }) } as any
43
- }
32
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
33
+ return useQuery({
34
+ queryKey: [...wishlistKeys.list(), params],
35
+ queryFn: () => token ? getWishlist(cfg, token, params) : Promise.reject(new Error('No access token available')),
36
+ enabled: !!token,
37
+ ...getCacheTier('medium'),
38
+ })
44
39
  }
45
40
 
46
41
  export function useCheckInWishlist(arg1?: SdkConfig | string, arg2?: string | null, arg3?: string) {
@@ -50,73 +45,53 @@ export function useCheckInWishlist(arg1?: SdkConfig | string, arg2?: string | nu
50
45
  const explicitToken = isArg1Config ? (arg2 as string | null) : undefined
51
46
  const productId = isArg1Config ? arg3 : (typeof arg1 === 'string' ? arg1 : undefined)
52
47
 
53
- try {
54
- const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
55
- return useQuery({
56
- queryKey: wishlistKeys.check(productId ?? ''),
57
- queryFn: () => token && productId ? checkInWishlist(cfg, token, productId) : Promise.resolve({ in_wishlist: false }),
58
- ...getCacheTier('low'),
59
- enabled: !!productId && !!token,
60
- })
61
- } catch (error) {
62
- console.warn('[useCheckInWishlist] Called outside QueryClientProvider, returning false')
63
- return { data: false, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: false }) } as any
64
- }
48
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
49
+ return useQuery({
50
+ queryKey: wishlistKeys.check(productId ?? ''),
51
+ queryFn: () => token && productId ? checkInWishlist(cfg, token, productId) : Promise.resolve({ in_wishlist: false }),
52
+ ...getCacheTier('low'),
53
+ enabled: !!productId && !!token,
54
+ })
65
55
  }
66
56
 
67
57
  export function useAddToWishlist(config?: SdkConfig, accessToken?: string | null) {
68
58
  const ctx = useSdkContext()
69
- try {
70
- const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
71
- const queryClient = useQueryClient()
72
- return useMutation({
73
- mutationFn: ({ productId, notes }: { productId: string; notes?: string }) =>
74
- token ? addToWishlist(cfg, token, productId, notes) : Promise.reject('No access token'),
75
- onSuccess: () => {
76
- queryClient.invalidateQueries({ queryKey: wishlistKeys.all })
77
- queryClient.invalidateQueries({ queryKey: ['wishlist', 'check'] })
78
- },
79
- })
80
- } catch (error) {
81
- console.warn('[useAddToWishlist] Called outside QueryClientProvider, returning no-op mutation')
82
- return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
83
- }
59
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
60
+ const queryClient = useQueryClient()
61
+ return useMutation({
62
+ mutationFn: ({ productId, notes }: { productId: string; notes?: string }) =>
63
+ token ? addToWishlist(cfg, token, productId, notes) : Promise.reject(new Error('No access token available')),
64
+ onSuccess: () => {
65
+ queryClient.invalidateQueries({ queryKey: wishlistKeys.all })
66
+ queryClient.invalidateQueries({ queryKey: ['wishlist', 'check'] })
67
+ },
68
+ })
84
69
  }
85
70
 
86
71
  export function useRemoveFromWishlist(config?: SdkConfig, accessToken?: string | null) {
87
72
  const ctx = useSdkContext()
88
- try {
89
- const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
90
- const queryClient = useQueryClient()
91
- return useMutation({
92
- mutationFn: (itemId: string) =>
93
- token ? removeFromWishlist(cfg, token, itemId) : Promise.reject('No access token'),
94
- onSuccess: () => {
95
- queryClient.invalidateQueries({ queryKey: wishlistKeys.all })
96
- queryClient.invalidateQueries({ queryKey: ['wishlist', 'check'] })
97
- },
98
- })
99
- } catch (error) {
100
- console.warn('[useRemoveFromWishlist] Called outside QueryClientProvider, returning no-op mutation')
101
- return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
102
- }
73
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
74
+ const queryClient = useQueryClient()
75
+ return useMutation({
76
+ mutationFn: (itemId: string) =>
77
+ token ? removeFromWishlist(cfg, token, itemId) : Promise.reject(new Error('No access token available')),
78
+ onSuccess: () => {
79
+ queryClient.invalidateQueries({ queryKey: wishlistKeys.all })
80
+ queryClient.invalidateQueries({ queryKey: ['wishlist', 'check'] })
81
+ },
82
+ })
103
83
  }
104
84
 
105
85
  export function useRemoveProductFromWishlist(config?: SdkConfig, accessToken?: string | null) {
106
86
  const ctx = useSdkContext()
107
- try {
108
- const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
109
- const queryClient = useQueryClient()
110
- return useMutation({
111
- mutationFn: (productId: string) =>
112
- token ? removeProductFromWishlist(cfg, token, productId) : Promise.reject('No access token'),
113
- onSuccess: () => {
114
- queryClient.invalidateQueries({ queryKey: wishlistKeys.all })
115
- queryClient.invalidateQueries({ queryKey: ['wishlist', 'check'] })
116
- },
117
- })
118
- } catch (error) {
119
- console.warn('[useRemoveProductFromWishlist] Called outside QueryClientProvider, returning no-op mutation')
120
- return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
121
- }
87
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
88
+ const queryClient = useQueryClient()
89
+ return useMutation({
90
+ mutationFn: (productId: string) =>
91
+ token ? removeProductFromWishlist(cfg, token, productId) : Promise.reject(new Error('No access token available')),
92
+ onSuccess: () => {
93
+ queryClient.invalidateQueries({ queryKey: wishlistKeys.all })
94
+ queryClient.invalidateQueries({ queryKey: ['wishlist', 'check'] })
95
+ },
96
+ })
122
97
  }
package/src/index.ts CHANGED
@@ -40,23 +40,27 @@ export { STORAGE_KEYS, PAYMENT_URLS } from './constants'
40
40
 
41
41
  // Types
42
42
  export * from './types'
43
+ export * from './generated'
43
44
 
44
45
  // Services (for server components)
45
46
  export * from './services'
46
47
 
47
48
  // Utils
48
- export { getCacheTier, setEnvironmentMode } from './utils/cache'
49
- export { logger, setLoggerEnvironmentMode } from './utils/logger'
50
- export * from './utils/sanitize-url'
51
- export * from './utils/customer'
52
- export * from './utils/checkout'
53
- export * from './utils/error-handler'
54
- export { sessionStore, localStore } from './utils/storage'
55
- export * from './utils/validators'
49
+ // REAL DUPLICATION FIXED (2026-09-22): this used to hand-list every utils
50
+ // submodule a second time, separately from utils/index.ts's own barrel —
51
+ // two lists to keep in sync by hand, and they'd already drifted:
52
+ // http-client.ts and graphql-url.ts (both touched/built this session) were
53
+ // missing from this file entirely, meaning `apiRequest`/`ApiError`/
54
+ // `createGraphQLClient` etc. were never actually reachable from the public
55
+ // `@kasuvia/sdk` package a consumer imports, despite being real, complete,
56
+ // consistency-critical pieces of the SDK. Delegates to the one real barrel
57
+ // (utils/index.ts) instead of re-declaring the same list twice.
58
+ export * from './utils'
56
59
 
57
60
  // App service functions
58
61
  export { googleTranslate } from './services/app.service'
59
62
 
60
- // Note: React Context providers and hooks are exported separately via '@kasuvia/sdk/hooks'
61
- // to avoid importing them in server components. Use:
62
- // import { SdkProvider, useSdkContext } from '@kasuvia/sdk/hooks'
63
+ // Note: React components are exported separately via '@kasuvia/sdk/components'
64
+ // and React Context providers & hooks are exported via '@kasuvia/sdk/hooks'
65
+ // to maintain clear separation for server/client modules.
66
+