@htlkg/data 0.0.21 → 0.0.23

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 (62) hide show
  1. package/dist/hooks/index.d.ts +702 -94
  2. package/dist/hooks/index.js +793 -56
  3. package/dist/hooks/index.js.map +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +802 -65
  6. package/dist/index.js.map +1 -1
  7. package/dist/mutations/index.js +4 -4
  8. package/dist/mutations/index.js.map +1 -1
  9. package/dist/queries/index.js +5 -5
  10. package/dist/queries/index.js.map +1 -1
  11. package/package.json +11 -12
  12. package/src/hooks/accounts/index.ts +2 -0
  13. package/src/hooks/{useAccounts.ts → accounts/useAccounts.ts} +48 -5
  14. package/src/hooks/accounts/usePaginatedAccounts.ts +166 -0
  15. package/src/hooks/brands/index.ts +2 -0
  16. package/src/hooks/{useBrands.ts → brands/useBrands.ts} +1 -1
  17. package/src/hooks/brands/usePaginatedBrands.ts +206 -0
  18. package/src/hooks/contacts/index.ts +2 -0
  19. package/src/hooks/contacts/useContacts.ts +176 -0
  20. package/src/hooks/contacts/usePaginatedContacts.ts +268 -0
  21. package/src/hooks/createPaginatedDataHook.ts +359 -0
  22. package/src/hooks/data-hook-errors.property.test.ts +4 -4
  23. package/src/hooks/data-hook-filters.property.test.ts +4 -4
  24. package/src/hooks/data-hooks.property.test.ts +4 -4
  25. package/src/hooks/index.ts +101 -8
  26. package/src/hooks/productInstances/index.ts +1 -0
  27. package/src/hooks/{useProductInstances.ts → productInstances/useProductInstances.ts} +9 -6
  28. package/src/hooks/products/index.ts +1 -0
  29. package/src/hooks/{useProducts.ts → products/useProducts.ts} +4 -5
  30. package/src/hooks/reservations/index.ts +2 -0
  31. package/src/hooks/reservations/usePaginatedReservations.ts +258 -0
  32. package/src/hooks/{useReservations.ts → reservations/useReservations.ts} +65 -10
  33. package/src/hooks/users/index.ts +2 -0
  34. package/src/hooks/users/usePaginatedUsers.ts +213 -0
  35. package/src/hooks/{useUsers.ts → users/useUsers.ts} +1 -1
  36. package/src/mutations/accounts/accounts.test.ts +287 -0
  37. package/src/mutations/{accounts.ts → accounts/accounts.ts} +2 -2
  38. package/src/mutations/accounts/index.ts +1 -0
  39. package/src/mutations/brands/brands.test.ts +292 -0
  40. package/src/mutations/{brands.ts → brands/brands.ts} +2 -2
  41. package/src/mutations/brands/index.ts +1 -0
  42. package/src/mutations/reservations/index.ts +1 -0
  43. package/src/mutations/{reservations.test.ts → reservations/reservations.test.ts} +1 -1
  44. package/src/mutations/{reservations.ts → reservations/reservations.ts} +2 -2
  45. package/src/mutations/users/index.ts +1 -0
  46. package/src/mutations/users/users.test.ts +289 -0
  47. package/src/mutations/{users.ts → users/users.ts} +2 -2
  48. package/src/queries/accounts/accounts.test.ts +228 -0
  49. package/src/queries/accounts/index.ts +1 -0
  50. package/src/queries/brands/brands.test.ts +288 -0
  51. package/src/queries/brands/index.ts +1 -0
  52. package/src/queries/products/index.ts +1 -0
  53. package/src/queries/products/products.test.ts +347 -0
  54. package/src/queries/reservations/index.ts +1 -0
  55. package/src/queries/users/index.ts +1 -0
  56. package/src/queries/users/users.test.ts +301 -0
  57. /package/src/queries/{accounts.ts → accounts/accounts.ts} +0 -0
  58. /package/src/queries/{brands.ts → brands/brands.ts} +0 -0
  59. /package/src/queries/{products.ts → products/products.ts} +0 -0
  60. /package/src/queries/{reservations.test.ts → reservations/reservations.test.ts} +0 -0
  61. /package/src/queries/{reservations.ts → reservations/reservations.ts} +0 -0
  62. /package/src/queries/{users.ts → users/users.ts} +0 -0
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Paginated Data Hook Factory
3
+ *
4
+ * Creates reusable Vue composables for fetching paginated data from GraphQL models.
5
+ * Supports cursor-based pagination (nextToken) for efficient handling of large datasets.
6
+ *
7
+ * Key features:
8
+ * - Server-side pagination with nextToken
9
+ * - loadMore() for infinite scroll/pagination
10
+ * - hasMore indicator
11
+ * - Independent pagination state per hook instance
12
+ * - Built-in support for active/deleted filtering
13
+ */
14
+
15
+ import { ref, computed, onMounted, type Ref, type ComputedRef } from "vue";
16
+ import { query, hasErrors, getErrorMessage } from "../client/proxy";
17
+
18
+ /**
19
+ * Filter for active items (not deleted)
20
+ * Uses OR condition because deletedAt can be:
21
+ * - Missing (attributeExists: false)
22
+ * - Explicitly null (eq: null)
23
+ */
24
+ export const ACTIVE_FILTER = {
25
+ or: [{ deletedAt: { attributeExists: false } }, { deletedAt: { eq: null } }],
26
+ };
27
+
28
+ /**
29
+ * Filter for deleted items
30
+ * Uses gt: "" to match only actual timestamp strings (not null or missing)
31
+ */
32
+ export const DELETED_FILTER = {
33
+ deletedAt: { gt: "" },
34
+ };
35
+
36
+ /**
37
+ * Configuration options for creating a paginated data hook
38
+ */
39
+ export interface CreatePaginatedDataHookOptions<T, TOptions extends PaginatedHookOptions = PaginatedHookOptions> {
40
+ /** The GraphQL model name (e.g., 'Account', 'User', 'Brand') */
41
+ model: string;
42
+ /** Default page size */
43
+ defaultPageSize?: number;
44
+ /** Selection set for the query (fields to fetch) */
45
+ selectionSet?: string[];
46
+ /** Transform function to apply to fetched data */
47
+ transform?: (item: any) => T;
48
+ /** Build filter from hook options */
49
+ buildFilter?: (options: TOptions) => any;
50
+ /** Plural name for the data property (e.g., 'accounts', 'users') */
51
+ dataPropertyName?: string;
52
+ /** Base filter to always apply (e.g., for active/deleted variants) */
53
+ baseFilter?: any;
54
+ }
55
+
56
+ /**
57
+ * Base options available to paginated hooks
58
+ */
59
+ export interface PaginatedHookOptions {
60
+ /** Additional filter criteria (merged with baseFilter) */
61
+ filter?: any;
62
+ /** Page size (default: 25) */
63
+ pageSize?: number;
64
+ /** Auto-fetch on mount (default: true) */
65
+ autoFetch?: boolean;
66
+ }
67
+
68
+ /**
69
+ * Pagination state
70
+ */
71
+ export interface PaginationState {
72
+ /** Current nextToken for fetching next page */
73
+ nextToken: string | null;
74
+ /** Whether there are more items to load */
75
+ hasMore: boolean;
76
+ /** Total items loaded so far */
77
+ loadedCount: number;
78
+ }
79
+
80
+ /**
81
+ * Return type for paginated data hooks
82
+ */
83
+ export interface PaginatedDataHookReturn<T> {
84
+ /** Reactive array of data (accumulated across pages) */
85
+ data: Ref<T[]>;
86
+ /** Loading state (true during any fetch) */
87
+ loading: Ref<boolean>;
88
+ /** Loading state for initial fetch */
89
+ initialLoading: Ref<boolean>;
90
+ /** Loading state for loadMore */
91
+ loadingMore: Ref<boolean>;
92
+ /** Error state */
93
+ error: Ref<Error | null>;
94
+ /** Pagination state */
95
+ pagination: Ref<PaginationState>;
96
+ /** Whether there are more items to load */
97
+ hasMore: ComputedRef<boolean>;
98
+ /** Load next page of data */
99
+ loadMore: () => Promise<void>;
100
+ /** Refetch data (resets to first page) */
101
+ refetch: () => Promise<void>;
102
+ /** Reset data and pagination state */
103
+ reset: () => void;
104
+ /** Update search filter and refetch from server (searches ALL data) */
105
+ setSearchFilter: (filter: any) => Promise<void>;
106
+ /** Current search filter */
107
+ searchFilter: Ref<any>;
108
+ }
109
+
110
+ /**
111
+ * Creates a reusable paginated data hook for a specific model
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * // Create a hook for active brands
116
+ * export const useActiveBrands = createPaginatedDataHook<Brand>({
117
+ * model: 'Brand',
118
+ * dataPropertyName: 'brands',
119
+ * baseFilter: ACTIVE_FILTER,
120
+ * selectionSet: ['id', 'name', 'status', 'accountId', 'account.name'],
121
+ * });
122
+ *
123
+ * // Usage in component
124
+ * const { brands, loading, hasMore, loadMore, refetch } = useActiveBrands({
125
+ * pageSize: 25,
126
+ * });
127
+ * ```
128
+ *
129
+ * @example With custom filter builder
130
+ * ```typescript
131
+ * interface UseBrandsOptions extends PaginatedHookOptions {
132
+ * accountId?: string;
133
+ * }
134
+ *
135
+ * export const useActiveBrands = createPaginatedDataHook<Brand, UseBrandsOptions>({
136
+ * model: 'Brand',
137
+ * dataPropertyName: 'brands',
138
+ * baseFilter: ACTIVE_FILTER,
139
+ * buildFilter: (options) => {
140
+ * if (options.accountId) {
141
+ * return { accountId: { eq: options.accountId } };
142
+ * }
143
+ * return undefined;
144
+ * },
145
+ * });
146
+ * ```
147
+ */
148
+ export function createPaginatedDataHook<T, TOptions extends PaginatedHookOptions = PaginatedHookOptions>(
149
+ config: CreatePaginatedDataHookOptions<T, TOptions>,
150
+ ) {
151
+ const {
152
+ model,
153
+ defaultPageSize = 25,
154
+ selectionSet,
155
+ transform,
156
+ buildFilter,
157
+ dataPropertyName = "data",
158
+ baseFilter,
159
+ } = config;
160
+
161
+ return function usePaginatedData(
162
+ options: TOptions = {} as TOptions,
163
+ ): PaginatedDataHookReturn<T> & Record<string, any> {
164
+ const { filter: additionalFilter, pageSize = defaultPageSize, autoFetch = true } = options;
165
+
166
+ // State
167
+ const data = ref<T[]>([]) as Ref<T[]>;
168
+ const loading = ref(false);
169
+ const initialLoading = ref(false);
170
+ const loadingMore = ref(false);
171
+ const error = ref<Error | null>(null);
172
+ const pagination = ref<PaginationState>({
173
+ nextToken: null,
174
+ hasMore: true,
175
+ loadedCount: 0,
176
+ });
177
+
178
+ // Dynamic search filter (for server-side filtering)
179
+ const searchFilter = ref<any>(null);
180
+
181
+ // Computed
182
+ const hasMore = computed(() => pagination.value.hasMore);
183
+
184
+ // Build combined filter
185
+ const getFilter = () => {
186
+ const filters: any[] = [];
187
+
188
+ // Add base filter (e.g., active/deleted)
189
+ if (baseFilter) {
190
+ filters.push(baseFilter);
191
+ }
192
+
193
+ // Add custom filter from buildFilter
194
+ if (buildFilter) {
195
+ const customFilter = buildFilter(options);
196
+ if (customFilter) {
197
+ filters.push(customFilter);
198
+ }
199
+ }
200
+
201
+ // Add additional filter from options
202
+ if (additionalFilter && Object.keys(additionalFilter).length > 0) {
203
+ filters.push(additionalFilter);
204
+ }
205
+
206
+ // Add dynamic search filter (for server-side search)
207
+ if (searchFilter.value && Object.keys(searchFilter.value).length > 0) {
208
+ filters.push(searchFilter.value);
209
+ }
210
+
211
+ // Combine filters with AND
212
+ if (filters.length === 0) {
213
+ return undefined;
214
+ }
215
+ if (filters.length === 1) {
216
+ return filters[0];
217
+ }
218
+ return { and: filters };
219
+ };
220
+
221
+ // Fetch function
222
+ async function fetchPage(nextToken?: string | null, append: boolean = false) {
223
+ if (!append) {
224
+ initialLoading.value = true;
225
+ } else {
226
+ loadingMore.value = true;
227
+ }
228
+ loading.value = true;
229
+ error.value = null;
230
+
231
+ try {
232
+ const queryOptions: Record<string, any> = {
233
+ limit: pageSize,
234
+ };
235
+
236
+ const filter = getFilter();
237
+ if (filter) {
238
+ queryOptions.filter = filter;
239
+ }
240
+
241
+ if (nextToken) {
242
+ queryOptions.nextToken = nextToken;
243
+ }
244
+
245
+ if (selectionSet) {
246
+ queryOptions.selectionSet = selectionSet;
247
+ }
248
+
249
+ const response = await query(model, "list", queryOptions);
250
+
251
+ if (hasErrors(response)) {
252
+ throw new Error(getErrorMessage(response) || `Failed to fetch ${model}`);
253
+ }
254
+
255
+ const items = response.data || [];
256
+ const transformedItems = transform ? items.map(transform) : items;
257
+
258
+ if (append) {
259
+ data.value = [...data.value, ...transformedItems];
260
+ } else {
261
+ data.value = transformedItems;
262
+ }
263
+
264
+ // Update pagination state
265
+ // Note: Amplify returns nextToken in the response
266
+ const responseNextToken = (response as any).nextToken;
267
+ pagination.value = {
268
+ nextToken: responseNextToken || null,
269
+ hasMore: !!responseNextToken,
270
+ loadedCount: data.value.length,
271
+ };
272
+ } catch (e) {
273
+ error.value = e as Error;
274
+ console.error(`[use${model}] Error fetching ${model}:`, e);
275
+ } finally {
276
+ loading.value = false;
277
+ initialLoading.value = false;
278
+ loadingMore.value = false;
279
+ }
280
+ }
281
+
282
+ // Load more function
283
+ async function loadMore() {
284
+ if (loadingMore.value || !pagination.value.hasMore) {
285
+ return;
286
+ }
287
+ await fetchPage(pagination.value.nextToken, true);
288
+ }
289
+
290
+ // Refetch (reset to first page)
291
+ async function refetch() {
292
+ pagination.value = {
293
+ nextToken: null,
294
+ hasMore: true,
295
+ loadedCount: 0,
296
+ };
297
+ await fetchPage(null, false);
298
+ }
299
+
300
+ // Reset state
301
+ function reset() {
302
+ data.value = [];
303
+ error.value = null;
304
+ searchFilter.value = null;
305
+ pagination.value = {
306
+ nextToken: null,
307
+ hasMore: true,
308
+ loadedCount: 0,
309
+ };
310
+ }
311
+
312
+ // Set search filter and refetch from server (searches ALL data)
313
+ async function setSearchFilter(filter: any) {
314
+ searchFilter.value = filter;
315
+ // Reset pagination and fetch with new filter
316
+ pagination.value = {
317
+ nextToken: null,
318
+ hasMore: true,
319
+ loadedCount: 0,
320
+ };
321
+ await fetchPage(null, false);
322
+ }
323
+
324
+ // Auto-fetch on mount if enabled
325
+ if (autoFetch) {
326
+ onMounted(() => {
327
+ fetchPage(null, false);
328
+ });
329
+ }
330
+
331
+ // Build return object
332
+ const result: PaginatedDataHookReturn<T> & Record<string, any> = {
333
+ data,
334
+ loading,
335
+ initialLoading,
336
+ loadingMore,
337
+ error,
338
+ pagination,
339
+ hasMore,
340
+ loadMore,
341
+ refetch,
342
+ reset,
343
+ setSearchFilter,
344
+ searchFilter,
345
+ };
346
+
347
+ // Add data property with custom name for backwards compatibility
348
+ if (dataPropertyName !== "data") {
349
+ result[dataPropertyName] = data;
350
+ }
351
+
352
+ return result;
353
+ };
354
+ }
355
+
356
+ /**
357
+ * Type helper to extract the return type of a created paginated hook
358
+ */
359
+ export type InferPaginatedHookReturn<THook extends (...args: any[]) => any> = ReturnType<THook>;
@@ -9,10 +9,10 @@
9
9
 
