@growsober/sdk 1.0.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.
Files changed (129) hide show
  1. package/README.md +276 -0
  2. package/dist/__tests__/e2e.test.d.ts +7 -0
  3. package/dist/__tests__/e2e.test.js +472 -0
  4. package/dist/api/client.d.ts +11 -0
  5. package/dist/api/client.js +61 -0
  6. package/dist/api/mutations/admin.d.ts +167 -0
  7. package/dist/api/mutations/admin.js +326 -0
  8. package/dist/api/mutations/ambassadors.d.ts +52 -0
  9. package/dist/api/mutations/ambassadors.js +148 -0
  10. package/dist/api/mutations/auth.d.ts +267 -0
  11. package/dist/api/mutations/auth.js +332 -0
  12. package/dist/api/mutations/bookings.d.ts +59 -0
  13. package/dist/api/mutations/bookings.js +143 -0
  14. package/dist/api/mutations/event-chat.d.ts +35 -0
  15. package/dist/api/mutations/event-chat.js +147 -0
  16. package/dist/api/mutations/events.d.ts +87 -0
  17. package/dist/api/mutations/events.js +205 -0
  18. package/dist/api/mutations/grow90.d.ts +36 -0
  19. package/dist/api/mutations/grow90.js +132 -0
  20. package/dist/api/mutations/hubs.d.ts +111 -0
  21. package/dist/api/mutations/hubs.js +240 -0
  22. package/dist/api/mutations/index.d.ts +22 -0
  23. package/dist/api/mutations/index.js +39 -0
  24. package/dist/api/mutations/jack.d.ts +61 -0
  25. package/dist/api/mutations/jack.js +104 -0
  26. package/dist/api/mutations/library.d.ts +67 -0
  27. package/dist/api/mutations/library.js +168 -0
  28. package/dist/api/mutations/map.d.ts +153 -0
  29. package/dist/api/mutations/map.js +181 -0
  30. package/dist/api/mutations/matching.d.ts +130 -0
  31. package/dist/api/mutations/matching.js +204 -0
  32. package/dist/api/mutations/notifications.d.ts +63 -0
  33. package/dist/api/mutations/notifications.js +106 -0
  34. package/dist/api/mutations/offers.d.ts +26 -0
  35. package/dist/api/mutations/offers.js +47 -0
  36. package/dist/api/mutations/subscriptions.d.ts +127 -0
  37. package/dist/api/mutations/subscriptions.js +140 -0
  38. package/dist/api/mutations/support.d.ts +165 -0
  39. package/dist/api/mutations/support.js +307 -0
  40. package/dist/api/mutations/users.d.ts +211 -0
  41. package/dist/api/mutations/users.js +261 -0
  42. package/dist/api/queries/admin.d.ts +257 -0
  43. package/dist/api/queries/admin.js +320 -0
  44. package/dist/api/queries/ambassadors.d.ts +53 -0
  45. package/dist/api/queries/ambassadors.js +98 -0
  46. package/dist/api/queries/auth.d.ts +16 -0
  47. package/dist/api/queries/auth.js +25 -0
  48. package/dist/api/queries/bookings.d.ts +91 -0
  49. package/dist/api/queries/bookings.js +102 -0
  50. package/dist/api/queries/businesses.d.ts +212 -0
  51. package/dist/api/queries/businesses.js +154 -0
  52. package/dist/api/queries/event-chat.d.ts +19 -0
  53. package/dist/api/queries/event-chat.js +75 -0
  54. package/dist/api/queries/events.d.ts +322 -0
  55. package/dist/api/queries/events.js +221 -0
  56. package/dist/api/queries/grow90.d.ts +26 -0
  57. package/dist/api/queries/grow90.js +85 -0
  58. package/dist/api/queries/hubs.d.ts +165 -0
  59. package/dist/api/queries/hubs.js +143 -0
  60. package/dist/api/queries/index.d.ts +23 -0
  61. package/dist/api/queries/index.js +40 -0
  62. package/dist/api/queries/jack.d.ts +63 -0
  63. package/dist/api/queries/jack.js +92 -0
  64. package/dist/api/queries/library.d.ts +132 -0
  65. package/dist/api/queries/library.js +120 -0
  66. package/dist/api/queries/map.d.ts +216 -0
  67. package/dist/api/queries/map.js +278 -0
  68. package/dist/api/queries/matching.d.ts +136 -0
  69. package/dist/api/queries/matching.js +161 -0
  70. package/dist/api/queries/notifications.d.ts +78 -0
  71. package/dist/api/queries/notifications.js +88 -0
  72. package/dist/api/queries/offers.d.ts +91 -0
  73. package/dist/api/queries/offers.js +103 -0
  74. package/dist/api/queries/subscriptions.d.ts +56 -0
  75. package/dist/api/queries/subscriptions.js +73 -0
  76. package/dist/api/queries/support.d.ts +106 -0
  77. package/dist/api/queries/support.js +202 -0
  78. package/dist/api/queries/users.d.ts +293 -0
  79. package/dist/api/queries/users.js +370 -0
  80. package/dist/api/types.d.ts +464 -0
  81. package/dist/api/types.js +9 -0
  82. package/dist/hooks/useAuth.d.ts +5 -0
  83. package/dist/hooks/useAuth.js +39 -0
  84. package/dist/hooks/useUser.d.ts +43 -0
  85. package/dist/hooks/useUser.js +44 -0
  86. package/dist/index.d.ts +36 -0
  87. package/dist/index.js +67 -0
  88. package/package.json +62 -0
  89. package/src/__tests__/e2e.test.ts +502 -0
  90. package/src/api/client.ts +71 -0
  91. package/src/api/mutations/admin.ts +531 -0
  92. package/src/api/mutations/ambassadors.ts +185 -0
  93. package/src/api/mutations/auth.ts +350 -0
  94. package/src/api/mutations/bookings.ts +190 -0
  95. package/src/api/mutations/event-chat.ts +177 -0
  96. package/src/api/mutations/events.ts +273 -0
  97. package/src/api/mutations/grow90.ts +169 -0
  98. package/src/api/mutations/hubs.ts +385 -0
  99. package/src/api/mutations/index.ts +23 -0
  100. package/src/api/mutations/jack.ts +130 -0
  101. package/src/api/mutations/library.ts +212 -0
  102. package/src/api/mutations/map.ts +230 -0
  103. package/src/api/mutations/matching.ts +271 -0
  104. package/src/api/mutations/notifications.ts +114 -0
  105. package/src/api/mutations/offers.ts +73 -0
  106. package/src/api/mutations/subscriptions.ts +162 -0
  107. package/src/api/mutations/support.ts +390 -0
  108. package/src/api/mutations/users.ts +271 -0
  109. package/src/api/queries/admin.ts +480 -0
  110. package/src/api/queries/ambassadors.ts +139 -0
  111. package/src/api/queries/auth.ts +24 -0
  112. package/src/api/queries/bookings.ts +135 -0
  113. package/src/api/queries/businesses.ts +203 -0
  114. package/src/api/queries/event-chat.ts +78 -0
  115. package/src/api/queries/events.ts +272 -0
  116. package/src/api/queries/grow90.ts +98 -0
  117. package/src/api/queries/hubs.ts +211 -0
  118. package/src/api/queries/index.ts +24 -0
  119. package/src/api/queries/jack.ts +127 -0
  120. package/src/api/queries/library.ts +166 -0
  121. package/src/api/queries/map.ts +331 -0
  122. package/src/api/queries/matching.ts +238 -0
  123. package/src/api/queries/notifications.ts +103 -0
  124. package/src/api/queries/offers.ts +136 -0
  125. package/src/api/queries/subscriptions.ts +91 -0
  126. package/src/api/queries/support.ts +235 -0
  127. package/src/api/queries/users.ts +393 -0
  128. package/src/api/types.ts +596 -0
  129. package/src/index.ts +57 -0
