@htlkg/data 0.0.2 → 0.0.9
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.
- package/README.md +53 -0
- package/dist/client/index.d.ts +16 -1
- package/dist/client/index.js +13 -1
- package/dist/client/index.js.map +1 -1
- package/dist/hooks/index.d.ts +113 -5
- package/dist/hooks/index.js +155 -164
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +263 -161
- package/dist/index.js.map +1 -1
- package/dist/queries/index.js.map +1 -1
- package/dist/stores/index.d.ts +106 -0
- package/dist/stores/index.js +108 -0
- package/dist/stores/index.js.map +1 -0
- package/package.json +64 -37
- package/src/client/__tests__/server.test.ts +106 -0
- package/src/client/client.md +91 -0
- package/src/client/index.test.ts +198 -0
- package/src/client/index.ts +145 -0
- package/src/client/server.ts +118 -0
- package/src/content-collections/content-collections.md +87 -0
- package/src/content-collections/generator.ts +314 -0
- package/src/content-collections/index.ts +32 -0
- package/src/content-collections/schemas.ts +75 -0
- package/src/content-collections/sync.ts +139 -0
- package/src/hooks/README.md +293 -0
- package/src/hooks/createDataHook.ts +208 -0
- package/src/hooks/data-hook-errors.property.test.ts +270 -0
- package/src/hooks/data-hook-filters.property.test.ts +263 -0
- package/src/hooks/data-hooks.property.test.ts +190 -0
- package/src/hooks/hooks.test.ts +76 -0
- package/src/hooks/index.ts +21 -0
- package/src/hooks/useAccounts.ts +66 -0
- package/src/hooks/useBrands.ts +95 -0
- package/src/hooks/useProducts.ts +88 -0
- package/src/hooks/useUsers.ts +89 -0
- package/src/index.ts +32 -0
- package/src/mutations/accounts.ts +127 -0
- package/src/mutations/brands.ts +133 -0
- package/src/mutations/index.ts +32 -0
- package/src/mutations/mutations.md +96 -0
- package/src/mutations/users.ts +136 -0
- package/src/queries/accounts.ts +121 -0
- package/src/queries/brands.ts +176 -0
- package/src/queries/index.ts +45 -0
- package/src/queries/products.ts +282 -0
- package/src/queries/queries.md +88 -0
- package/src/queries/server-helpers.ts +114 -0
- package/src/queries/users.ts +199 -0
- package/src/stores/createStores.ts +148 -0
- package/src/stores/index.ts +15 -0
- package/src/stores/stores.md +104 -0
|
@@ -0,0 +1,198 @@
|
|
|
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
|
+
createLogger: vi.fn(() => ({
|
|
41
|
+
debug: vi.fn(),
|
|
42
|
+
info: vi.fn(),
|
|
43
|
+
warn: vi.fn(),
|
|
44
|
+
error: vi.fn(),
|
|
45
|
+
})),
|
|
46
|
+
}));
|
|
47
|
+
|
|
48
|
+
// Mock aws-amplify/auth/server
|
|
49
|
+
vi.mock('aws-amplify/auth/server', () => ({
|
|
50
|
+
fetchAuthSession: vi.fn()
|
|
51
|
+
}));
|
|
52
|
+
|
|
53
|
+
// Import after mocks are set up
|
|
54
|
+
import { generateClient, generateServerClient } from './index';
|
|
55
|
+
import { Amplify } from 'aws-amplify';
|
|
56
|
+
import { generateClient as generateDataClient } from 'aws-amplify/data';
|
|
57
|
+
import { createRunWithAmplifyServerContext } from '@htlkg/core/amplify-astro-adapter';
|
|
58
|
+
|
|
59
|
+
describe('generateClient', () => {
|
|
60
|
+
it('should generate a client-side GraphQL client', () => {
|
|
61
|
+
const client = generateClient();
|
|
62
|
+
|
|
63
|
+
expect(client).toBeDefined();
|
|
64
|
+
expect(client.models).toBeDefined();
|
|
65
|
+
expect(client.models.Brand).toBeDefined();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should return a client with model operations', () => {
|
|
69
|
+
const client = generateClient();
|
|
70
|
+
|
|
71
|
+
expect(client.models.Brand.list).toBeDefined();
|
|
72
|
+
expect(client.models.Brand.get).toBeDefined();
|
|
73
|
+
expect(client.models.Brand.create).toBeDefined();
|
|
74
|
+
expect(client.models.Brand.update).toBeDefined();
|
|
75
|
+
expect(client.models.Brand.delete).toBeDefined();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should be callable multiple times', () => {
|
|
79
|
+
const client1 = generateClient();
|
|
80
|
+
const client2 = generateClient();
|
|
81
|
+
|
|
82
|
+
expect(client1).toBeDefined();
|
|
83
|
+
expect(client2).toBeDefined();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('generateServerClient', () => {
|
|
88
|
+
let mockConfig: any;
|
|
89
|
+
|
|
90
|
+
beforeEach(() => {
|
|
91
|
+
// Mock Amplify config
|
|
92
|
+
mockConfig = {
|
|
93
|
+
auth: {
|
|
94
|
+
user_pool_id: 'test-pool',
|
|
95
|
+
aws_region: 'us-east-1',
|
|
96
|
+
user_pool_client_id: 'test-client'
|
|
97
|
+
},
|
|
98
|
+
data: {
|
|
99
|
+
url: 'https://test.appsync-api.us-east-1.amazonaws.com/graphql',
|
|
100
|
+
aws_region: 'us-east-1',
|
|
101
|
+
api_key: 'test-api-key',
|
|
102
|
+
default_authorization_type: 'AMAZON_COGNITO_USER_POOLS',
|
|
103
|
+
authorization_types: ['API_KEY', 'AWS_IAM']
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
afterEach(() => {
|
|
109
|
+
vi.clearAllMocks();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe('basic functionality', () => {
|
|
113
|
+
it('should generate a server-side client', () => {
|
|
114
|
+
const client = generateServerClient();
|
|
115
|
+
|
|
116
|
+
expect(client).toBeDefined();
|
|
117
|
+
expect(client.models).toBeDefined();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should call generateDataClient without options', () => {
|
|
121
|
+
generateServerClient();
|
|
122
|
+
|
|
123
|
+
// generateServerClient calls generateDataClient without parameters
|
|
124
|
+
// authMode is specified per-operation, not at client creation
|
|
125
|
+
expect(generateDataClient).toHaveBeenCalled();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should not call Amplify.configure (should be done at app startup)', () => {
|
|
129
|
+
vi.clearAllMocks();
|
|
130
|
+
|
|
131
|
+
generateServerClient();
|
|
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
|
+
|
|
143
|
+
// generateServerClient should NOT call createRunWithAmplifyServerContext
|
|
144
|
+
// The caller should wrap the operation with runWithAmplifyServerContext
|
|
145
|
+
expect(createRunWithAmplifyServerContext).not.toHaveBeenCalled();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('with options', () => {
|
|
150
|
+
it('should accept authMode option', () => {
|
|
151
|
+
const client = generateServerClient({
|
|
152
|
+
authMode: 'apiKey'
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
expect(client).toBeDefined();
|
|
156
|
+
expect(client.models).toBeDefined();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should accept userPool authMode option', () => {
|
|
160
|
+
const client = generateServerClient({
|
|
161
|
+
authMode: 'userPool'
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
expect(client).toBeDefined();
|
|
165
|
+
expect(client.models).toBeDefined();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('multiple instances', () => {
|
|
170
|
+
it('should allow creating multiple server clients', () => {
|
|
171
|
+
const client1 = generateServerClient({
|
|
172
|
+
authMode: 'userPool'
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const client2 = generateServerClient({
|
|
176
|
+
authMode: 'apiKey'
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
expect(client1).toBeDefined();
|
|
180
|
+
expect(client2).toBeDefined();
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('type exports', () => {
|
|
186
|
+
it('should export AstroAmplifyConfig type', () => {
|
|
187
|
+
// This is a compile-time check, but we can verify the import works
|
|
188
|
+
const config: any = {
|
|
189
|
+
auth: {
|
|
190
|
+
user_pool_id: 'test',
|
|
191
|
+
aws_region: 'us-east-1',
|
|
192
|
+
user_pool_client_id: 'test'
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
expect(config).toBeDefined();
|
|
197
|
+
});
|
|
198
|
+
});
|
|
@@ -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
|
+
```
|