10
10
  import { describe, it, expect, vi, beforeEach } from "vitest";
11
11
  import * as fc from "fast-check";
12
- import { useBrands } from "./useBrands";
13
- import { useAccounts } from "./useAccounts";
14
- import { useUsers } from "./useUsers";
15
- import { useProducts } from "./useProducts";
12
+ import { useBrands } from "./brands/useBrands";
13
+ import { useAccounts } from "./accounts/useAccounts";
14
+ import { useUsers } from "./users/useUsers";
15
+ import { useProducts } from "./products/useProducts";
16
16
 
17
17
  // Create separate mock functions for each model
18
18
  const mockBrandList = vi.fn();
@@ -9,10 +9,10 @@
9
9
 
10
10
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
11
11
  import * as fc from "fast-check";
12
- import { useBrands } from "./useBrands";
13
- import { useAccounts } from "./useAccounts";
14
- import { useUsers } from "./useUsers";
15
- import { useProducts } from "./useProducts";
12
+ import { useBrands } from "./brands/useBrands";
13
+ import { useAccounts } from "./accounts/useAccounts";
14
+ import { useUsers } from "./users/useUsers";
15
+ import { useProducts } from "./products/useProducts";
16
16
  import type { Brand, Account, Product } from "@htlkg/core/types";
