@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,91 @@
1
+ # Client Module
2
+
3
+ GraphQL client generation for client-side and server-side data fetching.
4
+
5
+ ## Installation
6
+
7
+ ```typescript
8
+ import {
9
+ generateClient,
10
+ generateServerClient,
11
+ getSharedClient,
12
+ resetSharedClient,
13
+ } from '@htlkg/data/client';
14
+ ```
15
+
16
+ ## Client-Side
17
+
18
+ ### getSharedClient
19
+
20
+ Singleton client for client-side fetching. Avoids creating multiple instances.
21
+
22
+ ```typescript
23
+ import { getSharedClient } from '@htlkg/data/client';
24
+ import type { Schema } from '@backend/data/resource';
25
+
26
+ const client = getSharedClient<Schema>();
27
+ const { data } = await client.models.Account.list();
28
+ ```
29
+
30
+ ### generateClient
31
+
32
+ Create a new client instance. Use in component setup or after hydration.
33
+
34
+ ```typescript
35
+ import { generateClient } from '@htlkg/data/client';
36
+
37
+ const client = generateClient<Schema>();
38
+ const { data: brands } = await client.models.Brand.list();
39
+ ```
40
+
41
+ ### resetSharedClient
42
+
43
+ Reset the singleton (useful for auth state changes or testing).
44
+
45
+ ```typescript
46
+ import { resetSharedClient } from '@htlkg/data/client';
47
+
48
+ // After logout
49
+ resetSharedClient();
50
+ ```
51
+
52
+ ## Server-Side
53
+
54
+ ### generateServerClient
55
+
56
+ Create a server-side client for SSR. Must be called inside `runWithAmplifyServerContext`.
57
+
58
+ ```typescript
59
+ import { generateServerClient } from '@htlkg/data/client';
60
+ import { createRunWithAmplifyServerContext } from '@htlkg/core/amplify-astro-adapter';
61
+
62
+ const runWithAmplifyServerContext = createRunWithAmplifyServerContext({
63
+ config: amplifyConfig
64
+ });
65
+
66
+ const result = await runWithAmplifyServerContext({
67
+ astroServerContext: {
68
+ cookies: Astro.cookies,
69
+ request: Astro.request,
70
+ },
71
+ operation: async (contextSpec) => {
72
+ const client = generateServerClient<Schema>();
73
+ return await client.models.User.list();
74
+ },
75
+ });
76
+ ```
77
+
78
+ ## Auth Modes
79
+
80
+ | Mode | Description |
81
+ |------|-------------|
82
+ | `userPool` | Uses JWT from cookies (default) |
83
+ | `apiKey` | Uses API key for public requests |
84
+
85
+ ```typescript
86
+ // Authenticated request
87
+ const client = generateServerClient<Schema>({ authMode: 'userPool' });
88
+
89
+ // Public request
90
+ const client = generateServerClient<Schema>({ authMode: 'apiKey' });
91
+ ```
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Tests for @htlkg/data/client
3
+ *
4
+ * Tests the GraphQL client generation functions for both client-side and server-side usage
5
+ */
6
+
7
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
8
+ import type { AstroCookies } from 'astro';
9
+
10
+ // Mock aws-amplify
11
+ vi.mock('aws-amplify', () => ({
12
+ Amplify: {
13
+ configure: vi.fn(),
14
+ getConfig: vi.fn(() => ({}))
15
+ }
16
+ }));
17
+
18
+ // Mock aws-amplify/data
19
+ vi.mock('aws-amplify/data', () => ({
20
+ generateClient: vi.fn(() => ({
21
+ models: {
22
+ Brand: {
23
+ list: vi.fn(),
24
+ get: vi.fn(),
25
+ create: vi.fn(),
26
+ update: vi.fn(),
27
+ delete: vi.fn()
28
+ },
29
+ User: {
30
+ list: vi.fn(),
31
+ get: vi.fn()
32
+ }
33
+ }
34
+ }))
35
+ }));
36
+
37
+ // Mock @htlkg/core/amplify-astro-adapter
38
+ vi.mock('@htlkg/core/amplify-astro-adapter', () => ({
39
+ createRunWithAmplifyServerContext: vi.fn(() => vi.fn())
40
+ }));
41
+
42
+ // Mock aws-amplify/auth/server
43
+ vi.mock('aws-amplify/auth/server', () => ({
44
+ fetchAuthSession: vi.fn()
45
+ }));
46
+
47
+ // Import after mocks are set up
48
+ import { generateClient, generateServerClient } from './index';
49
+ import { Amplify } from 'aws-amplify';
50
+ import { generateClient as generateDataClient } from 'aws-amplify/data';
51
+ import { createRunWithAmplifyServerContext } from '@htlkg/core/amplify-astro-adapter';
52
+
53
+ describe('generateClient', () => {
54
+ it('should generate a client-side GraphQL client', () => {
55
+ const client = generateClient();
56
+
57
+ expect(client).toBeDefined();
58
+ expect(client.models).toBeDefined();
59
+ expect(client.models.Brand).toBeDefined();
60
+ });
61
+
62
+ it('should return a client with model operations', () => {
63
+ const client = generateClient();
64
+
65
+ expect(client.models.Brand.list).toBeDefined();
66
+ expect(client.models.Brand.get).toBeDefined();
67
+ expect(client.models.Brand.create).toBeDefined();
68
+ expect(client.models.Brand.update).toBeDefined();
69
+ expect(client.models.Brand.delete).toBeDefined();
70
+ });
71
+
72
+ it('should be callable multiple times', () => {
73
+ const client1 = generateClient();
74
+ const client2 = generateClient();
75
+
76
+ expect(client1).toBeDefined();
77
+ expect(client2).toBeDefined();
78
+ });
79
+ });
80
+
81
+ describe('generateServerClient', () => {
82
+ let mockConfig: any;
83
+
84
+ beforeEach(() => {
85
+ // Mock Amplify config
86
+ mockConfig = {
87
+ auth: {
88
+ user_pool_id: 'test-pool',
89
+ aws_region: 'us-east-1',
90
+ user_pool_client_id: 'test-client'
91
+ },
92
+ data: {
93
+ url: 'https://test.appsync-api.us-east-1.amazonaws.com/graphql',
94
+ aws_region: 'us-east-1',
95
+ api_key: 'test-api-key',
96
+ default_authorization_type: 'AMAZON_COGNITO_USER_POOLS',
97
+ authorization_types: ['API_KEY', 'AWS_IAM']
98
+ }
99
+ };
100
+ });
101
+
102
+ afterEach(() => {
103
+ vi.clearAllMocks();
104
+ });
105
+
106
+ describe('with userPool auth mode (default)', () => {
107
+ it('should generate a server-side client with default userPool auth', () => {
108
+ const client = generateServerClient({
109
+ config: mockConfig
110
+ });
111
+
112
+ expect(client).toBeDefined();
113
+ expect(client.models).toBeDefined();
114
+ });
115
+
116
+ it('should use userPool auth mode by default', () => {
117
+ generateServerClient({
118
+ config: mockConfig
119
+ });
120
+
121
+ expect(generateDataClient).toHaveBeenCalledWith({
122
+ authMode: 'userPool'
123
+ });
124
+ });
125
+
126
+ it('should not call Amplify.configure (should be done at app startup)', () => {
127
+ vi.clearAllMocks();
128
+
129
+ generateServerClient({
130
+ config: mockConfig
131
+ });
132
+
133
+ // generateServerClient should NOT call Amplify.configure
134
+ // It should be called once at app startup (e.g., in amplify-server.ts)
135
+ expect(Amplify.configure).not.toHaveBeenCalled();
136
+ });
137
+
138
+ it('should not call createRunWithAmplifyServerContext (should be done outside)', () => {
139
+ vi.clearAllMocks();
140
+
141
+ generateServerClient({
142
+ config: mockConfig
143
+ });
144
+
145
+ // generateServerClient should NOT call createRunWithAmplifyServerContext
146
+ // The caller should wrap the operation with runWithAmplifyServerContext
147
+ expect(createRunWithAmplifyServerContext).not.toHaveBeenCalled();
148
+ });
149
+ });
150
+
151
+ describe('with apiKey auth mode', () => {
152
+ it('should generate a server-side client with API key auth', () => {
153
+ const client = generateServerClient({
154
+ config: mockConfig,
155
+ authMode: 'apiKey'
156
+ });
157
+
158
+ expect(client).toBeDefined();
159
+ expect(client.models).toBeDefined();
160
+ });
161
+
162
+ it('should use apiKey auth mode when specified', () => {
163
+ generateServerClient({
164
+ config: mockConfig,
165
+ authMode: 'apiKey'
166
+ });
167
+
168
+ expect(generateDataClient).toHaveBeenCalledWith({
169
+ authMode: 'apiKey'
170
+ });
171
+ });
172
+ });
173
+
174
+ describe('configuration', () => {
175
+ it('should accept valid Amplify configuration', () => {
176
+ const client = generateServerClient({
177
+ config: mockConfig
178
+ });
179
+
180
+ expect(client).toBeDefined();
181
+ });
182
+
183
+ it('should handle configuration with minimal auth setup', () => {
184
+ const minimalConfig = {
185
+ auth: {
186
+ user_pool_id: 'test-pool',
187
+ aws_region: 'us-east-1',
188
+ user_pool_client_id: 'test-client'
189
+ }
190
+ };
191
+
192
+ const client = generateServerClient({
193
+ config: minimalConfig,
194
+ authMode: 'apiKey'
195
+ });
196
+
197
+ expect(client).toBeDefined();
198
+ });
199
+ });
200
+
201
+ describe('multiple instances', () => {
202
+ it('should allow creating multiple server clients', () => {
203
+ const client1 = generateServerClient({
204
+ config: mockConfig,
205
+ authMode: 'userPool'
206
+ });
207
+
208
+ const client2 = generateServerClient({
209
+ config: mockConfig,
210
+ authMode: 'apiKey'
211
+ });
212
+
213
+ expect(client1).toBeDefined();
214
+ expect(client2).toBeDefined();
215
+ });
216
+ });
217
+ });
218
+
219
+ describe('type exports', () => {
220
+ it('should export AstroAmplifyConfig type', () => {
221
+ // This is a compile-time check, but we can verify the import works
222
+ const config: any = {
223
+ auth: {
224
+ user_pool_id: 'test',
225
+ aws_region: 'us-east-1',
226
+ user_pool_client_id: 'test'
227
+ }
228
+ };
229
+
230
+ expect(config).toBeDefined();
231
+ });
232
+ });
@@ -0,0 +1,145 @@
1
+ /**
2
+ * GraphQL Client for @htlkg/data
3
+ *
4
+ * Provides both client-side and server-side GraphQL capabilities using AWS Amplify Data.
5
+ * The server-side functions use the Amplify Astro adapter for proper SSR support.
6
+ */
7
+
8
+ import { generateClient as generateDataClient } from "aws-amplify/data";
9
+ import type { ResourcesConfig } from "aws-amplify";
10
+
11
+ // Re-export server-side client generation
12
+ export { generateServerClientUsingCookies } from "./server";
13
+
14
+ // Singleton client instance for client-side fetching
15
+ let sharedClientInstance: any = null;
16
+
17
+ /**
18
+ * Get or create the shared GraphQL client instance (singleton pattern)
19
+ * Use this for client-side fetching to avoid creating multiple client instances.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const client = getSharedClient<Schema>();
24
+ * const { data } = await client.models.Account.list();
25
+ * ```
26
+ */
27
+ export function getSharedClient<
28
+ TSchema extends Record<string, unknown> = Record<string, unknown>,
29
+ >(): ReturnType<typeof generateDataClient<TSchema>> {
30
+ if (!sharedClientInstance) {
31
+ sharedClientInstance = generateDataClient<TSchema>();
32
+ }
33
+ return sharedClientInstance;
34
+ }
35
+
36
+ /**
37
+ * Reset the shared client instance (useful for testing or auth state changes)
38
+ */
39
+ export function resetSharedClient(): void {
40
+ sharedClientInstance = null;
41
+ }
42
+
43
+ /**
44
+ * Generate a client-side GraphQL client for use in Vue components and browser contexts
45
+ * This is SSR-safe and should be called within a component's setup function or after hydration
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * import type { Schema } from '@backend/data/resource';
50
+ * import { generateClient } from '@htlkg/data/client';
51
+ *
52
+ * const client = generateClient<Schema>();
53
+ * const { data: brands } = await client.models.Brand.list();
54
+ * ```
55
+ */
56
+ export function generateClient<
57
+ TSchema extends Record<string, unknown> = Record<string, unknown>,
58
+ >(): ReturnType<typeof generateDataClient<TSchema>> {
59
+ return generateDataClient<TSchema>();
60
+ }
61
+
62
+ /**
63
+ * Configuration for Amplify (matches amplify_outputs.json format)
64
+ */
65
+ export type AstroAmplifyConfig = ResourcesConfig;
66
+
67
+ /**
68
+ * Authentication mode for server-side GraphQL client
69
+ */
70
+ export type ServerAuthMode = 'userPool' | 'apiKey';
71
+
72
+ /**
73
+ * Options for generating a server-side GraphQL client
74
+ */
75
+ export interface GenerateServerClientOptions {
76
+ /** Authentication mode - 'userPool' (default) uses JWT from cookies, 'apiKey' uses API key */
77
+ authMode?: ServerAuthMode;
78
+ }
79
+
80
+ /**
81
+ * Generate a server-side GraphQL client for use within runWithAmplifyServerContext
82
+ *
83
+ * This function creates a GraphQL client that can be used for server-side data fetching in Astro.
84
+ * It MUST be called within runWithAmplifyServerContext to access JWT tokens from cookies.
85
+ *
86
+ * The client supports two authentication modes:
87
+ * - 'userPool' (default): Uses JWT tokens from cookies (requires runWithAmplifyServerContext)
88
+ * - 'apiKey': Uses API key for public/unauthenticated requests
89
+ *
90
+ * **Important**:
91
+ * - Amplify.configure() must be called once at app startup (e.g., in amplify-server.ts)
92
+ * - This function must be called INSIDE the operation function of runWithAmplifyServerContext
93
+ * - The context automatically provides the token provider that reads JWT tokens from cookies
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * // In your Astro page
98
+ * import type { Schema } from '../amplify/data/resource';
99
+ * import { generateServerClient } from '@htlkg/data/client';
100
+ * import { createRunWithAmplifyServerContext } from '@htlkg/core/amplify-astro-adapter';
101
+ * import outputs from '../amplify_outputs.json';
102
+ *
103
+ * const runWithAmplifyServerContext = createRunWithAmplifyServerContext({ config: outputs });
104
+ *
105
+ * // Fetch data with authentication
106
+ * const result = await runWithAmplifyServerContext({
107
+ * astroServerContext: {
108
+ * cookies: Astro.cookies,
109
+ * request: Astro.request
110
+ * },
111
+ * operation: async (contextSpec) => {
112
+ * // Generate client INSIDE the operation
113
+ * const client = generateServerClient<Schema>({ authMode: 'userPool' });
114
+ * return await client.models.User.list();
115
+ * }
116
+ * });
117
+ *
118
+ * const users = result.data || [];
119
+ * ```
120
+ *
121
+ * @example Using API key for public data
122
+ * ```typescript
123
+ * const result = await runWithAmplifyServerContext({
124
+ * astroServerContext: {
125
+ * cookies: Astro.cookies,
126
+ * request: Astro.request
127
+ * },
128
+ * operation: async (contextSpec) => {
129
+ * const client = generateServerClient<Schema>({ authMode: 'apiKey' });
130
+ * return await client.models.Brand.list();
131
+ * }
132
+ * });
133
+ * ```
134
+ */
135
+ export function generateServerClient<
136
+ TSchema extends Record<string, unknown> = Record<string, unknown>,
137
+ >(options?: GenerateServerClientOptions): ReturnType<typeof generateDataClient<TSchema>> {
138
+ // Generate the client without authMode parameter
139
+ // When called within runWithAmplifyServerContext, it will automatically use the token provider
140
+ // from the context (which reads JWT tokens from cookies)
141
+ // The authMode should be specified per-operation, not at client creation
142
+ const client = generateDataClient<TSchema>();
143
+
144
+ return client;
145
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Server-side data client for Astro
3
+ *
4
+ * Provides a client generator similar to Next.js's generateServerClientUsingCookies
5
+ * using generateClientWithAmplifyInstance for proper server context integration.
6
+ */
7
+
8
+ import type { AstroGlobal } from "astro";
9
+ import type { ResourcesConfig } from "aws-amplify";
10
+ import {
11
+ CommonPublicClientOptions,
12
+ DefaultCommonClientOptions,
13
+ V6ClientSSRCookies,
14
+ generateClientWithAmplifyInstance,
15
+ } from "aws-amplify/api/internals";
16
+ import { getAmplifyServerContext } from "aws-amplify/adapter-core/internals";
17
+ import { createRunWithAmplifyServerContext, createLogger } from "@htlkg/core/amplify-astro-adapter";
18
+
19
+ const log = createLogger('server-client');
20
+
21
+ interface AstroCookiesClientParams {
22
+ cookies: AstroGlobal["cookies"];
23
+ request: AstroGlobal["request"];
24
+ config: ResourcesConfig;
25
+ }
26
+
27
+ /**
28
+ * Generates a server-side data client for Astro (matches Next.js implementation)
29
+ *
30
+ * This function creates a client that automatically wraps all operations in the Amplify server context,
31
+ * ensuring that authentication tokens from cookies are properly used.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * import type { Schema } from '../amplify/data/resource';
36
+ * import { generateServerClientUsingCookies } from '@htlkg/data/client';
37
+ * import { parseAmplifyConfig } from 'aws-amplify/utils';
38
+ * import outputs from '../amplify_outputs.json';
39
+ *
40
+ * const amplifyConfig = parseAmplifyConfig(outputs);
41
+ *
42
+ * const client = generateServerClientUsingCookies<Schema>({
43
+ * config: amplifyConfig,
44
+ * cookies: Astro.cookies,
45
+ * request: Astro.request,
46
+ * });
47
+ *
48
+ * // Use the client directly - operations are automatically wrapped
49
+ * const result = await client.models.User.list({
50
+ * selectionSet: ['id', 'email'],
51
+ * limit: 100,
52
+ * });
53
+ * ```
54
+ */
55
+ export function generateServerClientUsingCookies<
56
+ T extends Record<any, any> = never,
57
+ Options extends CommonPublicClientOptions &
58
+ AstroCookiesClientParams = DefaultCommonClientOptions &
59
+ AstroCookiesClientParams,
60
+ >(options: Options): V6ClientSSRCookies<T, Options> {
61
+ const runWithAmplifyServerContext = createRunWithAmplifyServerContext({
62
+ config: options.config,
63
+ });
64
+
65
+ const resourcesConfig = options.config;
66
+
67
+ // This function reference gets passed down to InternalGraphQLAPI.ts.graphql
68
+ // where this._graphql is passed in as the `fn` argument
69
+ // causing it to always get invoked inside `runWithAmplifyServerContext`
70
+ const getAmplify = (fn: (amplify: any) => Promise<any>) => {
71
+ return runWithAmplifyServerContext({
72
+ astroServerContext: {
73
+ cookies: options.cookies,
74
+ request: options.request,
75
+ },
76
+ operation: async (contextSpec: any) => {
77
+ const amplifyInstance = getAmplifyServerContext(contextSpec).amplify;
78
+
79
+ // Debug logging (only when DEBUG=true)
80
+ try {
81
+ const config = amplifyInstance.getConfig();
82
+ log.debug('Amplify config from instance:', {
83
+ hasAPI: !!config.API,
84
+ hasGraphQL: !!config.API?.GraphQL,
85
+ endpoint: config.API?.GraphQL?.endpoint,
86
+ defaultAuthMode: config.API?.GraphQL?.defaultAuthMode,
87
+ region: config.API?.GraphQL?.region,
88
+ });
89
+
90
+ const session = await amplifyInstance.Auth.fetchAuthSession();
91
+ log.debug('Auth session:', {
92
+ hasTokens: !!session.tokens,
93
+ hasAccessToken: !!session.tokens?.accessToken,
94
+ hasIdToken: !!session.tokens?.idToken,
95
+ hasCredentials: !!session.credentials,
96
+ });
97
+ } catch (e: any) {
98
+ log.debug('Error fetching session:', e.message);
99
+ }
100
+
101
+ return fn(amplifyInstance);
102
+ },
103
+ });
104
+ };
105
+
106
+ const {
107
+ cookies: _cookies,
108
+ request: _request,
109
+ config: _config,
110
+ ...params
111
+ } = options;
112
+
113
+ return generateClientWithAmplifyInstance<T, V6ClientSSRCookies<T, Options>>({
114
+ amplify: getAmplify,
115
+ config: resourcesConfig,
116
+ ...params,
117
+ } as any);
118
+ }
@@ -0,0 +1,87 @@
1
+ # Content Collections Module
2
+
3
+ Astro content collection generators and schema definitions for static content.
4
+
5
+ ## Installation
6
+
7
+ ```typescript
8
+ import {
9
+ generateCollections,
10
+ syncCollections,
11
+ contentSchemas,
12
+ } from '@htlkg/data/content-collections';
13
+ ```
14
+
15
+ ## Overview
16
+
17
+ This module provides utilities for generating Astro content collections from external data sources, enabling static site generation with dynamic content.
18
+
19
+ ## Schemas
20
+
21
+ Pre-defined Zod schemas for content types:
22
+
23
+ ```typescript
24
+ import { contentSchemas } from '@htlkg/data/content-collections';
25
+
26
+ // Brand content schema
27
+ const brandSchema = contentSchemas.brand;
28
+
29
+ // Product content schema
30
+ const productSchema = contentSchemas.product;
31
+
32
+ // Documentation schema
33
+ const docSchema = contentSchemas.doc;
34
+ ```
35
+
36
+ ## Generator
37
+
38
+ Generate content collection files from API data:
39
+
40
+ ```typescript
41
+ import { generateCollections } from '@htlkg/data/content-collections';
42
+
43
+ await generateCollections({
44
+ outputDir: './src/content',
45
+ collections: ['brands', 'products'],
46
+ client: amplifyClient,
47
+ });
48
+ ```
49
+
50
+ ## Sync
51
+
52
+ Synchronize content collections with remote data:
53
+
54
+ ```typescript
55
+ import { syncCollections } from '@htlkg/data/content-collections';
56
+
57
+ // In a build script or CI
58
+ await syncCollections({
59
+ collections: ['brands'],
60
+ force: true, // Overwrite existing
61
+ });
62
+ ```
63
+
64
+ ## Usage in Astro
65
+
66
+ ```typescript
67
+ // src/content/config.ts
68
+ import { defineCollection } from 'astro:content';
69
+ import { contentSchemas } from '@htlkg/data/content-collections';
70
+
71
+ export const collections = {
72
+ brands: defineCollection({
73
+ type: 'data',
74
+ schema: contentSchemas.brand,
75
+ }),
76
+ };
77
+ ```
78
+
79
+ ```astro
80
+ ---
81
+ // src/pages/brands/[id].astro
82
+ import { getCollection, getEntry } from 'astro:content';
83
+
84
+ const brands = await getCollection('brands');
85
+ const brand = await getEntry('brands', Astro.params.id);
86
+ ---
87
+ ```