@@ -0,0 +1,136 @@
1
+ import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type { OfferResponse } from '../types';
4
+
5
+ // ============================================================================
6
+ // QUERY KEY FACTORY
7
+ // ============================================================================
8
+
9
+ export const offerKeys = {
10
+ all: ['offers'] as const,
11
+ lists: () => [...offerKeys.all, 'list'] as const,
12
+ list: (filters?: OfferFilters) => [...offerKeys.lists(), filters] as const,
13
+ details: () => [...offerKeys.all, 'detail'] as const,
14
+ detail: (id: string) => [...offerKeys.details(), id] as const,
15
+ canRedeem: (id: string) => [...offerKeys.detail(id), 'can-redeem'] as const,
16
+ };
17
+
18
+ // ============================================================================
19
+ // TYPES
20
+ // ============================================================================
21
+
22
+ export interface OfferFilters {
23
+ page?: number;
24
+ limit?: number;
25
+ businessId?: string;
26
+ isActive?: boolean;
27
+ }
28
+
29
+ export interface PaginatedOffersResponse {
30
+ offers: OfferResponse[];
31
+ total: number;
32
+ page: number;
33
+ limit: number;
34
+ totalPages: number;
35
+ }
36
+
37
+ export interface CanRedeemOfferResponse {
38
+ canRedeem: boolean;
39
+ reason?: string;
40
+ }
41
+
42
+ // ============================================================================
43
+ // QUERY HOOKS
44
+ // ============================================================================
45
+
46
+ /**
47
+ * Get paginated list of offers with optional filters
48
+ *
49
+ * @param filters - Query parameters for filtering and pagination
50
+ * @param options - TanStack Query options
51
+ *
52
+ * @example
53
+ * ```tsx
54
+ * const { data, isLoading } = useOffers({
55
+ * page: 1,
56
+ * limit: 20,
57
+ * businessId: 'business-123',
58
+ * isActive: true
59
+ * });
60
+ * ```
61
+ */
62
+ export function useOffers(
63
+ filters?: OfferFilters,
64
+ options?: Omit<UseQueryOptions<PaginatedOffersResponse>, 'queryKey' | 'queryFn'>
65
+ ) {
66
+ return useQuery({
67
+ queryKey: offerKeys.list(filters),
68
+ queryFn: async (): Promise<PaginatedOffersResponse> => {
69
+ const client = getApiClient();
70
+ const response = await client.get('/api/v1/offers', {
71
+ params: filters,
72
+ });
73
+ return response.data;
74
+ },
75
+ ...options,
76
+ });
77
+ }
78
+
79
+ /**
80
+ * Get a single offer by ID
81
+ *
82
+ * @param id - Offer ID
83
+ * @param options - TanStack Query options
84
+ *
85
+ * @example
86
+ * ```tsx
87
+ * const { data, isLoading } = useOffer('offer-123');
88
+ * ```
89
+ */
90
+ export function useOffer(
91
+ id: string,
92
+ options?: Omit<UseQueryOptions<OfferResponse>, 'queryKey' | 'queryFn'>
93
+ ) {
94
+ return useQuery({
95
+ queryKey: offerKeys.detail(id),
96
+ queryFn: async (): Promise<OfferResponse> => {
97
+ const client = getApiClient();
98
+ const response = await client.get(`/api/v1/offers/${id}`);
99
+ return response.data;
100
+ },
101
+ enabled: !!id,
102
+ ...options,
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Check if a user can redeem a specific offer
108
+ *
109
+ * @param id - Offer ID
110
+ * @param options - TanStack Query options
111
+ *
112
+ * @example
113
+ * ```tsx
114
+ * const { data, isLoading } = useCanRedeemOffer('offer-123');
115
+ * if (data?.canRedeem) {
116
+ * // User can redeem the offer
117
+ * } else {
118
+ * console.log('Cannot redeem:', data?.reason);
119
+ * }
120
+ * ```
121
+ */
122
+ export function useCanRedeemOffer(
123
+ id: string,
124
+ options?: Omit<UseQueryOptions<CanRedeemOfferResponse>, 'queryKey' | 'queryFn'>
125
+ ) {
126
+ return useQuery({
127
+ queryKey: offerKeys.canRedeem(id),
128
+ queryFn: async (): Promise<CanRedeemOfferResponse> => {
129
+ const client = getApiClient();
130
+ const response = await client.get(`/api/v1/offers/${id}/can-redeem`);
131
+ return response.data;
132
+ },
133
+ enabled: !!id,
134
+ ...options,
135
+ });
136
+ }
@@ -0,0 +1,91 @@
1
+ import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type { SubscriptionResponse } from '../types';
4
+
5
+ // ============================================================================
6
+ // QUERY KEY FACTORY
7
+ // ============================================================================
8
+
9
+ export const subscriptionKeys = {
10
+ all: ['subscriptions'] as const,
11
+ plans: () => [...subscriptionKeys.all, 'plans'] as const,
12
+ mine: () => [...subscriptionKeys.all, 'me'] as const,
13
+ };
14
+
15
+ // ============================================================================
16
+ // TYPES
17
+ // ============================================================================
18
+
19
+ export interface SubscriptionPlan {
20
+ id: string;
21
+ name: string;
22
+ tier: 'FREE' | 'PREMIUM';
23
+ price: number;
24
+ currency: string;
25
+ interval: 'month' | 'year';
26
+ features: string[];
27
+ stripePriceId?: string;
28
+ }
29
+
30
+ // ============================================================================
31
+ // QUERY HOOKS
32
+ // ============================================================================
33
+
34
+ /**
35
+ * Get available subscription plans
36
+ *
37
+ * @param options - TanStack Query options
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * const { data: plans, isLoading } = useSubscriptionPlans();
42
+ * ```
43
+ */
44
+ export function useSubscriptionPlans(
45
+ options?: Omit<UseQueryOptions<SubscriptionPlan[]>, 'queryKey' | 'queryFn'>
46
+ ) {
47
+ return useQuery({
48
+ queryKey: subscriptionKeys.plans(),
49
+ queryFn: async (): Promise<SubscriptionPlan[]> => {
50
+ const client = getApiClient();
51
+ const response = await client.get('/api/v1/subscriptions/plans');
52
+ return response.data;
53
+ },
54
+ ...options,
55
+ });
56
+ }
57
+
58
+ /**
59
+ * Get current user's subscription
60
+ *
61
+ * @param options - TanStack Query options
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * const { data: subscription, isLoading } = useMySubscription();
66
+ * ```
67
+ */
68
+ export function useMySubscription(
69
+ options?: Omit<UseQueryOptions<SubscriptionResponse | null>, 'queryKey' | 'queryFn'>
70
+ ) {
71
+ return useQuery({
72
+ queryKey: subscriptionKeys.mine(),
73
+ queryFn: async (): Promise<SubscriptionResponse | null> => {
74
+ const client = getApiClient();
75
+ try {
76
+ const response = await client.get('/api/v1/subscriptions/me');
77
+ return response.data;
78
+ } catch (error: unknown) {
79
+ // 404 means no subscription - return null instead of throwing
80
+ if (error && typeof error === 'object' && 'response' in error) {
81
+ const axiosError = error as { response?: { status?: number } };
82
+ if (axiosError.response?.status === 404) {
83
+ return null;
84
+ }
85
+ }
86
+ throw error;
87
+ }
88
+ },
89
+ ...options,
90
+ });
91
+ }
@@ -0,0 +1,235 @@
1
+ import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type {
4
+ DailyCheckInResponse,
5
+ MoodLogResponse,
6
+ WinResponse,
7
+ HabitResponse,
8
+ ReflectionResponse,
9
+ UserStreakResponse,
10
+ } from '../types';
11
+
12
+ // ============================================================================
13
+ // QUERY KEY FACTORY
14
+ // ============================================================================
15
+
16
+ export const supportKeys = {
17
+ all: ['support'] as const,
18
+ checkIns: () => [...supportKeys.all, 'check-ins'] as const,
19
+ checkInToday: () => [...supportKeys.checkIns(), 'today'] as const,
20
+ checkInStreak: () => [...supportKeys.checkIns(), 'streak'] as const,
21
+ moodLogs: () => [...supportKeys.all, 'mood'] as const,
22
+ wins: () => [...supportKeys.all, 'wins'] as const,
23
+ winsByCategory: () => [...supportKeys.wins(), 'by-category'] as const,
24
+ habits: () => [...supportKeys.all, 'habits'] as const,
25
+ reflections: () => [...supportKeys.all, 'reflections'] as const,
26
+ };
27
+
28
+ // ============================================================================
29
+ // TYPES
30
+ // ============================================================================
31
+
32
+ export interface WinsByCategory {
33
+ category: string;
34
+ wins: WinResponse[];
35
+ count: number;
36
+ }
37
+
38
+ // ============================================================================
39
+ // QUERY HOOKS
40
+ // ============================================================================
41
+
42
+ /**
43
+ * Get user's daily check-ins
44
+ *
45
+ * @param options - TanStack Query options
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * const { data, isLoading } = useCheckIns();
50
+ * ```
51
+ */
52
+ export function useCheckIns(
53
+ options?: Omit<UseQueryOptions<DailyCheckInResponse[]>, 'queryKey' | 'queryFn'>
54
+ ) {
55
+ return useQuery({
56
+ queryKey: supportKeys.checkIns(),
57
+ queryFn: async (): Promise<DailyCheckInResponse[]> => {
58
+ const client = getApiClient();
59
+ const response = await client.get('/api/v1/support/check-ins');
60
+ // API wraps responses in { data: [...], meta: {...} }
61
+ return response.data?.data || response.data || [];
62
+ },
63
+ ...options,
64
+ });
65
+ }
66
+
67
+ /**
68
+ * Get today's check-in
69
+ *
70
+ * @param options - TanStack Query options
71
+ *
72
+ * @example
73
+ * ```tsx
74
+ * const { data, isLoading } = useTodayCheckIn();
75
+ * ```
76
+ */
77
+ export function useTodayCheckIn(
78
+ options?: Omit<UseQueryOptions<DailyCheckInResponse | null>, 'queryKey' | 'queryFn'>
79
+ ) {
80
+ return useQuery({
81
+ queryKey: supportKeys.checkInToday(),
82
+ queryFn: async (): Promise<DailyCheckInResponse | null> => {
83
+ const client = getApiClient();
84
+ const response = await client.get('/api/v1/support/check-ins/today');
85
+ // API wraps responses in { data: {...}, meta: {...} }
86
+ return response.data?.data ?? response.data ?? null;
87
+ },
88
+ ...options,
89
+ });
90
+ }
91
+
92
+ /**
93
+ * Get user's check-in streak
94
+ *
95
+ * @param options - TanStack Query options
96
+ *
97
+ * @example
98
+ * ```tsx
99
+ * const { data, isLoading } = useCheckInStreak();
100
+ * ```
101
+ */
102
+ export function useCheckInStreak(
103
+ options?: Omit<UseQueryOptions<UserStreakResponse>, 'queryKey' | 'queryFn'>
104
+ ) {
105
+ return useQuery({
106
+ queryKey: supportKeys.checkInStreak(),
107
+ queryFn: async (): Promise<UserStreakResponse> => {
108
+ const client = getApiClient();
109
+ const response = await client.get('/api/v1/support/check-ins/streak');
110
+ // API wraps responses in { data: {...}, meta: {...} }
111
+ return response.data?.data || response.data || { currentStreak: 0, longestStreak: 0, totalCheckIns: 0 };
112
+ },
113
+ ...options,
114
+ });
115
+ }
116
+
117
+ /**
118
+ * Get user's mood logs
119
+ *
120
+ * @param options - TanStack Query options
121
+ *
122
+ * @example
123
+ * ```tsx
124
+ * const { data, isLoading } = useMoodLogs();
125
+ * ```
126
+ */
127
+ export function useMoodLogs(
128
+ options?: Omit<UseQueryOptions<MoodLogResponse[]>, 'queryKey' | 'queryFn'>
129
+ ) {
130
+ return useQuery({
131
+ queryKey: supportKeys.moodLogs(),
132
+ queryFn: async (): Promise<MoodLogResponse[]> => {
133
+ const client = getApiClient();
134
+ const response = await client.get('/api/v1/support/mood');
135
+ return response.data;
136
+ },
137
+ ...options,
138
+ });
139
+ }
140
+
141
+ /**
142
+ * Get user's wins
143
+ *
144
+ * @param options - TanStack Query options
145
+ *
146
+ * @example
147
+ * ```tsx
148
+ * const { data, isLoading } = useWins();
149
+ * ```
150
+ */
151
+ export function useWins(
152
+ options?: Omit<UseQueryOptions<WinResponse[]>, 'queryKey' | 'queryFn'>
153
+ ) {
154
+ return useQuery({
155
+ queryKey: supportKeys.wins(),
156
+ queryFn: async (): Promise<WinResponse[]> => {
157
+ const client = getApiClient();
158
+ const response = await client.get('/api/v1/support/wins');
159
+ return response.data;
160
+ },
161
+ ...options,
162
+ });
163
+ }
164
+
165
+ /**
166
+ * Get user's wins grouped by category
167
+ *
168
+ * @param options - TanStack Query options
169
+ *
170
+ * @example
171
+ * ```tsx
172
+ * const { data, isLoading } = useWinsByCategory();
173
+ * ```
174
+ */
175
+ export function useWinsByCategory(
176
+ options?: Omit<UseQueryOptions<WinsByCategory[]>, 'queryKey' | 'queryFn'>
177
+ ) {
178
+ return useQuery({
179
+ queryKey: supportKeys.winsByCategory(),
180
+ queryFn: async (): Promise<WinsByCategory[]> => {
181
+ const client = getApiClient();
182
+ const response = await client.get('/api/v1/support/wins/by-category');
183
+ return response.data;
184
+ },
185
+ ...options,
186
+ });
187
+ }
188
+
189
+ /**
190
+ * Get user's habits
191
+ *
192
+ * @param options - TanStack Query options
193
+ *
194
+ * @example
195
+ * ```tsx
196
+ * const { data, isLoading } = useHabits();
197
+ * ```
198
+ */
199
+ export function useHabits(
200
+ options?: Omit<UseQueryOptions<HabitResponse[]>, 'queryKey' | 'queryFn'>
201
+ ) {
202
+ return useQuery({
203
+ queryKey: supportKeys.habits(),
204
+ queryFn: async (): Promise<HabitResponse[]> => {
205
+ const client = getApiClient();
206
+ const response = await client.get('/api/v1/support/habits');
207
+ return response.data;
208
+ },
209
+ ...options,
210
+ });
211
+ }
212
+
213
+ /**
214
+ * Get user's reflections
215
+ *
216
+ * @param options - TanStack Query options
217
+ *
218
+ * @example
219
+ * ```tsx
220
+ * const { data, isLoading } = useReflections();
221
+ * ```
222
+ */
223
+ export function useReflections(
224
+ options?: Omit<UseQueryOptions<ReflectionResponse[]>, 'queryKey' | 'queryFn'>
225
+ ) {
226
+ return useQuery({
227
+ queryKey: supportKeys.reflections(),
228
+ queryFn: async (): Promise<ReflectionResponse[]> => {
229
+ const client = getApiClient();
230
+ const response = await client.get('/api/v1/support/reflections');
231
+ return response.data;
232
+ },
233
+ ...options,
234
+ });
235
+ }