17
17
 
18
18
  // Create separate mock functions for each model
@@ -10,10 +10,10 @@
10
10
  import { describe, it, expect, vi, beforeEach } from "vitest";
11
11
  import * as fc from "fast-check";
12
12
  import { ref, isRef, isReactive, computed } from "vue";
13
- import { useBrands } from "./useBrands";
14
- import { useAccounts } from "./useAccounts";
15
- import { useUsers } from "./useUsers";
16
- import { useProducts } from "./useProducts";
13
+ import { useBrands } from "./brands/useBrands";
14
+ import { useAccounts } from "./accounts/useAccounts";
15
+ import { useUsers } from "./users/useUsers";
16
+ import { useProducts } from "./products/useProducts";
17
17
 
18
18
  // Mock the client module
19
19
  vi.mock("../client", () => ({
@@ -2,6 +2,7 @@
2
2
  * Data Hooks for @htlkg/data
3
3
  *
4
4
  * Vue composables for fetching and managing data with reactive state.
5
+ * Organized by entity type in subfolders for better maintainability.
5
6
  */
6
7
 
7
8
  // Hook factory for creating custom data hooks
@@ -14,11 +15,103 @@ export {
14
15
  type InferHookReturn,
15
16
  } from "./createDataHook";
16
17
 
17
- // Pre-built hooks for common models
18
- export { useBrands, type UseBrandsOptions, type UseBrandsReturn } from "./useBrands";
19
- export { useAccounts, type UseAccountsOptions, type UseAccountsReturn } from "./useAccounts";
20
- export { useUsers, type UseUsersOptions, type UseUsersReturn } from "./useUsers";
21
- export { useProducts, type UseProductsOptions, type UseProductsReturn } from "./useProducts";
22
- export { useProductInstances, type UseProductInstancesOptions, type UseProductInstancesReturn } from "./useProductInstances";
23
- export { useReservations, type UseReservationsOptions, type UseReservationsReturn } from "./useReservations";
24
- export { useContacts, type UseContactsOptions, type UseContactsReturn } from "./useContacts";
18
+ // Paginated hook factory for large datasets
19
+ export {
20
+ createPaginatedDataHook,
21
+ ACTIVE_FILTER,
22
+ DELETED_FILTER,
23
+ type CreatePaginatedDataHookOptions,
24
+ type PaginatedHookOptions,
25
+ type PaginationState,
26
+ type PaginatedDataHookReturn,
27
+ type InferPaginatedHookReturn,
28
+ } from "./createPaginatedDataHook";
29
+
30
+ // ============================================
31
+ // BRAND HOOKS
32
+ // ============================================
33
+ export {
34
+ useBrands,
35
+ useActiveBrands,
36
+ useDeletedBrands,
37
+ type UseBrandsOptions,
38
+ type UseBrandsReturn,
39
+ type BrandWithCounts,
40
+ type UsePaginatedBrandsOptions,
41
+ type UsePaginatedBrandsReturn,
42
+ } from "./brands";
43
+
44
+ // ============================================
45
+ // USER HOOKS
46
+ // ============================================
47
+ export {
48
+ useUsers,
49
+ useActiveUsers,
50
+ useDeletedUsers,
51
+ type UseUsersOptions,
52
+ type UseUsersReturn,
53
+ type UserWithRelations,
54
+ type UsePaginatedUsersOptions,
55
+ type UsePaginatedUsersReturn,
56
+ } from "./users";
57
+
58
+ // ============================================
59
+ // ACCOUNT HOOKS
60
+ // ============================================
61
+ export {
62
+ useAccounts,
63
+ useActiveAccounts,
64
+ useDeletedAccounts,
65
+ type UseAccountsOptions,
66
+ type UseAccountsReturn,
67
+ type AccountWithBrands,
68
+ type AccountWithBrands as PaginatedAccountWithBrands,
69
+ type UsePaginatedAccountsOptions,
70
+ type UsePaginatedAccountsReturn,
71
+ } from "./accounts";
72
+
73
+ // ============================================
74
+ // RESERVATION HOOKS
75
+ // ============================================
76
+ export {
77
+ useReservations,
78
+ useActiveReservations,
79
+ useDeletedReservations,
80
+ type UseReservationsOptions,
81
+ type UseReservationsReturn,
82
+ type ReservationWithRelations,
83
+ type UsePaginatedReservationsOptions,
84
+ type UsePaginatedReservationsReturn,
85
+ } from "./reservations";
86
+
87
+ // ============================================
88
+ // PRODUCT HOOKS
89
+ // ============================================
90
+ export {
91
+ useProducts,
92
+ type UseProductsOptions,
93
+ type UseProductsReturn,
94
+ } from "./products";
95
+
96
+ // ============================================
97
+ // PRODUCT INSTANCE HOOKS
98
+ // ============================================
99
+ export {
100
+ useProductInstances,
101
+ type UseProductInstancesOptions,
102
+ type UseProductInstancesReturn,
103
+ } from "./productInstances";
104
+
105
+ // ============================================
106
+ // CONTACT HOOKS
107
+ // ============================================
108
+ export {
109
+ useContacts,
110
+ useActiveContacts,
111
+ useDeletedContacts,
112
+ type UseContactsOptions,
113
+ type UseContactsReturn,
114
+ type ContactWithRelations,
115
+ type UsePaginatedContactsOptions,
116
+ type UsePaginatedContactsReturn,
117
+ } from "./contacts";
@@ -0,0 +1 @@
1
+ export * from "./useProductInstances";
@@ -1,14 +1,14 @@
1
1
  /**
2
- * useProductInstances Hook
2
+ * ProductInstance Hooks
3
3
  *
4
- * Vue composable for fetching and managing product instance data with reactive state.
4
+ * Vue composables for fetching and managing product instance data with reactive state.
5
5
  * Provides loading states, error handling, refetch capabilities, and CRUD operations.
6
6
  */
7
7
 
8
8
  import type { Ref, ComputedRef } from "vue";
9
9
  import type { ProductInstance } from "@htlkg/core/types";
10
- import { createDataHook, type BaseHookOptions } from "./createDataHook";
11
- import { getSharedClient } from "../client";
10
+ import { createDataHook, type BaseHookOptions } from "../createDataHook";
11
+ import { getSharedClient } from "../../client";
12
12
  import {
13
13
  createProductInstance,
14
14
  updateProductInstance,
@@ -16,7 +16,7 @@ import {
16
16
  toggleProductInstanceEnabled,
17
17
  type CreateProductInstanceInput,
18
18
  type UpdateProductInstanceInput,
19
- } from "../mutations/productInstances";
19
+ } from "../../mutations/productInstances";
20
20
 
21
21
  export interface UseProductInstancesOptions extends BaseHookOptions {
22
22
  /** Filter criteria for product instances */
@@ -102,7 +102,7 @@ const useProductInstancesInternal = createDataHook<
102
102
  *
103
103
  * @example
104
104
  * ```typescript
105
- * import { useProductInstances } from '@htlkg/data/hooks';
105
+ * import { useProductInstances } from '@htlkg/data/hooks/productInstances';
106
106
  *
107
107
  * const { instances, loading, error, refetch } = useProductInstances();
108
108
  * ```
@@ -172,3 +172,6 @@ export function useProductInstances(options: UseProductInstancesOptions = {}): U
172
172
  toggleEnabled,
173
173
  };
174
174
  }
175
+
176
+ // Re-export types for convenience
177
+ export type { CreateProductInstanceInput, UpdateProductInstanceInput };
@@ -0,0 +1 @@
1
+ export * from "./useProducts";
@@ -1,13 +1,12 @@
1
1
  /**
2
- * useProducts Hook
2
+ * Product Hooks
3
3
  *
4
- * Vue composable for fetching and managing product data with reactive state.
5
- * Provides loading states, error handling, and refetch capabilities.
4
+ * Vue composables for fetching and managing product data with reactive state.
6
5
  */
7
6
 
8
7
  import type { Ref, ComputedRef } from "vue";
9
8
  import type { Product } from "@htlkg/core/types";
10
- import { createDataHook, type BaseHookOptions } from "./createDataHook";
9
+ import { createDataHook, type BaseHookOptions } from "../createDataHook";
11
10
 
12
11
  export interface UseProductsOptions extends BaseHookOptions {
13
12
  /** Filter criteria for products */
@@ -63,7 +62,7 @@ const useProductsInternal = createDataHook<Product, UseProductsOptions, { active
63
62
  *
64
63
  * @example
65
64
  * ```typescript
66
- * import { useProducts } from '@htlkg/data/hooks';
65
+ * import { useProducts } from '@htlkg/data/hooks/products';
67
66
  *
68
67
  * const { products, loading, error, refetch } = useProducts();
69
68
  * ```
@@ -0,0 +1,2 @@
1
+ export * from "./useReservations";
2
+ export * from "./usePaginatedReservations";