@htlkg/data 0.0.21 → 0.0.22

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 (59) hide show
  1. package/dist/hooks/index.d.ts +601 -94
  2. package/dist/hooks/index.js +682 -73
  3. package/dist/hooks/index.js.map +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +691 -82
  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/createPaginatedDataHook.ts +359 -0
  19. package/src/hooks/data-hook-errors.property.test.ts +4 -4
  20. package/src/hooks/data-hook-filters.property.test.ts +4 -4
  21. package/src/hooks/data-hooks.property.test.ts +4 -4
  22. package/src/hooks/index.ts +96 -8
  23. package/src/hooks/productInstances/index.ts +1 -0
  24. package/src/hooks/{useProductInstances.ts → productInstances/useProductInstances.ts} +9 -6
  25. package/src/hooks/products/index.ts +1 -0
  26. package/src/hooks/{useProducts.ts → products/useProducts.ts} +4 -5
  27. package/src/hooks/reservations/index.ts +2 -0
  28. package/src/hooks/reservations/usePaginatedReservations.ts +258 -0
  29. package/src/hooks/{useReservations.ts → reservations/useReservations.ts} +65 -10
  30. package/src/hooks/users/index.ts +2 -0
  31. package/src/hooks/users/usePaginatedUsers.ts +213 -0
  32. package/src/hooks/{useUsers.ts → users/useUsers.ts} +1 -1
  33. package/src/mutations/accounts/accounts.test.ts +287 -0
  34. package/src/mutations/{accounts.ts → accounts/accounts.ts} +2 -2
  35. package/src/mutations/accounts/index.ts +1 -0
  36. package/src/mutations/brands/brands.test.ts +292 -0
  37. package/src/mutations/{brands.ts → brands/brands.ts} +2 -2
  38. package/src/mutations/brands/index.ts +1 -0
  39. package/src/mutations/reservations/index.ts +1 -0
  40. package/src/mutations/{reservations.test.ts → reservations/reservations.test.ts} +1 -1
  41. package/src/mutations/{reservations.ts → reservations/reservations.ts} +2 -2
  42. package/src/mutations/users/index.ts +1 -0
  43. package/src/mutations/users/users.test.ts +289 -0
  44. package/src/mutations/{users.ts → users/users.ts} +2 -2
  45. package/src/queries/accounts/accounts.test.ts +228 -0
  46. package/src/queries/accounts/index.ts +1 -0
  47. package/src/queries/brands/brands.test.ts +288 -0
  48. package/src/queries/brands/index.ts +1 -0
  49. package/src/queries/products/index.ts +1 -0
  50. package/src/queries/products/products.test.ts +347 -0
  51. package/src/queries/reservations/index.ts +1 -0
  52. package/src/queries/users/index.ts +1 -0
  53. package/src/queries/users/users.test.ts +301 -0
  54. /package/src/queries/{accounts.ts → accounts/accounts.ts} +0 -0
  55. /package/src/queries/{brands.ts → brands/brands.ts} +0 -0
  56. /package/src/queries/{products.ts → products/products.ts} +0 -0
  57. /package/src/queries/{reservations.test.ts → reservations/reservations.test.ts} +0 -0
  58. /package/src/queries/{reservations.ts → reservations/reservations.ts} +0 -0
  59. /package/src/queries/{users.ts → users/users.ts} +0 -0
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Paginated Brands Hooks
3
+ *
4
+ * Vue composables for fetching brands with server-side pagination.
5
+ * Provides separate hooks for active and deleted brands to enable
6
+ * efficient tab-based filtering in large datasets.
7
+ */
8
+
9
+ import type { Ref, ComputedRef } from "vue";
10
+ import type { Brand } from "@htlkg/core/types";
11
+ import {
12
+ createPaginatedDataHook,
13
+ ACTIVE_FILTER,
14
+ DELETED_FILTER,
15
+ type PaginatedHookOptions,
16
+ type PaginationState,
17
+ } from "../createPaginatedDataHook";
18
+
19
+ /** Extended Brand type with computed fields */
20
+ export type BrandWithCounts = Brand & {
21
+ accountName?: string;
22
+ enabledProductCount?: number;
23
+ totalProductCount?: number;
24
+ deletedAt?: string;
25
+ deletedBy?: string;
26
+ };
27
+
28
+ export interface UsePaginatedBrandsOptions extends PaginatedHookOptions {
29
+ /** Filter by account ID */
30
+ accountId?: string;
31
+ }
32
+
33
+ export interface UsePaginatedBrandsReturn {
34
+ /** Reactive array of brands */
35
+ brands: Ref<BrandWithCounts[]>;
36
+ /** Loading state (true during any fetch) */
37
+ loading: Ref<boolean>;
38
+ /** Loading state for initial fetch */
39
+ initialLoading: Ref<boolean>;
40
+ /** Loading state for loadMore */
41
+ loadingMore: Ref<boolean>;
42
+ /** Error state */
43
+ error: Ref<Error | null>;
44
+ /** Pagination state */
45
+ pagination: Ref<PaginationState>;
46
+ /** Whether there are more items to load */
47
+ hasMore: ComputedRef<boolean>;
48
+ /** Load next page of data */
49
+ loadMore: () => Promise<void>;
50
+ /** Refetch data (resets to first page) */
51
+ refetch: () => Promise<void>;
52
+ /** Reset data and pagination state */
53
+ reset: () => void;
54
+ /** Update search filter and refetch from server (searches ALL data) */
55
+ setSearchFilter: (filter: any) => Promise<void>;
56
+ /** Current search filter */
57
+ searchFilter: Ref<any>;
58
+ }
59
+
60
+ /**
61
+ * Build additional filter from hook options
62
+ */
63
+ function buildFilter(options: UsePaginatedBrandsOptions): any {
64
+ const conditions: any[] = [];
65
+
66
+ if (options.accountId) {
67
+ conditions.push({ accountId: { eq: options.accountId } });
68
+ }
69
+
70
+ if (options.filter && Object.keys(options.filter).length > 0) {
71
+ conditions.push(options.filter);
72
+ }
73
+
74
+ if (conditions.length === 0) {
75
+ return undefined;
76
+ }
77
+ if (conditions.length === 1) {
78
+ return conditions[0];
79
+ }
80
+ return { and: conditions };
81
+ }
82
+
83
+ /**
84
+ * Transform brand data
85
+ */
86
+ function transformBrand(brand: any): BrandWithCounts {
87
+ return {
88
+ ...brand,
89
+ accountName: brand.account?.name || "",
90
+ };
91
+ }
92
+
93
+ /**
94
+ * Selection set for brand queries
95
+ */
96
+ const BRAND_SELECTION_SET = [
97
+ "id",
98
+ "name",
99
+ "accountId",
100
+ "logo",
101
+ "timezone",
102
+ "status",
103
+ "settings",
104
+ "deletedAt",
105
+ "deletedBy",
106
+ "account.name",
107
+ ];
108
+
109
+ /**
110
+ * Internal hook for active brands
111
+ */
112
+ const useActiveBrandsInternal = createPaginatedDataHook<BrandWithCounts, UsePaginatedBrandsOptions>({
113
+ model: "Brand",
114
+ dataPropertyName: "brands",
115
+ defaultPageSize: 25,
116
+ selectionSet: BRAND_SELECTION_SET,
117
+ transform: transformBrand,
118
+ buildFilter,
119
+ baseFilter: ACTIVE_FILTER,
120
+ });
121
+
122
+ /**
123
+ * Internal hook for deleted brands
124
+ */
125
+ const useDeletedBrandsInternal = createPaginatedDataHook<BrandWithCounts, UsePaginatedBrandsOptions>({
126
+ model: "Brand",
127
+ dataPropertyName: "brands",
128
+ defaultPageSize: 25,
129
+ selectionSet: BRAND_SELECTION_SET,
130
+ transform: transformBrand,
131
+ buildFilter,
132
+ baseFilter: DELETED_FILTER,
133
+ });
134
+
135
+ /**
136
+ * Composable for fetching active (non-deleted) brands with pagination
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * import { useActiveBrands } from '@htlkg/data/hooks';
141
+ *
142
+ * const { brands, loading, hasMore, loadMore, refetch } = useActiveBrands({
143
+ * pageSize: 25,
144
+ * });
145
+ *
146
+ * // Load more when user scrolls or clicks "Load More"
147
+ * async function onLoadMore() {
148
+ * await loadMore();
149
+ * }
150
+ * ```
151
+ *
152
+ * @example With account filter
153
+ * ```typescript
154
+ * const { brands, loading } = useActiveBrands({
155
+ * accountId: 'account-123',
156
+ * pageSize: 50
157
+ * });
158
+ * ```
159
+ */
160
+ export function useActiveBrands(options: UsePaginatedBrandsOptions = {}): UsePaginatedBrandsReturn {
161
+ const result = useActiveBrandsInternal(options);
162
+ return {
163
+ brands: result.brands as Ref<BrandWithCounts[]>,
164
+ loading: result.loading,
165
+ initialLoading: result.initialLoading,
166
+ loadingMore: result.loadingMore,
167
+ error: result.error,
168
+ pagination: result.pagination,
169
+ hasMore: result.hasMore,
170
+ loadMore: result.loadMore,
171
+ refetch: result.refetch,
172
+ reset: result.reset,
173
+ setSearchFilter: result.setSearchFilter,
174
+ searchFilter: result.searchFilter,
175
+ };
176
+ }
177
+
178
+ /**
179
+ * Composable for fetching deleted brands with pagination
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * import { useDeletedBrands } from '@htlkg/data/hooks';
184
+ *
185
+ * const { brands, loading, hasMore, loadMore, refetch } = useDeletedBrands({
186
+ * pageSize: 25,
187
+ * });
188
+ * ```
189
+ */
190
+ export function useDeletedBrands(options: UsePaginatedBrandsOptions = {}): UsePaginatedBrandsReturn {
191
+ const result = useDeletedBrandsInternal(options);
192
+ return {
193
+ brands: result.brands as Ref<BrandWithCounts[]>,
194
+ loading: result.loading,
195
+ initialLoading: result.initialLoading,
196
+ loadingMore: result.loadingMore,
197
+ error: result.error,
198
+ pagination: result.pagination,
199
+ hasMore: result.hasMore,
200
+ loadMore: result.loadMore,
201
+ refetch: result.refetch,
202
+ reset: result.reset,
203
+ setSearchFilter: result.setSearchFilter,
204
+ searchFilter: result.searchFilter,
205
+ };
206
+ }
@@ -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", () => ({