@spotsdev/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 (79) hide show
  1. package/dist/api/client.d.ts +12 -0
  2. package/dist/api/client.js +68 -0
  3. package/dist/api/mutations/clubs.d.ts +47 -0
  4. package/dist/api/mutations/clubs.js +95 -0
  5. package/dist/api/mutations/conversations.d.ts +45 -0
  6. package/dist/api/mutations/conversations.js +110 -0
  7. package/dist/api/mutations/index.d.ts +13 -0
  8. package/dist/api/mutations/index.js +38 -0
  9. package/dist/api/mutations/notifications.d.ts +38 -0
  10. package/dist/api/mutations/notifications.js +64 -0
  11. package/dist/api/mutations/orders.d.ts +73 -0
  12. package/dist/api/mutations/orders.js +116 -0
  13. package/dist/api/mutations/posts.d.ts +123 -0
  14. package/dist/api/mutations/posts.js +229 -0
  15. package/dist/api/mutations/products.d.ts +81 -0
  16. package/dist/api/mutations/products.js +102 -0
  17. package/dist/api/mutations/spots.d.ts +59 -0
  18. package/dist/api/mutations/spots.js +129 -0
  19. package/dist/api/mutations/users.d.ts +71 -0
  20. package/dist/api/mutations/users.js +173 -0
  21. package/dist/api/queries/auth.d.ts +37 -0
  22. package/dist/api/queries/auth.js +61 -0
  23. package/dist/api/queries/clubs.d.ts +52 -0
  24. package/dist/api/queries/clubs.js +116 -0
  25. package/dist/api/queries/conversations.d.ts +52 -0
  26. package/dist/api/queries/conversations.js +83 -0
  27. package/dist/api/queries/index.d.ts +26 -0
  28. package/dist/api/queries/index.js +65 -0
  29. package/dist/api/queries/misc.d.ts +54 -0
  30. package/dist/api/queries/misc.js +129 -0
  31. package/dist/api/queries/notifications.d.ts +34 -0
  32. package/dist/api/queries/notifications.js +62 -0
  33. package/dist/api/queries/orders.d.ts +45 -0
  34. package/dist/api/queries/orders.js +93 -0
  35. package/dist/api/queries/posts.d.ts +55 -0
  36. package/dist/api/queries/posts.js +130 -0
  37. package/dist/api/queries/products.d.ts +52 -0
  38. package/dist/api/queries/products.js +89 -0
  39. package/dist/api/queries/spots.d.ts +78 -0
  40. package/dist/api/queries/spots.js +168 -0
  41. package/dist/api/queries/templates.d.ts +42 -0
  42. package/dist/api/queries/templates.js +86 -0
  43. package/dist/api/queries/users.d.ts +90 -0
  44. package/dist/api/queries/users.js +187 -0
  45. package/dist/api/services/index.d.ts +2 -0
  46. package/dist/api/services/index.js +8 -0
  47. package/dist/api/services/marketplace.d.ts +129 -0
  48. package/dist/api/services/marketplace.js +168 -0
  49. package/dist/api/types.d.ts +54 -0
  50. package/dist/api/types.js +34 -0
  51. package/dist/index.d.ts +38 -0
  52. package/dist/index.js +73 -0
  53. package/package.json +57 -0
  54. package/src/api/client.ts +78 -0
  55. package/src/api/mutations/clubs.ts +107 -0
  56. package/src/api/mutations/conversations.ts +124 -0
  57. package/src/api/mutations/index.ts +29 -0
  58. package/src/api/mutations/notifications.ts +70 -0
  59. package/src/api/mutations/orders.ts +174 -0
  60. package/src/api/mutations/posts.ts +278 -0
  61. package/src/api/mutations/products.ts +160 -0
  62. package/src/api/mutations/spots.ts +146 -0
  63. package/src/api/mutations/users.ts +197 -0
  64. package/src/api/queries/auth.ts +67 -0
  65. package/src/api/queries/clubs.ts +135 -0
  66. package/src/api/queries/conversations.ts +94 -0
  67. package/src/api/queries/index.ts +48 -0
  68. package/src/api/queries/misc.ts +140 -0
  69. package/src/api/queries/notifications.ts +66 -0
  70. package/src/api/queries/orders.ts +119 -0
  71. package/src/api/queries/posts.ts +142 -0
  72. package/src/api/queries/products.ts +123 -0
  73. package/src/api/queries/spots.ts +201 -0
  74. package/src/api/queries/templates.ts +95 -0
  75. package/src/api/queries/users.ts +206 -0
  76. package/src/api/services/index.ts +6 -0
  77. package/src/api/services/marketplace.ts +265 -0
  78. package/src/api/types.ts +144 -0
  79. package/src/index.ts +63 -0
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Spots Query Hooks
3
+ *
4
+ * TanStack Query hooks for spot-related operations.
5
+ */
6
+
7
+ import { useQuery, useInfiniteQuery, UseQueryOptions, UseQueryResult, UseInfiniteQueryOptions, UseInfiniteQueryResult } from '@tanstack/react-query';
8
+ import { getApiClient } from '../client';
9
+ import type { Spot, SpotImage, ApiResponse, PaginatedResponse } from '../types';
10
+
11
+ // ============================================================================
12
+ // QUERY KEYS
13
+ // ============================================================================
14
+
15
+ export const spotKeys = {
16
+ all: ['spots'] as const,
17
+ lists: () => [...spotKeys.all, 'list'] as const,
18
+ list: (filters?: Record<string, unknown>) => [...spotKeys.lists(), filters] as const,
19
+ details: () => [...spotKeys.all, 'detail'] as const,
20
+ detail: (id: string) => [...spotKeys.details(), id] as const,
21
+ bySlug: (slug: string) => [...spotKeys.all, 'slug', slug] as const,
22
+ byQR: (qrCode: string) => [...spotKeys.all, 'qr', qrCode] as const,
23
+ images: (spotId: string) => [...spotKeys.detail(spotId), 'images'] as const,
24
+ };
25
+
26
+ // ============================================================================
27
+ // QUERY HOOKS
28
+ // ============================================================================
29
+
30
+ /**
31
+ * Get all spots (paginated)
32
+ *
33
+ * @endpoint GET /api/v1/spots
34
+ * @returns PaginatedResponse with spots array and meta
35
+ */
36
+ export function useSpots(
37
+ params?: {
38
+ limit?: number;
39
+ page?: number;
40
+ city?: string;
41
+ type?: string;
42
+ templateSlugs?: string[];
43
+ vibeIds?: string[];
44
+ search?: string;
45
+ },
46
+ options?: Omit<UseQueryOptions<PaginatedResponse<Spot>>, 'queryKey' | 'queryFn'>
47
+ ): UseQueryResult<PaginatedResponse<Spot>> {
48
+ return useQuery({
49
+ queryKey: spotKeys.list(params),
50
+ queryFn: async (): Promise<PaginatedResponse<Spot>> => {
51
+ const client = getApiClient();
52
+ const queryParams = new URLSearchParams();
53
+ if (params?.limit) queryParams.set('limit', String(params.limit));
54
+ if (params?.page) queryParams.set('page', String(params.page));
55
+ if (params?.city) queryParams.set('city', params.city);
56
+ if (params?.type) queryParams.set('type', params.type);
57
+ if (params?.search) queryParams.set('search', params.search);
58
+ if (params?.templateSlugs) {
59
+ params.templateSlugs.forEach(slug => queryParams.append('templateSlugs', slug));
60
+ }
61
+ if (params?.vibeIds) {
62
+ params.vibeIds.forEach(id => queryParams.append('vibeIds', id));
63
+ }
64
+ const response = await client.get<ApiResponse<PaginatedResponse<Spot>>>(`/api/v1/spots?${queryParams}`);
65
+ return response.data.data;
66
+ },
67
+ ...options,
68
+ });
69
+ }
70
+
71
+ /**
72
+ * Get a spot by ID
73
+ *
74
+ * @endpoint GET /api/v1/spots/{spotId}
75
+ */
76
+ export function useSpot(
77
+ spotId: string,
78
+ options?: Omit<UseQueryOptions<Spot>, 'queryKey' | 'queryFn'>
79
+ ): UseQueryResult<Spot> {
80
+ return useQuery({
81
+ queryKey: spotKeys.detail(spotId),
82
+ queryFn: async (): Promise<Spot> => {
83
+ const client = getApiClient();
84
+ const response = await client.get<ApiResponse<Spot>>(`/api/v1/spots/${spotId}`);
85
+ return response.data.data;
86
+ },
87
+ enabled: !!spotId,
88
+ ...options,
89
+ });
90
+ }
91
+
92
+ /**
93
+ * Get a spot by slug
94
+ *
95
+ * @endpoint GET /api/v1/spots/slug/{slug}
96
+ */
97
+ export function useSpotBySlug(
98
+ slug: string,
99
+ options?: Omit<UseQueryOptions<Spot>, 'queryKey' | 'queryFn'>
100
+ ): UseQueryResult<Spot> {
101
+ return useQuery({
102
+ queryKey: spotKeys.bySlug(slug),
103
+ queryFn: async (): Promise<Spot> => {
104
+ const client = getApiClient();
105
+ const response = await client.get<ApiResponse<Spot>>(`/api/v1/spots/slug/${slug}`);
106
+ return response.data.data;
107
+ },
108
+ enabled: !!slug,
109
+ ...options,
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Get a spot by QR code
115
+ *
116
+ * @endpoint GET /api/v1/spots/qr/{qrCode}
117
+ */
118
+ export function useSpotByQR(
119
+ qrCode: string,
120
+ options?: Omit<UseQueryOptions<Spot>, 'queryKey' | 'queryFn'>
121
+ ): UseQueryResult<Spot> {
122
+ return useQuery({
123
+ queryKey: spotKeys.byQR(qrCode),
124
+ queryFn: async (): Promise<Spot> => {
125
+ const client = getApiClient();
126
+ const response = await client.get<ApiResponse<Spot>>(`/api/v1/spots/qr/${qrCode}`);
127
+ return response.data.data;
128
+ },
129
+ enabled: !!qrCode,
130
+ ...options,
131
+ });
132
+ }
133
+
134
+ /**
135
+ * Get images for a spot
136
+ *
137
+ * @endpoint GET /api/v1/spots/{spotId}/images
138
+ */
139
+ export function useSpotImages(
140
+ spotId: string,
141
+ options?: Omit<UseQueryOptions<SpotImage[]>, 'queryKey' | 'queryFn'>
142
+ ): UseQueryResult<SpotImage[]> {
143
+ return useQuery({
144
+ queryKey: spotKeys.images(spotId),
145
+ queryFn: async (): Promise<SpotImage[]> => {
146
+ const client = getApiClient();
147
+ const response = await client.get<ApiResponse<SpotImage[]>>(`/api/v1/spots/${spotId}/images`);
148
+ return response.data.data;
149
+ },
150
+ enabled: !!spotId,
151
+ ...options,
152
+ });
153
+ }
154
+
155
+ /**
156
+ * Infinite scroll query for spots
157
+ *
158
+ * @endpoint GET /api/v1/spots (paginated)
159
+ * @returns Infinite query with pages of spots
160
+ */
161
+ export interface InfiniteSpotsParams {
162
+ limit?: number;
163
+ city?: string;
164
+ cityId?: string;
165
+ type?: string;
166
+ templateSlugs?: string[];
167
+ vibeIds?: string[];
168
+ search?: string;
169
+ }
170
+
171
+ export function useInfiniteSpots(
172
+ params?: InfiniteSpotsParams,
173
+ options?: Omit<UseInfiniteQueryOptions<PaginatedResponse<Spot>, Error, { pages: PaginatedResponse<Spot>[]; pageParams: number[] }>, 'queryKey' | 'queryFn' | 'getNextPageParam' | 'initialPageParam'>
174
+ ): UseInfiniteQueryResult<{ pages: PaginatedResponse<Spot>[]; pageParams: number[] }, Error> {
175
+ return useInfiniteQuery({
176
+ queryKey: [...spotKeys.lists(), 'infinite', params] as const,
177
+ queryFn: async ({ pageParam }): Promise<PaginatedResponse<Spot>> => {
178
+ const client = getApiClient();
179
+ const queryParams = new URLSearchParams();
180
+ queryParams.set('page', String(pageParam));
181
+ if (params?.limit) queryParams.set('limit', String(params.limit));
182
+ if (params?.city) queryParams.set('city', params.city);
183
+ if (params?.cityId) queryParams.set('cityId', params.cityId);
184
+ if (params?.type && params.type !== 'All') queryParams.set('type', params.type);
185
+ if (params?.search?.trim()) queryParams.set('search', params.search.trim());
186
+ if (params?.templateSlugs) {
187
+ params.templateSlugs.forEach(slug => queryParams.append('templateSlugs', slug));
188
+ }
189
+ if (params?.vibeIds) {
190
+ params.vibeIds.forEach(id => queryParams.append('vibeIds', id));
191
+ }
192
+ const response = await client.get<ApiResponse<PaginatedResponse<Spot>>>(`/api/v1/spots?${queryParams}`);
193
+ return response.data.data;
194
+ },
195
+ initialPageParam: 1,
196
+ getNextPageParam: (lastPage) => {
197
+ return lastPage.meta.hasNextPage ? lastPage.meta.page + 1 : undefined;
198
+ },
199
+ ...options,
200
+ });
201
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Templates Query Hooks
3
+ *
4
+ * TanStack Query hooks for post template operations.
5
+ *
6
+ * Templates are reference data (flat array), not paginated.
7
+ */
8
+
9
+ import { useQuery, UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
10
+ import { getApiClient } from '../client';
11
+ import type { Template, ApiResponse } from '../types';
12
+
13
+ // ============================================================================
14
+ // QUERY KEYS
15
+ // ============================================================================
16
+
17
+ export const templateKeys = {
18
+ all: ['templates'] as const,
19
+ lists: () => [...templateKeys.all, 'list'] as const,
20
+ list: (filters?: { spotType?: string }) => [...templateKeys.lists(), filters] as const,
21
+ details: () => [...templateKeys.all, 'detail'] as const,
22
+ detail: (id: string) => [...templateKeys.details(), id] as const,
23
+ bySlug: (slug: string) => [...templateKeys.all, 'slug', slug] as const,
24
+ };
25
+
26
+ // ============================================================================
27
+ // QUERY HOOKS
28
+ // ============================================================================
29
+
30
+ /**
31
+ * Get all templates (flat array - reference data)
32
+ *
33
+ * @endpoint GET /api/v1/templates
34
+ * @returns Flat array of templates (not paginated)
35
+ */
36
+ export function useTemplates(
37
+ params?: { spotType?: string },
38
+ options?: Omit<UseQueryOptions<Template[]>, 'queryKey' | 'queryFn'>
39
+ ): UseQueryResult<Template[]> {
40
+ return useQuery({
41
+ queryKey: templateKeys.list(params),
42
+ queryFn: async (): Promise<Template[]> => {
43
+ const client = getApiClient();
44
+ const queryParams = new URLSearchParams();
45
+ if (params?.spotType) queryParams.set('spotType', params.spotType);
46
+ const response = await client.get<ApiResponse<Template[]>>(`/api/v1/templates?${queryParams}`);
47
+ // Templates endpoint returns flat array: { data: [] }
48
+ return response.data.data;
49
+ },
50
+ staleTime: 1000 * 60 * 60, // Cache for 1 hour (reference data)
51
+ ...options,
52
+ });
53
+ }
54
+
55
+ /**
56
+ * Get a template by ID
57
+ *
58
+ * @endpoint GET /api/v1/templates/{templateId}
59
+ */
60
+ export function useTemplate(
61
+ templateId: string,
62
+ options?: Omit<UseQueryOptions<Template>, 'queryKey' | 'queryFn'>
63
+ ): UseQueryResult<Template> {
64
+ return useQuery({
65
+ queryKey: templateKeys.detail(templateId),
66
+ queryFn: async (): Promise<Template> => {
67
+ const client = getApiClient();
68
+ const response = await client.get<ApiResponse<Template>>(`/api/v1/templates/${templateId}`);
69
+ return response.data.data;
70
+ },
71
+ enabled: !!templateId,
72
+ ...options,
73
+ });
74
+ }
75
+
76
+ /**
77
+ * Get a template by slug
78
+ *
79
+ * @endpoint GET /api/v1/templates/slug/{slug}
80
+ */
81
+ export function useTemplateBySlug(
82
+ slug: string,
83
+ options?: Omit<UseQueryOptions<Template>, 'queryKey' | 'queryFn'>
84
+ ): UseQueryResult<Template> {
85
+ return useQuery({
86
+ queryKey: templateKeys.bySlug(slug),
87
+ queryFn: async (): Promise<Template> => {
88
+ const client = getApiClient();
89
+ const response = await client.get<ApiResponse<Template>>(`/api/v1/templates/slug/${slug}`);
90
+ return response.data.data;
91
+ },
92
+ enabled: !!slug,
93
+ ...options,
94
+ });
95
+ }
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Users Query Hooks
3
+ *
4
+ * TanStack Query hooks for user-related operations.
5
+ */
6
+
7
+ import { useQuery, UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
8
+ import { getApiClient } from '../client';
9
+ import type { User, Post, Club, Spot, SpotSubscription, FavoriteSpot, ApiResponse } from '../types';
10
+
11
+ // ============================================================================
12
+ // QUERY KEYS
13
+ // ============================================================================
14
+
15
+ export const userKeys = {
16
+ all: ['users'] as const,
17
+ me: () => [...userKeys.all, 'me'] as const,
18
+ stats: () => [...userKeys.me(), 'stats'] as const,
19
+ activity: (limit?: number) => [...userKeys.me(), 'activity', limit] as const,
20
+ posts: (params?: { page?: number; limit?: number }) => [...userKeys.me(), 'posts', params] as const,
21
+ clubs: () => [...userKeys.me(), 'clubs'] as const,
22
+ subscriptions: () => [...userKeys.me(), 'subscriptions'] as const,
23
+ blocked: () => [...userKeys.me(), 'blocked'] as const,
24
+ ownedSpots: () => [...userKeys.me(), 'owned-spots'] as const,
25
+ favorites: () => [...userKeys.me(), 'favorites'] as const,
26
+ };
27
+
28
+ // ============================================================================
29
+ // QUERY HOOKS
30
+ // ============================================================================
31
+
32
+ /**
33
+ * Get current user's profile
34
+ *
35
+ * @endpoint GET /api/v1/users/me
36
+ */
37
+ export function useCurrentUser(
38
+ options?: Omit<UseQueryOptions<User>, 'queryKey' | 'queryFn'>
39
+ ): UseQueryResult<User> {
40
+ return useQuery({
41
+ queryKey: userKeys.me(),
42
+ queryFn: async (): Promise<User> => {
43
+ const client = getApiClient();
44
+ const response = await client.get<ApiResponse<User>>('/api/v1/users/me');
45
+ return response.data.data;
46
+ },
47
+ ...options,
48
+ });
49
+ }
50
+
51
+ /**
52
+ * Get current user's stats
53
+ *
54
+ * @endpoint GET /api/v1/users/me/stats
55
+ */
56
+ export function useUserStats(
57
+ options?: Omit<UseQueryOptions<{ posts: number; responses: number; upvotes: number }>, 'queryKey' | 'queryFn'>
58
+ ): UseQueryResult<{ posts: number; responses: number; upvotes: number }> {
59
+ return useQuery({
60
+ queryKey: userKeys.stats(),
61
+ queryFn: async () => {
62
+ const client = getApiClient();
63
+ const response = await client.get<ApiResponse<{ posts: number; responses: number; upvotes: number }>>('/api/v1/users/me/stats');
64
+ return response.data.data;
65
+ },
66
+ ...options,
67
+ });
68
+ }
69
+
70
+ /**
71
+ * Get current user's activity
72
+ *
73
+ * @endpoint GET /api/v1/users/me/activity
74
+ */
75
+ export function useUserActivity(
76
+ limit: number = 10,
77
+ options?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>
78
+ ): UseQueryResult<unknown[]> {
79
+ return useQuery({
80
+ queryKey: userKeys.activity(limit),
81
+ queryFn: async () => {
82
+ const client = getApiClient();
83
+ const response = await client.get<ApiResponse<unknown[]>>(`/api/v1/users/me/activity?limit=${limit}`);
84
+ return response.data.data;
85
+ },
86
+ ...options,
87
+ });
88
+ }
89
+
90
+ /**
91
+ * Get current user's posts
92
+ *
93
+ * @endpoint GET /api/v1/user/me/posts
94
+ */
95
+ export function useUserPosts(
96
+ params?: { page?: number; limit?: number },
97
+ options?: Omit<UseQueryOptions<Post[]>, 'queryKey' | 'queryFn'>
98
+ ): UseQueryResult<Post[]> {
99
+ return useQuery({
100
+ queryKey: userKeys.posts(params),
101
+ queryFn: async () => {
102
+ const client = getApiClient();
103
+ const queryParams = new URLSearchParams();
104
+ if (params?.page) queryParams.set('page', String(params.page));
105
+ if (params?.limit) queryParams.set('limit', String(params.limit));
106
+ const response = await client.get<ApiResponse<Post[]>>(`/api/v1/user/me/posts?${queryParams}`);
107
+ return response.data.data;
108
+ },
109
+ ...options,
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Get current user's clubs
115
+ *
116
+ * @endpoint GET /api/v1/user/me/clubs
117
+ */
118
+ export function useUserClubs(
119
+ options?: Omit<UseQueryOptions<Club[]>, 'queryKey' | 'queryFn'>
120
+ ): UseQueryResult<Club[]> {
121
+ return useQuery({
122
+ queryKey: userKeys.clubs(),
123
+ queryFn: async () => {
124
+ const client = getApiClient();
125
+ const response = await client.get<ApiResponse<Club[]>>('/api/v1/user/me/clubs');
126
+ return response.data.data;
127
+ },
128
+ ...options,
129
+ });
130
+ }
131
+
132
+ /**
133
+ * Get current user's spot subscriptions
134
+ *
135
+ * @endpoint GET /api/v1/user/me/subscriptions
136
+ */
137
+ export function useUserSubscriptions(
138
+ options?: Omit<UseQueryOptions<SpotSubscription[]>, 'queryKey' | 'queryFn'>
139
+ ): UseQueryResult<SpotSubscription[]> {
140
+ return useQuery({
141
+ queryKey: userKeys.subscriptions(),
142
+ queryFn: async () => {
143
+ const client = getApiClient();
144
+ const response = await client.get<ApiResponse<SpotSubscription[]>>('/api/v1/user/me/subscriptions');
145
+ return response.data.data;
146
+ },
147
+ ...options,
148
+ });
149
+ }
150
+
151
+ /**
152
+ * Get blocked users list
153
+ *
154
+ * @endpoint GET /api/v1/user/me/blocked
155
+ */
156
+ export function useBlockedUsers(
157
+ options?: Omit<UseQueryOptions<User[]>, 'queryKey' | 'queryFn'>
158
+ ): UseQueryResult<User[]> {
159
+ return useQuery({
160
+ queryKey: userKeys.blocked(),
161
+ queryFn: async () => {
162
+ const client = getApiClient();
163
+ const response = await client.get<ApiResponse<User[]>>('/api/v1/user/me/blocked');
164
+ return response.data.data;
165
+ },
166
+ ...options,
167
+ });
168
+ }
169
+
170
+ /**
171
+ * Get current user's owned spots (for business owners)
172
+ *
173
+ * @endpoint GET /api/v1/users/me/owned-spots
174
+ */
175
+ export function useOwnedSpots(
176
+ options?: Omit<UseQueryOptions<Spot[]>, 'queryKey' | 'queryFn'>
177
+ ): UseQueryResult<Spot[]> {
178
+ return useQuery({
179
+ queryKey: userKeys.ownedSpots(),
180
+ queryFn: async () => {
181
+ const client = getApiClient();
182
+ const response = await client.get<ApiResponse<Spot[]>>('/api/v1/users/me/owned-spots');
183
+ return response.data.data;
184
+ },
185
+ ...options,
186
+ });
187
+ }
188
+
189
+ /**
190
+ * Get current user's favorite spots
191
+ *
192
+ * @endpoint GET /api/v1/users/me/favorites
193
+ */
194
+ export function useUserFavorites(
195
+ options?: Omit<UseQueryOptions<FavoriteSpot[]>, 'queryKey' | 'queryFn'>
196
+ ): UseQueryResult<FavoriteSpot[]> {
197
+ return useQuery({
198
+ queryKey: userKeys.favorites(),
199
+ queryFn: async () => {
200
+ const client = getApiClient();
201
+ const response = await client.get<ApiResponse<FavoriteSpot[]>>('/api/v1/users/me/favorites');
202
+ return response.data.data;
203
+ },
204
+ ...options,
205
+ });
206
+ }
@@ -0,0 +1,6 @@
1
+ export { productsService, ordersService, paymentsService } from './marketplace';
2
+ export type {
3
+ CreateProductInput,
4
+ UpdateProductInput,
5
+ CreateOrderInput,
6
+ } from './marketplace';