@htlkg/data 0.0.1 → 0.0.3

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 (56) hide show
  1. package/README.md +53 -0
  2. package/dist/client/index.d.ts +117 -31
  3. package/dist/client/index.js +74 -22
  4. package/dist/client/index.js.map +1 -1
  5. package/dist/content-collections/index.js +20 -24
  6. package/dist/content-collections/index.js.map +1 -1
  7. package/dist/hooks/index.d.ts +113 -5
  8. package/dist/hooks/index.js +165 -182
  9. package/dist/hooks/index.js.map +1 -1
  10. package/dist/index.d.ts +8 -4
  11. package/dist/index.js +305 -182
  12. package/dist/index.js.map +1 -1
  13. package/dist/queries/index.d.ts +78 -1
  14. package/dist/queries/index.js +47 -0
  15. package/dist/queries/index.js.map +1 -1
  16. package/dist/stores/index.d.ts +106 -0
  17. package/dist/stores/index.js +108 -0
  18. package/dist/stores/index.js.map +1 -0
  19. package/package.json +60 -37
  20. package/src/client/__tests__/server.test.ts +100 -0
  21. package/src/client/client.md +91 -0
  22. package/src/client/index.test.ts +232 -0
  23. package/src/client/index.ts +145 -0
  24. package/src/client/server.ts +118 -0
  25. package/src/content-collections/content-collections.md +87 -0
  26. package/src/content-collections/generator.ts +314 -0
  27. package/src/content-collections/index.ts +32 -0
  28. package/src/content-collections/schemas.ts +75 -0
  29. package/src/content-collections/sync.ts +139 -0
  30. package/src/hooks/README.md +293 -0
  31. package/src/hooks/createDataHook.ts +208 -0
  32. package/src/hooks/data-hook-errors.property.test.ts +270 -0
  33. package/src/hooks/data-hook-filters.property.test.ts +263 -0
  34. package/src/hooks/data-hooks.property.test.ts +190 -0
  35. package/src/hooks/hooks.test.ts +76 -0
  36. package/src/hooks/index.ts +21 -0
  37. package/src/hooks/useAccounts.ts +66 -0
  38. package/src/hooks/useBrands.ts +95 -0
  39. package/src/hooks/useProducts.ts +88 -0
  40. package/src/hooks/useUsers.ts +89 -0
  41. package/src/index.ts +32 -0
  42. package/src/mutations/accounts.ts +127 -0
  43. package/src/mutations/brands.ts +133 -0
  44. package/src/mutations/index.ts +32 -0
  45. package/src/mutations/mutations.md +96 -0
  46. package/src/mutations/users.ts +136 -0
  47. package/src/queries/accounts.ts +121 -0
  48. package/src/queries/brands.ts +176 -0
  49. package/src/queries/index.ts +45 -0
  50. package/src/queries/products.ts +282 -0
  51. package/src/queries/queries.md +88 -0
  52. package/src/queries/server-helpers.ts +114 -0
  53. package/src/queries/users.ts +199 -0
  54. package/src/stores/createStores.ts +148 -0
  55. package/src/stores/index.ts +15 -0
  56. package/src/stores/stores.md +104 -0
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Property-Based Tests for Data Hooks
3
+ *
4
+ * Feature: htlkg-modular-architecture, Property 5: Data hooks return reactive state
5
+ * Validates: Requirements 11.1, 11.2, 11.3
6
+ *
7
+ * Tests that data hooks return reactive state with correct structure and behavior.
8
+ */
9
+
10
+ import { describe, it, expect, vi, beforeEach } from "vitest";
11
+ import * as fc from "fast-check";
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";
17
+
18
+ // Mock the client module
19
+ vi.mock("../client", () => ({
20
+ generateClient: vi.fn(() => ({
21
+ models: {
22
+ Brand: {
23
+ list: vi.fn().mockResolvedValue({ data: [], errors: null }),
24
+ },
25
+ Account: {
26
+ list: vi.fn().mockResolvedValue({ data: [], errors: null }),
27
+ },
28
+ User: {
29
+ list: vi.fn().mockResolvedValue({ data: [], errors: null }),
30
+ },
31
+ Product: {
32
+ list: vi.fn().mockResolvedValue({ data: [], errors: null }),
33
+ },
34
+ },
35
+ })),
36
+ }));
37
+
38
+ describe("Data Hooks - Property 5: Data hooks return reactive state", () => {
39
+ beforeEach(() => {
40
+ vi.clearAllMocks();
41
+ });
42
+
43
+ /**
44
+ * Property: For any data hook, calling it should return reactive refs
45
+ * for data, loading, error, and a refetch function
46
+ */
47
+ it("useBrands returns reactive state structure", () => {
48
+ fc.assert(
49
+ fc.property(
50
+ fc.record({
51
+ autoFetch: fc.boolean(),
52
+ limit: fc.option(fc.integer({ min: 1, max: 100 }), { nil: undefined }),
53
+ }),
54
+ (options) => {
55
+ const result = useBrands(options);
56
+
57
+ // Check that all required properties exist
58
+ expect(result).toHaveProperty("brands");
59
+ expect(result).toHaveProperty("activeBrands");
60
+ expect(result).toHaveProperty("loading");
61
+ expect(result).toHaveProperty("error");
62
+ expect(result).toHaveProperty("refetch");
63
+
64
+ // Check that data properties are reactive refs
65
+ expect(isRef(result.brands)).toBe(true);
66
+ expect(isRef(result.loading)).toBe(true);
67
+ expect(isRef(result.error)).toBe(true);
68
+
69
+ // Check that activeBrands is a computed ref
70
+ expect(isRef(result.activeBrands)).toBe(true);
71
+
72
+ // Check that refetch is a function
73
+ expect(typeof result.refetch).toBe("function");
74
+
75
+ // Check initial state values
76
+ expect(Array.isArray(result.brands.value)).toBe(true);
77
+ expect(typeof result.loading.value).toBe("boolean");
78
+ expect(result.error.value === null || result.error.value instanceof Error).toBe(true);
79
+ },
80
+ ),
81
+ { numRuns: 100 },
82
+ );
83
+ });
84
+
85
+ it("useAccounts returns reactive state structure", () => {
86
+ fc.assert(
87
+ fc.property(
88
+ fc.record({
89
+ autoFetch: fc.boolean(),
90
+ limit: fc.option(fc.integer({ min: 1, max: 100 }), { nil: undefined }),
91
+ }),
92
+ (options) => {
93
+ const result = useAccounts(options);
94
+
95
+ // Check that all required properties exist
96
+ expect(result).toHaveProperty("accounts");
97
+ expect(result).toHaveProperty("loading");
98
+ expect(result).toHaveProperty("error");
99
+ expect(result).toHaveProperty("refetch");
100
+
101
+ // Check that data properties are reactive refs
102
+ expect(isRef(result.accounts)).toBe(true);
103
+ expect(isRef(result.loading)).toBe(true);
104
+ expect(isRef(result.error)).toBe(true);
105
+
106
+ // Check that refetch is a function
107
+ expect(typeof result.refetch).toBe("function");
108
+
109
+ // Check initial state values
110
+ expect(Array.isArray(result.accounts.value)).toBe(true);
111
+ expect(typeof result.loading.value).toBe("boolean");
112
+ expect(result.error.value === null || result.error.value instanceof Error).toBe(true);
113
+ },
114
+ ),
115
+ { numRuns: 100 },
116
+ );
117
+ });
118
+
119
+ it("useUsers returns reactive state structure", () => {
120
+ fc.assert(
121
+ fc.property(
122
+ fc.record({
123
+ autoFetch: fc.boolean(),
124
+ limit: fc.option(fc.integer({ min: 1, max: 100 }), { nil: undefined }),
125
+ }),
126
+ (options) => {
127
+ const result = useUsers(options);
128
+
129
+ // Check that all required properties exist
130
+ expect(result).toHaveProperty("users");
131
+ expect(result).toHaveProperty("loading");
132
+ expect(result).toHaveProperty("error");
133
+ expect(result).toHaveProperty("refetch");
134
+
135
+ // Check that data properties are reactive refs
136
+ expect(isRef(result.users)).toBe(true);
137
+ expect(isRef(result.loading)).toBe(true);
138
+ expect(isRef(result.error)).toBe(true);
139
+
140
+ // Check that refetch is a function
141
+ expect(typeof result.refetch).toBe("function");
142
+
143
+ // Check initial state values
144
+ expect(Array.isArray(result.users.value)).toBe(true);
145
+ expect(typeof result.loading.value).toBe("boolean");
146
+ expect(result.error.value === null || result.error.value instanceof Error).toBe(true);
147
+ },
148
+ ),
149
+ { numRuns: 100 },
150
+ );
151
+ });
152
+
153
+ it("useProducts returns reactive state structure", () => {
154
+ fc.assert(
155
+ fc.property(
156
+ fc.record({
157
+ autoFetch: fc.boolean(),
158
+ limit: fc.option(fc.integer({ min: 1, max: 100 }), { nil: undefined }),
159
+ }),
160
+ (options) => {
161
+ const result = useProducts(options);
162
+
163
+ // Check that all required properties exist
164
+ expect(result).toHaveProperty("products");
165
+ expect(result).toHaveProperty("activeProducts");
166
+ expect(result).toHaveProperty("loading");
167
+ expect(result).toHaveProperty("error");
168
+ expect(result).toHaveProperty("refetch");
169
+
170
+ // Check that data properties are reactive refs
171
+ expect(isRef(result.products)).toBe(true);
172
+ expect(isRef(result.loading)).toBe(true);
173
+ expect(isRef(result.error)).toBe(true);
174
+
175
+ // Check that activeProducts is a computed ref
176
+ expect(isRef(result.activeProducts)).toBe(true);
177
+
178
+ // Check that refetch is a function
179
+ expect(typeof result.refetch).toBe("function");
180
+
181
+ // Check initial state values
182
+ expect(Array.isArray(result.products.value)).toBe(true);
183
+ expect(typeof result.loading.value).toBe("boolean");
184
+ expect(result.error.value === null || result.error.value instanceof Error).toBe(true);
185
+ },
186
+ ),
187
+ { numRuns: 100 },
188
+ );
189
+ });
190
+ });
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Data Hooks Tests
3
+ *
4
+ * Basic smoke tests to verify hooks can be imported and have correct structure.
5
+ */
6
+
7
+ import { describe, it, expect } from "vitest";
8
+ import { useBrands, useAccounts, useUsers, useProducts } from "./index";
9
+
10
+ describe("Data Hooks", () => {
11
+ describe("useBrands", () => {
12
+ it("should be a function", () => {
13
+ expect(typeof useBrands).toBe("function");
14
+ });
15
+
16
+ it("should return expected properties", () => {
17
+ const result = useBrands({ autoFetch: false });
18
+
19
+ expect(result).toHaveProperty("brands");
20
+ expect(result).toHaveProperty("activeBrands");
21
+ expect(result).toHaveProperty("loading");
22
+ expect(result).toHaveProperty("error");
23
+ expect(result).toHaveProperty("refetch");
24
+ expect(typeof result.refetch).toBe("function");
25
+ });
26
+ });
27
+
28
+ describe("useAccounts", () => {
29
+ it("should be a function", () => {
30
+ expect(typeof useAccounts).toBe("function");
31
+ });
32
+
33
+ it("should return expected properties", () => {
34
+ const result = useAccounts({ autoFetch: false });
35
+
36
+ expect(result).toHaveProperty("accounts");
37
+ expect(result).toHaveProperty("loading");
38
+ expect(result).toHaveProperty("error");
39
+ expect(result).toHaveProperty("refetch");
40
+ expect(typeof result.refetch).toBe("function");
41
+ });
42
+ });
43
+
44
+ describe("useUsers", () => {
45
+ it("should be a function", () => {
46
+ expect(typeof useUsers).toBe("function");
47
+ });
48
+
49
+ it("should return expected properties", () => {
50
+ const result = useUsers({ autoFetch: false });
51
+
52
+ expect(result).toHaveProperty("users");
53
+ expect(result).toHaveProperty("loading");
54
+ expect(result).toHaveProperty("error");
55
+ expect(result).toHaveProperty("refetch");
56
+ expect(typeof result.refetch).toBe("function");
57
+ });
58
+ });
59
+
60
+ describe("useProducts", () => {
61
+ it("should be a function", () => {
62
+ expect(typeof useProducts).toBe("function");
63
+ });
64
+
65
+ it("should return expected properties", () => {
66
+ const result = useProducts({ autoFetch: false });
67
+
68
+ expect(result).toHaveProperty("products");
69
+ expect(result).toHaveProperty("activeProducts");
70
+ expect(result).toHaveProperty("loading");
71
+ expect(result).toHaveProperty("error");
72
+ expect(result).toHaveProperty("refetch");
73
+ expect(typeof result.refetch).toBe("function");
74
+ });
75
+ });
76
+ });
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Data Hooks for @htlkg/data
3
+ *
4
+ * Vue composables for fetching and managing data with reactive state.
5
+ */
6
+
7
+ // Hook factory for creating custom data hooks
8
+ export {
9
+ createDataHook,
10
+ resetClientInstance,
11
+ type CreateDataHookOptions,
12
+ type BaseHookOptions,
13
+ type DataHookReturn,
14
+ type InferHookReturn,
15
+ } from "./createDataHook";
16
+
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";
@@ -0,0 +1,66 @@
1
+ /**
2
+ * useAccounts Hook
3
+ *
4
+ * Vue composable for fetching and managing account data with reactive state.
5
+ * Provides loading states, error handling, and refetch capabilities.
6
+ */
7
+
8
+ import type { Ref } from "vue";
9
+ import type { Account } from "@htlkg/core/types";
10
+ import { createDataHook, type BaseHookOptions } from "./createDataHook";
11
+
12
+ export interface UseAccountsOptions extends BaseHookOptions {
13
+ /** Filter criteria for accounts */
14
+ filter?: any;
15
+ /** Limit number of results */
16
+ limit?: number;
17
+ /** Auto-fetch on mount (default: true) */
18
+ autoFetch?: boolean;
19
+ }
20
+
21
+ export interface UseAccountsReturn {
22
+ /** Reactive array of accounts */
23
+ accounts: Ref<Account[]>;
24
+ /** Loading state */
25
+ loading: Ref<boolean>;
26
+ /** Error state */
27
+ error: Ref<Error | null>;
28
+ /** Refetch accounts */
29
+ refetch: () => Promise<void>;
30
+ }
31
+
32
+ /**
33
+ * Internal hook created by factory
34
+ */
35
+ const useAccountsInternal = createDataHook<Account, UseAccountsOptions>({
36
+ model: "Account",
37
+ dataPropertyName: "accounts",
38
+ });
39
+
40
+ /**
41
+ * Composable for fetching and managing accounts
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * import { useAccounts } from '@htlkg/data/hooks';
46
+ *
47
+ * const { accounts, loading, error, refetch } = useAccounts();
48
+ * ```
49
+ *
50
+ * @example With filters
51
+ * ```typescript
52
+ * const { accounts, loading } = useAccounts({
53
+ * filter: { status: { eq: 'active' } },
54
+ * limit: 50
55
+ * });
56
+ * ```
57
+ */
58
+ export function useAccounts(options: UseAccountsOptions = {}): UseAccountsReturn {
59
+ const result = useAccountsInternal(options);
60
+ return {
61
+ accounts: result.accounts as Ref<Account[]>,
62
+ loading: result.loading,
63
+ error: result.error,
64
+ refetch: result.refetch,
65
+ };
66
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * useBrands Hook
3
+ *
4
+ * Vue composable for fetching and managing brand data with reactive state.
5
+ * Provides loading states, error handling, and refetch capabilities.
6
+ */
7
+
8
+ import type { Ref, ComputedRef } from "vue";
9
+ import type { Brand } from "@htlkg/core/types";
10
+ import { createDataHook, type BaseHookOptions } from "./createDataHook";
11
+
12
+ export interface UseBrandsOptions extends BaseHookOptions {
13
+ /** Filter criteria for brands */
14
+ filter?: any;
15
+ /** Limit number of results */
16
+ limit?: number;
17
+ /** Auto-fetch on mount (default: true) */
18
+ autoFetch?: boolean;
19
+ /** Filter by account ID */
20
+ accountId?: string;
21
+ /** Only active brands */
22
+ activeOnly?: boolean;
23
+ }
24
+
25
+ export interface UseBrandsReturn {
26
+ /** Reactive array of brands */
27
+ brands: Ref<Brand[]>;
28
+ /** Computed array of active brands only */
29
+ activeBrands: ComputedRef<Brand[]>;
30
+ /** Loading state */
31
+ loading: Ref<boolean>;
32
+ /** Error state */
33
+ error: Ref<Error | null>;
34
+ /** Refetch brands */
35
+ refetch: () => Promise<void>;
36
+ }
37
+
38
+ /**
39
+ * Build filter from hook options
40
+ */
41
+ function buildFilter(options: UseBrandsOptions): any {
42
+ let filter: any = options.filter || {};
43
+
44
+ if (options.accountId) {
45
+ filter = { ...filter, accountId: { eq: options.accountId } };
46
+ }
47
+
48
+ if (options.activeOnly) {
49
+ filter = { ...filter, status: { eq: "active" } };
50
+ }
51
+
52
+ return Object.keys(filter).length > 0 ? filter : undefined;
53
+ }
54
+
55
+ /**
56
+ * Internal hook created by factory
57
+ */
58
+ const useBrandsInternal = createDataHook<Brand, UseBrandsOptions, { activeBrands: Brand[] }>({
59
+ model: "Brand",
60
+ dataPropertyName: "brands",
61
+ buildFilter,
62
+ computedProperties: {
63
+ activeBrands: (brands) => brands.filter((b) => b.status === "active"),
64
+ },
65
+ });
66
+
67
+ /**
68
+ * Composable for fetching and managing brands
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * import { useBrands } from '@htlkg/data/hooks';
73
+ *
74
+ * const { brands, loading, error, refetch } = useBrands();
75
+ * ```
76
+ *
77
+ * @example With filters
78
+ * ```typescript
79
+ * const { brands, loading } = useBrands({
80
+ * accountId: 'account-123',
81
+ * activeOnly: true,
82
+ * limit: 50
83
+ * });
84
+ * ```
85
+ */
86
+ export function useBrands(options: UseBrandsOptions = {}): UseBrandsReturn {
87
+ const result = useBrandsInternal(options);
88
+ return {
89
+ brands: result.brands as Ref<Brand[]>,
90
+ activeBrands: result.activeBrands as ComputedRef<Brand[]>,
91
+ loading: result.loading,
92
+ error: result.error,
93
+ refetch: result.refetch,
94
+ };
95
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * useProducts Hook
3
+ *
4
+ * Vue composable for fetching and managing product data with reactive state.
5
+ * Provides loading states, error handling, and refetch capabilities.
6
+ */
7
+
8
+ import type { Ref, ComputedRef } from "vue";
9
+ import type { Product } from "@htlkg/core/types";
10
+ import { createDataHook, type BaseHookOptions } from "./createDataHook";
11
+
12
+ export interface UseProductsOptions extends BaseHookOptions {
13
+ /** Filter criteria for products */
14
+ filter?: any;
15
+ /** Limit number of results */
16
+ limit?: number;
17
+ /** Auto-fetch on mount (default: true) */
18
+ autoFetch?: boolean;
19
+ /** Only active products */
20
+ activeOnly?: boolean;
21
+ }
22
+
23
+ export interface UseProductsReturn {
24
+ /** Reactive array of products */
25
+ products: Ref<Product[]>;
26
+ /** Computed array of active products only */
27
+ activeProducts: ComputedRef<Product[]>;
28
+ /** Loading state */
29
+ loading: Ref<boolean>;
30
+ /** Error state */
31
+ error: Ref<Error | null>;
32
+ /** Refetch products */
33
+ refetch: () => Promise<void>;
34
+ }
35
+
36
+ /**
37
+ * Build filter from hook options
38
+ */
39
+ function buildFilter(options: UseProductsOptions): any {
40
+ let filter: any = options.filter || {};
41
+
42
+ if (options.activeOnly) {
43
+ filter = { ...filter, isActive: { eq: true } };
44
+ }
45
+
46
+ return Object.keys(filter).length > 0 ? filter : undefined;
47
+ }
48
+
49
+ /**
50
+ * Internal hook created by factory
51
+ */
52
+ const useProductsInternal = createDataHook<Product, UseProductsOptions, { activeProducts: Product[] }>({
53
+ model: "Product",
54
+ dataPropertyName: "products",
55
+ buildFilter,
56
+ computedProperties: {
57
+ activeProducts: (products) => products.filter((p) => p.isActive === true),
58
+ },
59
+ });
60
+
61
+ /**
62
+ * Composable for fetching and managing products
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * import { useProducts } from '@htlkg/data/hooks';
67
+ *
68
+ * const { products, loading, error, refetch } = useProducts();
69
+ * ```
70
+ *
71
+ * @example With filters
72
+ * ```typescript
73
+ * const { products, loading } = useProducts({
74
+ * activeOnly: true,
75
+ * limit: 50
76
+ * });
77
+ * ```
78
+ */
79
+ export function useProducts(options: UseProductsOptions = {}): UseProductsReturn {
80
+ const result = useProductsInternal(options);
81
+ return {
82
+ products: result.products as Ref<Product[]>,
83
+ activeProducts: result.activeProducts as ComputedRef<Product[]>,
84
+ loading: result.loading,
85
+ error: result.error,
86
+ refetch: result.refetch,
87
+ };
88
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * useUsers Hook
3
+ *
4
+ * Vue composable for fetching and managing user data with reactive state.
5
+ * Provides loading states, error handling, and refetch capabilities.
6
+ */
7
+
8
+ import type { Ref } from "vue";
9
+ import type { User } from "@htlkg/core/types";
10
+ import { createDataHook, type BaseHookOptions } from "./createDataHook";
11
+
12
+ export interface UseUsersOptions extends BaseHookOptions {
13
+ /** Filter criteria for users */
14
+ filter?: any;
15
+ /** Limit number of results */
16
+ limit?: number;
17
+ /** Auto-fetch on mount (default: true) */
18
+ autoFetch?: boolean;
19
+ /** Filter by brand ID */
20
+ brandId?: string;
21
+ /** Filter by account ID */
22
+ accountId?: string;
23
+ }
24
+
25
+ export interface UseUsersReturn {
26
+ /** Reactive array of users */
27
+ users: Ref<User[]>;
28
+ /** Loading state */
29
+ loading: Ref<boolean>;
30
+ /** Error state */
31
+ error: Ref<Error | null>;
32
+ /** Refetch users */
33
+ refetch: () => Promise<void>;
34
+ }
35
+
36
+ /**
37
+ * Build filter from hook options
38
+ */
39
+ function buildFilter(options: UseUsersOptions): any {
40
+ let filter: any = options.filter || {};
41
+
42
+ if (options.brandId) {
43
+ filter = { ...filter, brandIds: { contains: options.brandId } };
44
+ }
45
+
46
+ if (options.accountId) {
47
+ filter = { ...filter, accountIds: { contains: options.accountId } };
48
+ }
49
+
50
+ return Object.keys(filter).length > 0 ? filter : undefined;
51
+ }
52
+
53
+ /**
54
+ * Internal hook created by factory
55
+ */
56
+ const useUsersInternal = createDataHook<User, UseUsersOptions>({
57
+ model: "User",
58
+ dataPropertyName: "users",
59
+ buildFilter,
60
+ });
61
+
62
+ /**
63
+ * Composable for fetching and managing users
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * import { useUsers } from '@htlkg/data/hooks';
68
+ *
69
+ * const { users, loading, error, refetch } = useUsers();
70
+ * ```
71
+ *
72
+ * @example With filters
73
+ * ```typescript
74
+ * const { users, loading } = useUsers({
75
+ * brandId: 'brand-123',
76
+ * accountId: 'account-456',
77
+ * limit: 50
78
+ * });
79
+ * ```
80
+ */
81
+ export function useUsers(options: UseUsersOptions = {}): UseUsersReturn {
82
+ const result = useUsersInternal(options);
83
+ return {
84
+ users: result.users as Ref<User[]>,
85
+ loading: result.loading,
86
+ error: result.error,
87
+ refetch: result.refetch,
88
+ };
89
+ }
package/src/index.ts ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @htlkg/data - Data Layer Module
3
+ *
4
+ * Provides GraphQL operations, Amplify integration, and reactive data hooks
5
+ * for the Hotelinking multi-tenant SaaS platform.
6
+ *
7
+ * @module @htlkg/data
8
+ */
9
+
10
+ // Client exports
11
+ export {
12
+ generateClient,
13
+ generateServerClient,
14
+ getSharedClient,
15
+ resetSharedClient,
16
+ type AstroAmplifyConfig,
17
+ } from "./client";
18
+
19
+ // Query exports
20
+ export * from "./queries";
21
+
22
+ // Mutation exports
23
+ export * from "./mutations";
24
+
25
+ // Hook exports
26
+ export * from "./hooks";
27
+
28
+ // Store factory exports
29
+ export * from "./stores";
30
+
31
+ // Content Collections exports (will be populated in task 3.8)
32
+ // export * from "./content-collections";