@htlkg/data 0.0.14 → 0.0.16
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 +72 -0
- package/dist/client/index.d.ts +123 -30
- package/dist/client/index.js +75 -1
- package/dist/client/index.js.map +1 -1
- package/dist/hooks/index.d.ts +76 -2
- package/dist/hooks/index.js +224 -6
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +550 -7
- package/dist/index.js.map +1 -1
- package/dist/mutations/index.d.ts +149 -5
- package/dist/mutations/index.js +397 -0
- package/dist/mutations/index.js.map +1 -1
- package/dist/productInstances-CzT3NZKU.d.ts +98 -0
- package/dist/queries/index.d.ts +54 -2
- package/dist/queries/index.js +60 -1
- package/dist/queries/index.js.map +1 -1
- package/dist/server/index.d.ts +47 -0
- package/dist/server/index.js +59 -0
- package/dist/server/index.js.map +1 -0
- package/package.json +5 -1
- package/src/client/index.ts +82 -3
- package/src/client/proxy.ts +170 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useProductInstances.ts +174 -0
- package/src/index.ts +11 -0
- package/src/mutations/accounts.ts +102 -1
- package/src/mutations/brands.ts +102 -1
- package/src/mutations/index.ts +23 -0
- package/src/mutations/productInstances/index.ts +14 -0
- package/src/mutations/productInstances/productInstances.integration.test.ts +621 -0
- package/src/mutations/productInstances/productInstances.test.ts +680 -0
- package/src/mutations/productInstances/productInstances.ts +280 -0
- package/src/mutations/systemSettings.ts +130 -0
- package/src/mutations/users.ts +102 -1
- package/src/queries/index.ts +9 -0
- package/src/queries/systemSettings.ts +115 -0
package/README.md
CHANGED
|
@@ -30,6 +30,39 @@ Astro content collection generators and schema definitions.
|
|
|
30
30
|
|
|
31
31
|
## Quick Start
|
|
32
32
|
|
|
33
|
+
### Server-Side (Astro Pages) - Zero Config (Recommended)
|
|
34
|
+
|
|
35
|
+
When using `@htlkg/astro` integration, the Amplify client is **automatically injected** into `Astro.locals.amplifyClient` by the auth middleware. No imports, no config needed:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
---
|
|
39
|
+
// In any Astro page (.astro file)
|
|
40
|
+
export const prerender = false;
|
|
41
|
+
|
|
42
|
+
// Just use it - no imports needed for client setup!
|
|
43
|
+
const { amplifyClient } = Astro.locals;
|
|
44
|
+
|
|
45
|
+
// Fetch data directly
|
|
46
|
+
const { data: users } = await amplifyClient.models.User.list({
|
|
47
|
+
selectionSet: ['id', 'email', 'status'],
|
|
48
|
+
authMode: 'userPool',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const { data: brands } = await amplifyClient.models.Brand.list();
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
<ul>
|
|
55
|
+
{users?.map(user => <li>{user.email}</li>)}
|
|
56
|
+
</ul>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Requirements:**
|
|
60
|
+
- Must use `@htlkg/astro` integration with `vueAppSetup: 'full'`
|
|
61
|
+
- User must be authenticated (client is only available when `Astro.locals.user` exists)
|
|
62
|
+
- Page must have `export const prerender = false` (SSR mode)
|
|
63
|
+
|
|
64
|
+
### Client-Side (Vue Components)
|
|
65
|
+
|
|
33
66
|
```typescript
|
|
34
67
|
// Client-side data fetching
|
|
35
68
|
import { getSharedClient } from '@htlkg/data/client';
|
|
@@ -51,3 +84,42 @@ import { fetchBrands, fetchAccounts } from '@htlkg/data/queries';
|
|
|
51
84
|
|
|
52
85
|
const brands = await fetchBrands(client, { accountId });
|
|
53
86
|
```
|
|
87
|
+
|
|
88
|
+
## Migration Guide: From Manual Client to Zero-Config
|
|
89
|
+
|
|
90
|
+
### Before (Manual Setup)
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
---
|
|
94
|
+
import { generateServerClientUsingCookies } from "@htlkg/data/client";
|
|
95
|
+
import { parseAmplifyConfig } from "aws-amplify/utils";
|
|
96
|
+
import type { Schema } from "@backend/data/resource";
|
|
97
|
+
import { amplifyOutputs } from "@/lib/amplify-config";
|
|
98
|
+
|
|
99
|
+
const amplifyConfig = parseAmplifyConfig(amplifyOutputs);
|
|
100
|
+
const client = generateServerClientUsingCookies<Schema>({
|
|
101
|
+
config: amplifyConfig,
|
|
102
|
+
cookies: Astro.cookies,
|
|
103
|
+
request: Astro.request,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const { data } = await client.models.User.list();
|
|
107
|
+
---
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### After (Zero-Config)
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
---
|
|
114
|
+
const { amplifyClient } = Astro.locals;
|
|
115
|
+
|
|
116
|
+
const { data } = await amplifyClient.models.User.list();
|
|
117
|
+
---
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Benefits:**
|
|
121
|
+
- No imports needed for client setup
|
|
122
|
+
- No config parsing
|
|
123
|
+
- No manual parameter passing
|
|
124
|
+
- Type-safe with full IntelliSense support
|
|
125
|
+
- Client is automatically scoped to the authenticated user
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,57 +1,119 @@
|
|
|
1
1
|
import { generateClient as generateClient$1 } from 'aws-amplify/data';
|
|
2
2
|
import { ResourcesConfig } from 'aws-amplify';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { generateServerClientUsingCookies } from '../server/index.js';
|
|
4
|
+
import 'astro';
|
|
5
|
+
import 'aws-amplify/api/internals';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
+
* GraphQL Proxy Client
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* Client-side helper for making authenticated GraphQL operations through
|
|
11
|
+
* the server-side proxy. This allows Vue components to perform mutations
|
|
12
|
+
* while keeping auth cookies httpOnly for security.
|
|
13
|
+
*
|
|
14
|
+
* @module @htlkg/data/proxy
|
|
11
15
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Valid GraphQL operations
|
|
18
|
+
*/
|
|
19
|
+
type Operation = "create" | "update" | "delete" | "get" | "list";
|
|
20
|
+
/**
|
|
21
|
+
* Response type from GraphQL operations
|
|
22
|
+
*/
|
|
23
|
+
interface GraphQLResponse<T = any> {
|
|
24
|
+
data: T | null;
|
|
25
|
+
errors?: Array<{
|
|
26
|
+
message: string;
|
|
27
|
+
[key: string]: any;
|
|
28
|
+
}>;
|
|
17
29
|
}
|
|
18
30
|
/**
|
|
19
|
-
*
|
|
31
|
+
* Options for proxy requests
|
|
32
|
+
*/
|
|
33
|
+
interface ProxyOptions {
|
|
34
|
+
/** Custom API endpoint (default: /api/graphql) */
|
|
35
|
+
endpoint?: string;
|
|
36
|
+
/** Additional fetch options */
|
|
37
|
+
fetchOptions?: RequestInit;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Execute a GraphQL mutation through the server proxy
|
|
20
41
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
42
|
+
* @param model - The model name (e.g., 'User', 'Brand', 'Account')
|
|
43
|
+
* @param operation - The operation type ('create', 'update', 'delete')
|
|
44
|
+
* @param data - The operation data/input
|
|
45
|
+
* @param options - Optional configuration
|
|
46
|
+
* @returns Promise with the operation result
|
|
23
47
|
*
|
|
24
|
-
* @example
|
|
48
|
+
* @example Create
|
|
25
49
|
* ```typescript
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* const amplifyConfig = parseAmplifyConfig(outputs);
|
|
50
|
+
* const result = await mutate('User', 'create', {
|
|
51
|
+
* email: 'user@example.com',
|
|
52
|
+
* accountId: '123',
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
32
55
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
56
|
+
* @example Update
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const result = await mutate('User', 'update', {
|
|
59
|
+
* id: 'user-id',
|
|
60
|
+
* status: 'deleted',
|
|
61
|
+
* deletedAt: new Date().toISOString(),
|
|
37
62
|
* });
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @example Delete
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const result = await mutate('User', 'delete', { id: 'user-id' });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
declare function mutate<T = any>(model: string, operation: "create" | "update" | "delete", data: Record<string, any>, options?: ProxyOptions): Promise<GraphQLResponse<T>>;
|
|
71
|
+
/**
|
|
72
|
+
* Execute a GraphQL query through the server proxy
|
|
73
|
+
*
|
|
74
|
+
* @param model - The model name (e.g., 'User', 'Brand', 'Account')
|
|
75
|
+
* @param operation - The operation type ('get', 'list')
|
|
76
|
+
* @param data - The query parameters (id for get, filter/limit for list)
|
|
77
|
+
* @param options - Optional configuration
|
|
78
|
+
* @returns Promise with the query result
|
|
38
79
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
80
|
+
* @example Get by ID
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const result = await query('User', 'get', { id: 'user-id' });
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @example List with filter
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const result = await query('User', 'list', {
|
|
88
|
+
* filter: { status: { eq: 'active' } },
|
|
42
89
|
* limit: 100,
|
|
43
90
|
* });
|
|
44
91
|
* ```
|
|
45
92
|
*/
|
|
46
|
-
declare function
|
|
93
|
+
declare function query<T = any>(model: string, operation: "get" | "list", data?: Record<string, any>, options?: ProxyOptions): Promise<GraphQLResponse<T>>;
|
|
94
|
+
/**
|
|
95
|
+
* Helper to check if a response has errors
|
|
96
|
+
*/
|
|
97
|
+
declare function hasErrors(response: GraphQLResponse): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Helper to get the first error message from a response
|
|
100
|
+
*/
|
|
101
|
+
declare function getErrorMessage(response: GraphQLResponse): string | null;
|
|
47
102
|
|
|
48
103
|
/**
|
|
49
104
|
* GraphQL Client for @htlkg/data
|
|
50
105
|
*
|
|
51
106
|
* Provides both client-side and server-side GraphQL capabilities using AWS Amplify Data.
|
|
52
107
|
* The server-side functions use the Amplify Astro adapter for proper SSR support.
|
|
108
|
+
*
|
|
109
|
+
* For server-side usage, use `Astro.locals.amplifyClient` (zero-config, injected by middleware).
|
|
53
110
|
*/
|
|
54
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Type for the server-side Amplify client (for use in type declarations)
|
|
114
|
+
* This represents the client returned by generateServerClientUsingCookies
|
|
115
|
+
*/
|
|
116
|
+
type AmplifyServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>> = ReturnType<typeof generateServerClientUsingCookies<TSchema>>;
|
|
55
117
|
/**
|
|
56
118
|
* Get or create the shared GraphQL client instance (singleton pattern)
|
|
57
119
|
* Use this for client-side fetching to avoid creating multiple client instances.
|
|
@@ -151,6 +213,37 @@ interface GenerateServerClientOptions {
|
|
|
151
213
|
* });
|
|
152
214
|
* ```
|
|
153
215
|
*/
|
|
154
|
-
declare function generateServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>>(
|
|
216
|
+
declare function generateServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>>(_options?: GenerateServerClientOptions): ReturnType<typeof generateClient$1<TSchema>>;
|
|
217
|
+
/**
|
|
218
|
+
* Context required for getting a server client in API routes
|
|
219
|
+
*/
|
|
220
|
+
interface ServerClientContext {
|
|
221
|
+
locals: {
|
|
222
|
+
amplifyClient?: any;
|
|
223
|
+
user?: any;
|
|
224
|
+
};
|
|
225
|
+
cookies: any;
|
|
226
|
+
request: Request;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get the server client from Astro context
|
|
230
|
+
*
|
|
231
|
+
* Uses locals.amplifyClient if available (set by middleware),
|
|
232
|
+
* otherwise creates a new client using Amplify's global config.
|
|
233
|
+
* No config parameter needed - uses the config set by the middleware.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```typescript
|
|
237
|
+
* import { getServerClient } from '@htlkg/data/client';
|
|
238
|
+
*
|
|
239
|
+
* export const POST: APIRoute = async (context) => {
|
|
240
|
+
* const client = getServerClient(context);
|
|
241
|
+
* if (!client) return new Response('Not authenticated', { status: 401 });
|
|
242
|
+
*
|
|
243
|
+
* const result = await client.models.User.list();
|
|
244
|
+
* };
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
declare function getServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>>(context: ServerClientContext): ReturnType<typeof generateServerClientUsingCookies<TSchema>> | null;
|
|
155
248
|
|
|
156
|
-
export { type AstroAmplifyConfig, type GenerateServerClientOptions, type ServerAuthMode, generateClient, generateServerClient, generateServerClientUsingCookies, getSharedClient, resetSharedClient };
|
|
249
|
+
export { type AmplifyServerClient, type AstroAmplifyConfig, type GenerateServerClientOptions, type GraphQLResponse, type Operation, type ProxyOptions, type ServerAuthMode, type ServerClientContext, generateClient, generateServerClient, generateServerClientUsingCookies, getErrorMessage, getServerClient, getSharedClient, hasErrors, mutate, query, resetSharedClient };
|
package/dist/client/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/client/index.ts
|
|
2
2
|
import { generateClient as generateDataClient } from "aws-amplify/data";
|
|
3
|
+
import { Amplify } from "aws-amplify";
|
|
3
4
|
|
|
4
5
|
// src/client/server.ts
|
|
5
6
|
import {
|
|
@@ -57,6 +58,54 @@ function generateServerClientUsingCookies(options) {
|
|
|
57
58
|
});
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
// src/client/proxy.ts
|
|
62
|
+
var DEFAULT_ENDPOINT = "/api/graphql";
|
|
63
|
+
async function mutate(model, operation, data, options) {
|
|
64
|
+
return proxyRequest(model, operation, data, options);
|
|
65
|
+
}
|
|
66
|
+
async function query(model, operation, data, options) {
|
|
67
|
+
return proxyRequest(model, operation, data, options);
|
|
68
|
+
}
|
|
69
|
+
async function proxyRequest(model, operation, data, options) {
|
|
70
|
+
const endpoint = options?.endpoint ?? DEFAULT_ENDPOINT;
|
|
71
|
+
try {
|
|
72
|
+
const response = await fetch(endpoint, {
|
|
73
|
+
method: "POST",
|
|
74
|
+
headers: {
|
|
75
|
+
"Content-Type": "application/json"
|
|
76
|
+
},
|
|
77
|
+
credentials: "include",
|
|
78
|
+
// Important: include cookies
|
|
79
|
+
...options?.fetchOptions,
|
|
80
|
+
body: JSON.stringify({ model, operation, data })
|
|
81
|
+
});
|
|
82
|
+
const result = await response.json();
|
|
83
|
+
if (response.status === 401) {
|
|
84
|
+
console.error("[GraphQL Proxy] Unauthorized - session may have expired");
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error("[GraphQL Proxy] Request failed:", error);
|
|
89
|
+
return {
|
|
90
|
+
data: null,
|
|
91
|
+
errors: [
|
|
92
|
+
{
|
|
93
|
+
message: error instanceof Error ? error.message : "Network error"
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function hasErrors(response) {
|
|
100
|
+
return !!response.errors && response.errors.length > 0;
|
|
101
|
+
}
|
|
102
|
+
function getErrorMessage(response) {
|
|
103
|
+
if (!response.errors || response.errors.length === 0) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return response.errors[0].message;
|
|
107
|
+
}
|
|
108
|
+
|
|
60
109
|
// src/client/index.ts
|
|
61
110
|
var sharedClientInstance = null;
|
|
62
111
|
function getSharedClient() {
|
|
@@ -71,15 +120,40 @@ function resetSharedClient() {
|
|
|
71
120
|
function generateClient() {
|
|
72
121
|
return generateDataClient();
|
|
73
122
|
}
|
|
74
|
-
function generateServerClient(
|
|
123
|
+
function generateServerClient(_options) {
|
|
75
124
|
const client = generateDataClient();
|
|
76
125
|
return client;
|
|
77
126
|
}
|
|
127
|
+
function getServerClient(context) {
|
|
128
|
+
if (context.locals.amplifyClient) {
|
|
129
|
+
return context.locals.amplifyClient;
|
|
130
|
+
}
|
|
131
|
+
if (context.locals.user) {
|
|
132
|
+
try {
|
|
133
|
+
const amplifyConfig = Amplify.getConfig();
|
|
134
|
+
if (amplifyConfig) {
|
|
135
|
+
return generateServerClientUsingCookies({
|
|
136
|
+
config: amplifyConfig,
|
|
137
|
+
cookies: context.cookies,
|
|
138
|
+
request: context.request
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
} catch (e) {
|
|
142
|
+
console.error("[getServerClient] Failed to get Amplify config:", e);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
78
147
|
export {
|
|
79
148
|
generateClient,
|
|
80
149
|
generateServerClient,
|
|
81
150
|
generateServerClientUsingCookies,
|
|
151
|
+
getErrorMessage,
|
|
152
|
+
getServerClient,
|
|
82
153
|
getSharedClient,
|
|
154
|
+
hasErrors,
|
|
155
|
+
mutate,
|
|
156
|
+
query,
|
|
83
157
|
resetSharedClient
|
|
84
158
|
};
|
|
85
159
|
//# sourceMappingURL=index.js.map
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/index.ts","../../src/client/server.ts"],"sourcesContent":["/**\n * GraphQL Client for @htlkg/data\n *\n * Provides both client-side and server-side GraphQL capabilities using AWS Amplify Data.\n * The server-side functions use the Amplify Astro adapter for proper SSR support.\n */\n\nimport { generateClient as generateDataClient } from \"aws-amplify/data\";\nimport type { ResourcesConfig } from \"aws-amplify\";\n\n// Re-export server-side client generation\nexport { generateServerClientUsingCookies } from \"./server\";\n\n// Singleton client instance for client-side fetching\nlet sharedClientInstance: any = null;\n\n/**\n * Get or create the shared GraphQL client instance (singleton pattern)\n * Use this for client-side fetching to avoid creating multiple client instances.\n *\n * @example\n * ```typescript\n * const client = getSharedClient<Schema>();\n * const { data } = await client.models.Account.list();\n * ```\n */\nexport function getSharedClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(): ReturnType<typeof generateDataClient<TSchema>> {\n\tif (!sharedClientInstance) {\n\t\tsharedClientInstance = generateDataClient<TSchema>();\n\t}\n\treturn sharedClientInstance;\n}\n\n/**\n * Reset the shared client instance (useful for testing or auth state changes)\n */\nexport function resetSharedClient(): void {\n\tsharedClientInstance = null;\n}\n\n/**\n * Generate a client-side GraphQL client for use in Vue components and browser contexts\n * This is SSR-safe and should be called within a component's setup function or after hydration\n *\n * @example\n * ```typescript\n * import type { Schema } from '@backend/data/resource';\n * import { generateClient } from '@htlkg/data/client';\n *\n * const client = generateClient<Schema>();\n * const { data: brands } = await client.models.Brand.list();\n * ```\n */\nexport function generateClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(): ReturnType<typeof generateDataClient<TSchema>> {\n\treturn generateDataClient<TSchema>();\n}\n\n/**\n * Configuration for Amplify (matches amplify_outputs.json format)\n */\nexport type AstroAmplifyConfig = ResourcesConfig;\n\n/**\n * Authentication mode for server-side GraphQL client\n */\nexport type ServerAuthMode = 'userPool' | 'apiKey';\n\n/**\n * Options for generating a server-side GraphQL client\n */\nexport interface GenerateServerClientOptions {\n\t/** Authentication mode - 'userPool' (default) uses JWT from cookies, 'apiKey' uses API key */\n\tauthMode?: ServerAuthMode;\n}\n\n/**\n * Generate a server-side GraphQL client for use within runWithAmplifyServerContext\n * \n * This function creates a GraphQL client that can be used for server-side data fetching in Astro.\n * It MUST be called within runWithAmplifyServerContext to access JWT tokens from cookies.\n * \n * The client supports two authentication modes:\n * - 'userPool' (default): Uses JWT tokens from cookies (requires runWithAmplifyServerContext)\n * - 'apiKey': Uses API key for public/unauthenticated requests\n *\n * **Important**: \n * - Amplify.configure() must be called once at app startup (e.g., in amplify-server.ts)\n * - This function must be called INSIDE the operation function of runWithAmplifyServerContext\n * - The context automatically provides the token provider that reads JWT tokens from cookies\n *\n * @example\n * ```typescript\n * // In your Astro page\n * import type { Schema } from '../amplify/data/resource';\n * import { generateServerClient } from '@htlkg/data/client';\n * import { createRunWithAmplifyServerContext } from '@htlkg/core/amplify-astro-adapter';\n * import outputs from '../amplify_outputs.json';\n *\n * const runWithAmplifyServerContext = createRunWithAmplifyServerContext({ config: outputs });\n *\n * // Fetch data with authentication\n * const result = await runWithAmplifyServerContext({\n * astroServerContext: {\n * cookies: Astro.cookies,\n * request: Astro.request\n * },\n * operation: async (contextSpec) => {\n * // Generate client INSIDE the operation\n * const client = generateServerClient<Schema>({ authMode: 'userPool' });\n * return await client.models.User.list();\n * }\n * });\n * \n * const users = result.data || [];\n * ```\n * \n * @example Using API key for public data\n * ```typescript\n * const result = await runWithAmplifyServerContext({\n * astroServerContext: {\n * cookies: Astro.cookies,\n * request: Astro.request\n * },\n * operation: async (contextSpec) => {\n * const client = generateServerClient<Schema>({ authMode: 'apiKey' });\n * return await client.models.Brand.list();\n * }\n * });\n * ```\n */\nexport function generateServerClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(options?: GenerateServerClientOptions): ReturnType<typeof generateDataClient<TSchema>> {\n\t// Generate the client without authMode parameter\n\t// When called within runWithAmplifyServerContext, it will automatically use the token provider\n\t// from the context (which reads JWT tokens from cookies)\n\t// The authMode should be specified per-operation, not at client creation\n\tconst client = generateDataClient<TSchema>();\n\t\n\treturn client;\n}\n","/**\n * Server-side data client for Astro\n *\n * Provides a client generator similar to Next.js's generateServerClientUsingCookies\n * using generateClientWithAmplifyInstance for proper server context integration.\n */\n\nimport type { AstroGlobal } from \"astro\";\nimport type { ResourcesConfig } from \"aws-amplify\";\nimport {\n\tCommonPublicClientOptions,\n\tDefaultCommonClientOptions,\n\tV6ClientSSRCookies,\n\tgenerateClientWithAmplifyInstance,\n} from \"aws-amplify/api/internals\";\nimport { getAmplifyServerContext } from \"aws-amplify/adapter-core/internals\";\nimport { createRunWithAmplifyServerContext, createLogger } from \"@htlkg/core/amplify-astro-adapter\";\n\nconst log = createLogger('server-client');\n\ninterface AstroCookiesClientParams {\n\tcookies: AstroGlobal[\"cookies\"];\n\trequest: AstroGlobal[\"request\"];\n\tconfig: ResourcesConfig;\n}\n\n/**\n * Generates a server-side data client for Astro (matches Next.js implementation)\n *\n * This function creates a client that automatically wraps all operations in the Amplify server context,\n * ensuring that authentication tokens from cookies are properly used.\n *\n * @example\n * ```typescript\n * import type { Schema } from '../amplify/data/resource';\n * import { generateServerClientUsingCookies } from '@htlkg/data/client';\n * import { parseAmplifyConfig } from 'aws-amplify/utils';\n * import outputs from '../amplify_outputs.json';\n *\n * const amplifyConfig = parseAmplifyConfig(outputs);\n *\n * const client = generateServerClientUsingCookies<Schema>({\n * config: amplifyConfig,\n * cookies: Astro.cookies,\n * request: Astro.request,\n * });\n *\n * // Use the client directly - operations are automatically wrapped\n * const result = await client.models.User.list({\n * selectionSet: ['id', 'email'],\n * limit: 100,\n * });\n * ```\n */\nexport function generateServerClientUsingCookies<\n\tT extends Record<any, any> = never,\n\tOptions extends CommonPublicClientOptions &\n\t\tAstroCookiesClientParams = DefaultCommonClientOptions &\n\t\tAstroCookiesClientParams,\n>(options: Options): V6ClientSSRCookies<T, Options> {\n\tconst runWithAmplifyServerContext = createRunWithAmplifyServerContext({\n\t\tconfig: options.config,\n\t});\n\n\tconst resourcesConfig = options.config;\n\n\t// This function reference gets passed down to InternalGraphQLAPI.ts.graphql\n\t// where this._graphql is passed in as the `fn` argument\n\t// causing it to always get invoked inside `runWithAmplifyServerContext`\n\tconst getAmplify = (fn: (amplify: any) => Promise<any>) => {\n\t\treturn runWithAmplifyServerContext({\n\t\t\tastroServerContext: {\n\t\t\t\tcookies: options.cookies,\n\t\t\t\trequest: options.request,\n\t\t\t},\n\t\t\toperation: async (contextSpec: any) => {\n\t\t\t\tconst amplifyInstance = getAmplifyServerContext(contextSpec).amplify;\n\t\t\t\t\n\t\t\t\t// Debug logging (only when DEBUG=true)\n\t\t\t\ttry {\n\t\t\t\t\tconst config = amplifyInstance.getConfig();\n\t\t\t\t\tlog.debug('Amplify config from instance:', {\n\t\t\t\t\t\thasAPI: !!config.API,\n\t\t\t\t\t\thasGraphQL: !!config.API?.GraphQL,\n\t\t\t\t\t\tendpoint: config.API?.GraphQL?.endpoint,\n\t\t\t\t\t\tdefaultAuthMode: config.API?.GraphQL?.defaultAuthMode,\n\t\t\t\t\t\tregion: config.API?.GraphQL?.region,\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tconst session = await amplifyInstance.Auth.fetchAuthSession();\n\t\t\t\t\tlog.debug('Auth session:', {\n\t\t\t\t\t\thasTokens: !!session.tokens,\n\t\t\t\t\t\thasAccessToken: !!session.tokens?.accessToken,\n\t\t\t\t\t\thasIdToken: !!session.tokens?.idToken,\n\t\t\t\t\t\thasCredentials: !!session.credentials,\n\t\t\t\t\t});\n\t\t\t\t} catch (e: any) {\n\t\t\t\t\tlog.debug('Error fetching session:', e.message);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn fn(amplifyInstance);\n\t\t\t},\n\t\t});\n\t};\n\n\tconst {\n\t\tcookies: _cookies,\n\t\trequest: _request,\n\t\tconfig: _config,\n\t\t...params\n\t} = options;\n\n\treturn generateClientWithAmplifyInstance<T, V6ClientSSRCookies<T, Options>>({\n\t\tamplify: getAmplify,\n\t\tconfig: resourcesConfig,\n\t\t...params,\n\t} as any);\n}\n"],"mappings":";AAOA,SAAS,kBAAkB,0BAA0B;;;ACErD;AAAA,EAIC;AAAA,OACM;AACP,SAAS,+BAA+B;AACxC,SAAS,mCAAmC,oBAAoB;AAEhE,IAAM,MAAM,aAAa,eAAe;AAoCjC,SAAS,iCAKd,SAAkD;AACnD,QAAM,8BAA8B,kCAAkC;AAAA,IACrE,QAAQ,QAAQ;AAAA,EACjB,CAAC;AAED,QAAM,kBAAkB,QAAQ;AAKhC,QAAM,aAAa,CAAC,OAAuC;AAC1D,WAAO,4BAA4B;AAAA,MAClC,oBAAoB;AAAA,QACnB,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,MAClB;AAAA,MACA,WAAW,OAAO,gBAAqB;AACtC,cAAM,kBAAkB,wBAAwB,WAAW,EAAE;AAG7D,YAAI;AACH,gBAAM,SAAS,gBAAgB,UAAU;AACzC,cAAI,MAAM,iCAAiC;AAAA,YAC1C,QAAQ,CAAC,CAAC,OAAO;AAAA,YACjB,YAAY,CAAC,CAAC,OAAO,KAAK;AAAA,YAC1B,UAAU,OAAO,KAAK,SAAS;AAAA,YAC/B,iBAAiB,OAAO,KAAK,SAAS;AAAA,YACtC,QAAQ,OAAO,KAAK,SAAS;AAAA,UAC9B,CAAC;AAED,gBAAM,UAAU,MAAM,gBAAgB,KAAK,iBAAiB;AAC5D,cAAI,MAAM,iBAAiB;AAAA,YAC1B,WAAW,CAAC,CAAC,QAAQ;AAAA,YACrB,gBAAgB,CAAC,CAAC,QAAQ,QAAQ;AAAA,YAClC,YAAY,CAAC,CAAC,QAAQ,QAAQ;AAAA,YAC9B,gBAAgB,CAAC,CAAC,QAAQ;AAAA,UAC3B,CAAC;AAAA,QACF,SAAS,GAAQ;AAChB,cAAI,MAAM,2BAA2B,EAAE,OAAO;AAAA,QAC/C;AAEA,eAAO,GAAG,eAAe;AAAA,MAC1B;AAAA,IACD,CAAC;AAAA,EACF;AAEA,QAAM;AAAA,IACL,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,GAAG;AAAA,EACJ,IAAI;AAEJ,SAAO,kCAAqE;AAAA,IAC3E,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,GAAG;AAAA,EACJ,CAAQ;AACT;;;ADvGA,IAAI,uBAA4B;AAYzB,SAAS,kBAEoC;AACnD,MAAI,CAAC,sBAAsB;AAC1B,2BAAuB,mBAA4B;AAAA,EACpD;AACA,SAAO;AACR;AAKO,SAAS,oBAA0B;AACzC,yBAAuB;AACxB;AAeO,SAAS,iBAEoC;AACnD,SAAO,mBAA4B;AACpC;AA2EO,SAAS,qBAEd,SAAuF;AAKxF,QAAM,SAAS,mBAA4B;AAE3C,SAAO;AACR;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/index.ts","../../src/client/server.ts","../../src/client/proxy.ts"],"sourcesContent":["/**\n * GraphQL Client for @htlkg/data\n *\n * Provides both client-side and server-side GraphQL capabilities using AWS Amplify Data.\n * The server-side functions use the Amplify Astro adapter for proper SSR support.\n *\n * For server-side usage, use `Astro.locals.amplifyClient` (zero-config, injected by middleware).\n */\n\nimport { generateClient as generateDataClient } from \"aws-amplify/data\";\nimport { Amplify } from \"aws-amplify\";\nimport type { ResourcesConfig } from \"aws-amplify\";\nimport { generateServerClientUsingCookies } from \"./server\";\n\n// Re-export server-side client generation (used internally by middleware)\nexport { generateServerClientUsingCookies } from \"./server\";\n\n// Re-export proxy functions for authenticated client-side operations\nexport {\n\tmutate,\n\tquery,\n\thasErrors,\n\tgetErrorMessage,\n\ttype Operation,\n\ttype GraphQLResponse,\n\ttype ProxyOptions,\n} from \"./proxy\";\n\n/**\n * Type for the server-side Amplify client (for use in type declarations)\n * This represents the client returned by generateServerClientUsingCookies\n */\nexport type AmplifyServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>> =\n\tReturnType<typeof generateServerClientUsingCookies<TSchema>>;\n\n// Singleton client instance for client-side fetching\nlet sharedClientInstance: any = null;\n\n/**\n * Get or create the shared GraphQL client instance (singleton pattern)\n * Use this for client-side fetching to avoid creating multiple client instances.\n *\n * @example\n * ```typescript\n * const client = getSharedClient<Schema>();\n * const { data } = await client.models.Account.list();\n * ```\n */\nexport function getSharedClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(): ReturnType<typeof generateDataClient<TSchema>> {\n\tif (!sharedClientInstance) {\n\t\tsharedClientInstance = generateDataClient<TSchema>();\n\t}\n\treturn sharedClientInstance;\n}\n\n/**\n * Reset the shared client instance (useful for testing or auth state changes)\n */\nexport function resetSharedClient(): void {\n\tsharedClientInstance = null;\n}\n\n/**\n * Generate a client-side GraphQL client for use in Vue components and browser contexts\n * This is SSR-safe and should be called within a component's setup function or after hydration\n *\n * @example\n * ```typescript\n * import type { Schema } from '@backend/data/resource';\n * import { generateClient } from '@htlkg/data/client';\n *\n * const client = generateClient<Schema>();\n * const { data: brands } = await client.models.Brand.list();\n * ```\n */\nexport function generateClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(): ReturnType<typeof generateDataClient<TSchema>> {\n\treturn generateDataClient<TSchema>();\n}\n\n/**\n * Configuration for Amplify (matches amplify_outputs.json format)\n */\nexport type AstroAmplifyConfig = ResourcesConfig;\n\n/**\n * Authentication mode for server-side GraphQL client\n */\nexport type ServerAuthMode = 'userPool' | 'apiKey';\n\n/**\n * Options for generating a server-side GraphQL client\n */\nexport interface GenerateServerClientOptions {\n\t/** Authentication mode - 'userPool' (default) uses JWT from cookies, 'apiKey' uses API key */\n\tauthMode?: ServerAuthMode;\n}\n\n/**\n * Generate a server-side GraphQL client for use within runWithAmplifyServerContext\n * \n * This function creates a GraphQL client that can be used for server-side data fetching in Astro.\n * It MUST be called within runWithAmplifyServerContext to access JWT tokens from cookies.\n * \n * The client supports two authentication modes:\n * - 'userPool' (default): Uses JWT tokens from cookies (requires runWithAmplifyServerContext)\n * - 'apiKey': Uses API key for public/unauthenticated requests\n *\n * **Important**: \n * - Amplify.configure() must be called once at app startup (e.g., in amplify-server.ts)\n * - This function must be called INSIDE the operation function of runWithAmplifyServerContext\n * - The context automatically provides the token provider that reads JWT tokens from cookies\n *\n * @example\n * ```typescript\n * // In your Astro page\n * import type { Schema } from '../amplify/data/resource';\n * import { generateServerClient } from '@htlkg/data/client';\n * import { createRunWithAmplifyServerContext } from '@htlkg/core/amplify-astro-adapter';\n * import outputs from '../amplify_outputs.json';\n *\n * const runWithAmplifyServerContext = createRunWithAmplifyServerContext({ config: outputs });\n *\n * // Fetch data with authentication\n * const result = await runWithAmplifyServerContext({\n * astroServerContext: {\n * cookies: Astro.cookies,\n * request: Astro.request\n * },\n * operation: async (contextSpec) => {\n * // Generate client INSIDE the operation\n * const client = generateServerClient<Schema>({ authMode: 'userPool' });\n * return await client.models.User.list();\n * }\n * });\n * \n * const users = result.data || [];\n * ```\n * \n * @example Using API key for public data\n * ```typescript\n * const result = await runWithAmplifyServerContext({\n * astroServerContext: {\n * cookies: Astro.cookies,\n * request: Astro.request\n * },\n * operation: async (contextSpec) => {\n * const client = generateServerClient<Schema>({ authMode: 'apiKey' });\n * return await client.models.Brand.list();\n * }\n * });\n * ```\n */\nexport function generateServerClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(_options?: GenerateServerClientOptions): ReturnType<typeof generateDataClient<TSchema>> {\n\t// Generate the client without authMode parameter\n\t// When called within runWithAmplifyServerContext, it will automatically use the token provider\n\t// from the context (which reads JWT tokens from cookies)\n\t// The authMode should be specified per-operation, not at client creation\n\tconst client = generateDataClient<TSchema>();\n\n\treturn client;\n}\n\n/**\n * Context required for getting a server client in API routes\n */\nexport interface ServerClientContext {\n\tlocals: { amplifyClient?: any; user?: any };\n\tcookies: any;\n\trequest: Request;\n}\n\n/**\n * Get the server client from Astro context\n *\n * Uses locals.amplifyClient if available (set by middleware),\n * otherwise creates a new client using Amplify's global config.\n * No config parameter needed - uses the config set by the middleware.\n *\n * @example\n * ```typescript\n * import { getServerClient } from '@htlkg/data/client';\n *\n * export const POST: APIRoute = async (context) => {\n * const client = getServerClient(context);\n * if (!client) return new Response('Not authenticated', { status: 401 });\n *\n * const result = await client.models.User.list();\n * };\n * ```\n */\nexport function getServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>>(\n\tcontext: ServerClientContext,\n): ReturnType<typeof generateServerClientUsingCookies<TSchema>> | null {\n\t// Try to use client from middleware first\n\tif (context.locals.amplifyClient) {\n\t\treturn context.locals.amplifyClient as ReturnType<typeof generateServerClientUsingCookies<TSchema>>;\n\t}\n\n\t// If no client from middleware and user is authenticated, create one using global Amplify config\n\tif (context.locals.user) {\n\t\ttry {\n\t\t\t// Get config from Amplify (set by middleware)\n\t\t\tconst amplifyConfig = Amplify.getConfig();\n\t\t\tif (amplifyConfig) {\n\t\t\t\treturn generateServerClientUsingCookies<TSchema>({\n\t\t\t\t\tconfig: amplifyConfig,\n\t\t\t\t\tcookies: context.cookies,\n\t\t\t\t\trequest: context.request,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.error('[getServerClient] Failed to get Amplify config:', e);\n\t\t}\n\t}\n\n\t// No authentication available\n\treturn null;\n}\n","/**\n * Server-side data client for Astro\n *\n * Provides a client generator similar to Next.js's generateServerClientUsingCookies\n * using generateClientWithAmplifyInstance for proper server context integration.\n */\n\nimport type { AstroGlobal } from \"astro\";\nimport type { ResourcesConfig } from \"aws-amplify\";\nimport {\n\tCommonPublicClientOptions,\n\tDefaultCommonClientOptions,\n\tV6ClientSSRCookies,\n\tgenerateClientWithAmplifyInstance,\n} from \"aws-amplify/api/internals\";\nimport { getAmplifyServerContext } from \"aws-amplify/adapter-core/internals\";\nimport { createRunWithAmplifyServerContext, createLogger } from \"@htlkg/core/amplify-astro-adapter\";\n\nconst log = createLogger('server-client');\n\ninterface AstroCookiesClientParams {\n\tcookies: AstroGlobal[\"cookies\"];\n\trequest: AstroGlobal[\"request\"];\n\tconfig: ResourcesConfig;\n}\n\n/**\n * Generates a server-side data client for Astro (matches Next.js implementation)\n *\n * This function creates a client that automatically wraps all operations in the Amplify server context,\n * ensuring that authentication tokens from cookies are properly used.\n *\n * @example\n * ```typescript\n * import type { Schema } from '../amplify/data/resource';\n * import { generateServerClientUsingCookies } from '@htlkg/data/client';\n * import { parseAmplifyConfig } from 'aws-amplify/utils';\n * import outputs from '../amplify_outputs.json';\n *\n * const amplifyConfig = parseAmplifyConfig(outputs);\n *\n * const client = generateServerClientUsingCookies<Schema>({\n * config: amplifyConfig,\n * cookies: Astro.cookies,\n * request: Astro.request,\n * });\n *\n * // Use the client directly - operations are automatically wrapped\n * const result = await client.models.User.list({\n * selectionSet: ['id', 'email'],\n * limit: 100,\n * });\n * ```\n */\nexport function generateServerClientUsingCookies<\n\tT extends Record<any, any> = never,\n\tOptions extends CommonPublicClientOptions &\n\t\tAstroCookiesClientParams = DefaultCommonClientOptions &\n\t\tAstroCookiesClientParams,\n>(options: Options): V6ClientSSRCookies<T, Options> {\n\tconst runWithAmplifyServerContext = createRunWithAmplifyServerContext({\n\t\tconfig: options.config,\n\t});\n\n\tconst resourcesConfig = options.config;\n\n\t// This function reference gets passed down to InternalGraphQLAPI.ts.graphql\n\t// where this._graphql is passed in as the `fn` argument\n\t// causing it to always get invoked inside `runWithAmplifyServerContext`\n\tconst getAmplify = (fn: (amplify: any) => Promise<any>) => {\n\t\treturn runWithAmplifyServerContext({\n\t\t\tastroServerContext: {\n\t\t\t\tcookies: options.cookies,\n\t\t\t\trequest: options.request,\n\t\t\t},\n\t\t\toperation: async (contextSpec: any) => {\n\t\t\t\tconst amplifyInstance = getAmplifyServerContext(contextSpec).amplify;\n\t\t\t\t\n\t\t\t\t// Debug logging (only when DEBUG=true)\n\t\t\t\ttry {\n\t\t\t\t\tconst config = amplifyInstance.getConfig();\n\t\t\t\t\tlog.debug('Amplify config from instance:', {\n\t\t\t\t\t\thasAPI: !!config.API,\n\t\t\t\t\t\thasGraphQL: !!config.API?.GraphQL,\n\t\t\t\t\t\tendpoint: config.API?.GraphQL?.endpoint,\n\t\t\t\t\t\tdefaultAuthMode: config.API?.GraphQL?.defaultAuthMode,\n\t\t\t\t\t\tregion: config.API?.GraphQL?.region,\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tconst session = await amplifyInstance.Auth.fetchAuthSession();\n\t\t\t\t\tlog.debug('Auth session:', {\n\t\t\t\t\t\thasTokens: !!session.tokens,\n\t\t\t\t\t\thasAccessToken: !!session.tokens?.accessToken,\n\t\t\t\t\t\thasIdToken: !!session.tokens?.idToken,\n\t\t\t\t\t\thasCredentials: !!session.credentials,\n\t\t\t\t\t});\n\t\t\t\t} catch (e: any) {\n\t\t\t\t\tlog.debug('Error fetching session:', e.message);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn fn(amplifyInstance);\n\t\t\t},\n\t\t});\n\t};\n\n\tconst {\n\t\tcookies: _cookies,\n\t\trequest: _request,\n\t\tconfig: _config,\n\t\t...params\n\t} = options;\n\n\treturn generateClientWithAmplifyInstance<T, V6ClientSSRCookies<T, Options>>({\n\t\tamplify: getAmplify,\n\t\tconfig: resourcesConfig,\n\t\t...params,\n\t} as any);\n}\n","/**\n * GraphQL Proxy Client\n *\n * Client-side helper for making authenticated GraphQL operations through\n * the server-side proxy. This allows Vue components to perform mutations\n * while keeping auth cookies httpOnly for security.\n *\n * @module @htlkg/data/proxy\n */\n\n/**\n * Valid GraphQL operations\n */\nexport type Operation = \"create\" | \"update\" | \"delete\" | \"get\" | \"list\";\n\n/**\n * Response type from GraphQL operations\n */\nexport interface GraphQLResponse<T = any> {\n\tdata: T | null;\n\terrors?: Array<{ message: string; [key: string]: any }>;\n}\n\n/**\n * Options for proxy requests\n */\nexport interface ProxyOptions {\n\t/** Custom API endpoint (default: /api/graphql) */\n\tendpoint?: string;\n\t/** Additional fetch options */\n\tfetchOptions?: RequestInit;\n}\n\n/**\n * Default proxy endpoint\n */\nconst DEFAULT_ENDPOINT = \"/api/graphql\";\n\n/**\n * Execute a GraphQL mutation through the server proxy\n *\n * @param model - The model name (e.g., 'User', 'Brand', 'Account')\n * @param operation - The operation type ('create', 'update', 'delete')\n * @param data - The operation data/input\n * @param options - Optional configuration\n * @returns Promise with the operation result\n *\n * @example Create\n * ```typescript\n * const result = await mutate('User', 'create', {\n * email: 'user@example.com',\n * accountId: '123',\n * });\n * ```\n *\n * @example Update\n * ```typescript\n * const result = await mutate('User', 'update', {\n * id: 'user-id',\n * status: 'deleted',\n * deletedAt: new Date().toISOString(),\n * });\n * ```\n *\n * @example Delete\n * ```typescript\n * const result = await mutate('User', 'delete', { id: 'user-id' });\n * ```\n */\nexport async function mutate<T = any>(\n\tmodel: string,\n\toperation: \"create\" | \"update\" | \"delete\",\n\tdata: Record<string, any>,\n\toptions?: ProxyOptions,\n): Promise<GraphQLResponse<T>> {\n\treturn proxyRequest<T>(model, operation, data, options);\n}\n\n/**\n * Execute a GraphQL query through the server proxy\n *\n * @param model - The model name (e.g., 'User', 'Brand', 'Account')\n * @param operation - The operation type ('get', 'list')\n * @param data - The query parameters (id for get, filter/limit for list)\n * @param options - Optional configuration\n * @returns Promise with the query result\n *\n * @example Get by ID\n * ```typescript\n * const result = await query('User', 'get', { id: 'user-id' });\n * ```\n *\n * @example List with filter\n * ```typescript\n * const result = await query('User', 'list', {\n * filter: { status: { eq: 'active' } },\n * limit: 100,\n * });\n * ```\n */\nexport async function query<T = any>(\n\tmodel: string,\n\toperation: \"get\" | \"list\",\n\tdata?: Record<string, any>,\n\toptions?: ProxyOptions,\n): Promise<GraphQLResponse<T>> {\n\treturn proxyRequest<T>(model, operation, data, options);\n}\n\n/**\n * Internal function to make proxy requests\n */\nasync function proxyRequest<T>(\n\tmodel: string,\n\toperation: Operation,\n\tdata?: Record<string, any>,\n\toptions?: ProxyOptions,\n): Promise<GraphQLResponse<T>> {\n\tconst endpoint = options?.endpoint ?? DEFAULT_ENDPOINT;\n\n\ttry {\n\t\tconst response = await fetch(endpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tcredentials: \"include\", // Important: include cookies\n\t\t\t...options?.fetchOptions,\n\t\t\tbody: JSON.stringify({ model, operation, data }),\n\t\t});\n\n\t\tconst result: GraphQLResponse<T> = await response.json();\n\n\t\t// Handle auth errors\n\t\tif (response.status === 401) {\n\t\t\tconsole.error(\"[GraphQL Proxy] Unauthorized - session may have expired\");\n\t\t\t// Optionally trigger a redirect to login\n\t\t\t// window.location.href = '/login';\n\t\t}\n\n\t\treturn result;\n\t} catch (error) {\n\t\tconsole.error(\"[GraphQL Proxy] Request failed:\", error);\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terrors: [\n\t\t\t\t{\n\t\t\t\t\tmessage: error instanceof Error ? error.message : \"Network error\",\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n}\n\n/**\n * Helper to check if a response has errors\n */\nexport function hasErrors(response: GraphQLResponse): boolean {\n\treturn !!response.errors && response.errors.length > 0;\n}\n\n/**\n * Helper to get the first error message from a response\n */\nexport function getErrorMessage(response: GraphQLResponse): string | null {\n\tif (!response.errors || response.errors.length === 0) {\n\t\treturn null;\n\t}\n\treturn response.errors[0].message;\n}\n"],"mappings":"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","names":[]}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Ref, ComputedRef } from 'vue';
|
|
2
|
-
import { Brand, Account, User, Product } from '@htlkg/core/types';
|
|
2
|
+
import { Brand, Account, User, Product, ProductInstance } from '@htlkg/core/types';
|
|
3
|
+
import { C as CreateProductInstanceInput, U as UpdateProductInstanceInput } from '../productInstances-CzT3NZKU.js';
|
|
3
4
|
export { resetSharedClient as resetClientInstance } from '../client/index.js';
|
|
4
5
|
import 'aws-amplify/data';
|
|
5
6
|
import 'aws-amplify';
|
|
7
|
+
import '../server/index.js';
|
|
6
8
|
import 'astro';
|
|
7
9
|
import 'aws-amplify/api/internals';
|
|
8
10
|
|
|
@@ -305,4 +307,76 @@ interface UseProductsReturn {
|
|
|
305
307
|
*/
|
|
306
308
|
declare function useProducts(options?: UseProductsOptions): UseProductsReturn;
|
|
307
309
|
|
|
308
|
-
|
|
310
|
+
/**
|
|
311
|
+
* useProductInstances Hook
|
|
312
|
+
*
|
|
313
|
+
* Vue composable for fetching and managing product instance data with reactive state.
|
|
314
|
+
* Provides loading states, error handling, refetch capabilities, and CRUD operations.
|
|
315
|
+
*/
|
|
316
|
+
|
|
317
|
+
interface UseProductInstancesOptions extends BaseHookOptions {
|
|
318
|
+
/** Filter criteria for product instances */
|
|
319
|
+
filter?: any;
|
|
320
|
+
/** Limit number of results */
|
|
321
|
+
limit?: number;
|
|
322
|
+
/** Auto-fetch on mount (default: true) */
|
|
323
|
+
autoFetch?: boolean;
|
|
324
|
+
/** Filter by brand ID */
|
|
325
|
+
brandId?: string;
|
|
326
|
+
/** Filter by account ID */
|
|
327
|
+
accountId?: string;
|
|
328
|
+
/** Filter by product ID */
|
|
329
|
+
productId?: string;
|
|
330
|
+
/** Only enabled instances */
|
|
331
|
+
enabledOnly?: boolean;
|
|
332
|
+
}
|
|
333
|
+
interface UseProductInstancesReturn {
|
|
334
|
+
/** Reactive array of product instances */
|
|
335
|
+
instances: Ref<ProductInstance[]>;
|
|
336
|
+
/** Computed array of enabled instances only */
|
|
337
|
+
enabledInstances: ComputedRef<ProductInstance[]>;
|
|
338
|
+
/** Loading state */
|
|
339
|
+
loading: Ref<boolean>;
|
|
340
|
+
/** Error state */
|
|
341
|
+
error: Ref<Error | null>;
|
|
342
|
+
/** Refetch product instances */
|
|
343
|
+
refetch: () => Promise<void>;
|
|
344
|
+
/** Create a new product instance */
|
|
345
|
+
createInstance: (input: CreateProductInstanceInput) => Promise<ProductInstance>;
|
|
346
|
+
/** Update an existing product instance */
|
|
347
|
+
updateInstance: (input: UpdateProductInstanceInput) => Promise<ProductInstance>;
|
|
348
|
+
/** Delete a product instance */
|
|
349
|
+
deleteInstance: (id: string) => Promise<boolean>;
|
|
350
|
+
/** Toggle the enabled status of a product instance */
|
|
351
|
+
toggleEnabled: (id: string, enabled: boolean) => Promise<ProductInstance>;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Composable for fetching and managing product instances
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```typescript
|
|
358
|
+
* import { useProductInstances } from '@htlkg/data/hooks';
|
|
359
|
+
*
|
|
360
|
+
* const { instances, loading, error, refetch } = useProductInstances();
|
|
361
|
+
* ```
|
|
362
|
+
*
|
|
363
|
+
* @example With filters
|
|
364
|
+
* ```typescript
|
|
365
|
+
* const { instances, enabledInstances, loading } = useProductInstances({
|
|
366
|
+
* brandId: 'brand-123',
|
|
367
|
+
* enabledOnly: true,
|
|
368
|
+
* limit: 50
|
|
369
|
+
* });
|
|
370
|
+
* ```
|
|
371
|
+
*
|
|
372
|
+
* @example For a specific account
|
|
373
|
+
* ```typescript
|
|
374
|
+
* const { instances, loading } = useProductInstances({
|
|
375
|
+
* accountId: 'account-456',
|
|
376
|
+
* autoFetch: true
|
|
377
|
+
* });
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
380
|
+
declare function useProductInstances(options?: UseProductInstancesOptions): UseProductInstancesReturn;
|
|
381
|
+
|
|
382
|
+
export { type BaseHookOptions, type CreateDataHookOptions, type DataHookReturn, type InferHookReturn, type UseAccountsOptions, type UseAccountsReturn, type UseBrandsOptions, type UseBrandsReturn, type UseProductInstancesOptions, type UseProductInstancesReturn, type UseProductsOptions, type UseProductsReturn, type UseUsersOptions, type UseUsersReturn, createDataHook, useAccounts, useBrands, useProductInstances, useProducts, useUsers };
|