@htlkg/data 0.0.14 → 0.0.15

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.
@@ -0,0 +1,280 @@
1
+ /**
2
+ * ProductInstance Mutation Functions
3
+ *
4
+ * Provides mutation functions for creating, updating, and deleting product instances.
5
+ * Product instances represent enabled products for a specific brand with their configuration.
6
+ */
7
+
8
+ import type { ProductInstance } from "@htlkg/core/types";
9
+ import { getClientUser } from "@htlkg/core/auth";
10
+ import { getCurrentTimestamp } from "@htlkg/core/utils";
11
+ import { AppError } from "@htlkg/core/errors";
12
+
13
+ /**
14
+ * Get current user identifier for audit trails
15
+ * Uses getClientUser() and returns email or username, falling back to "system"
16
+ */
17
+ async function getUserIdentifier(fallback = "system"): Promise<string> {
18
+ try {
19
+ const user = await getClientUser();
20
+ if (user) {
21
+ return user.email || user.username || fallback;
22
+ }
23
+ return fallback;
24
+ } catch {
25
+ return fallback;
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Input type for creating a product instance
31
+ */
32
+ export interface CreateProductInstanceInput {
33
+ productId: string;
34
+ brandId: string;
35
+ accountId: string;
36
+ productName: string;
37
+ enabled: boolean;
38
+ config?: Record<string, any>;
39
+ version?: string;
40
+ lastUpdated?: string;
41
+ updatedBy?: string;
42
+ }
43
+
44
+ /**
45
+ * Input type for updating a product instance
46
+ */
47
+ export interface UpdateProductInstanceInput {
48
+ id: string;
49
+ enabled?: boolean;
50
+ config?: Record<string, any>;
51
+ version?: string;
52
+ lastUpdated?: string;
53
+ updatedBy?: string;
54
+ }
55
+
56
+ /**
57
+ * Create a new product instance
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * import { createProductInstance } from '@htlkg/data/mutations';
62
+ * import { generateClient } from '@htlkg/data/client';
63
+ *
64
+ * const client = generateClient<Schema>();
65
+ * const instance = await createProductInstance(client, {
66
+ * productId: 'product-123',
67
+ * brandId: 'brand-456',
68
+ * accountId: 'account-789',
69
+ * enabled: true,
70
+ * config: { apiKey: 'xxx', maxRequests: 100 }
71
+ * });
72
+ * ```
73
+ */
74
+ export async function createProductInstance<TClient = any>(
75
+ client: TClient,
76
+ input: CreateProductInstanceInput,
77
+ ): Promise<ProductInstance | null> {
78
+ try {
79
+ // Build input - manually construct to avoid Vue Proxy issues
80
+ const createInput: any = {
81
+ productId: input.productId,
82
+ productName: input.productName,
83
+ brandId: input.brandId,
84
+ accountId: input.accountId,
85
+ enabled: input.enabled,
86
+ version: input.version,
87
+ lastUpdated: input.lastUpdated || getCurrentTimestamp(),
88
+ updatedBy: input.updatedBy || await getUserIdentifier(),
89
+ };
90
+
91
+ // AWSJSON type requires JSON STRING
92
+ if (input.config) {
93
+ // Double stringify: first to strip Vue Proxy, second to create JSON string
94
+ createInput.config = JSON.stringify(JSON.parse(JSON.stringify(input.config)));
95
+ }
96
+
97
+ console.log("[createProductInstance] Config as string:", createInput.config);
98
+ console.log("[createProductInstance] Config type:", typeof createInput.config);
99
+
100
+ const { data, errors } = await (client as any).models.ProductInstance.create(createInput);
101
+
102
+ if (errors) {
103
+ console.error("[createProductInstance] GraphQL errors:", errors);
104
+ throw new AppError(
105
+ "Failed to create product instance",
106
+ "PRODUCT_INSTANCE_CREATE_ERROR",
107
+ 500,
108
+ { errors }
109
+ );
110
+ }
111
+
112
+ return data as ProductInstance;
113
+ } catch (error) {
114
+ console.error("[createProductInstance] Error creating product instance:", error);
115
+ if (error instanceof AppError) {
116
+ throw error;
117
+ }
118
+ throw new AppError(
119
+ "Failed to create product instance",
120
+ "PRODUCT_INSTANCE_CREATE_ERROR",
121
+ 500,
122
+ { originalError: error }
123
+ );
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Update an existing product instance
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * import { updateProductInstance } from '@htlkg/data/mutations';
133
+ * import { generateClient } from '@htlkg/data/client';
134
+ *
135
+ * const client = generateClient<Schema>();
136
+ * const instance = await updateProductInstance(client, {
137
+ * id: 'instance-123',
138
+ * enabled: false,
139
+ * config: { apiKey: 'new-key', maxRequests: 200 }
140
+ * });
141
+ * ```
142
+ */
143
+ export async function updateProductInstance<TClient = any>(
144
+ client: TClient,
145
+ input: UpdateProductInstanceInput,
146
+ ): Promise<ProductInstance | null> {
147
+ try {
148
+ // Add timestamp and user metadata if not provided
149
+ // Convert config from Vue Proxy to plain object
150
+ const updateInput: any = {
151
+ ...input,
152
+ lastUpdated: input.lastUpdated || getCurrentTimestamp(),
153
+ updatedBy: input.updatedBy || await getUserIdentifier(),
154
+ };
155
+
156
+ // AWSJSON type requires JSON STRING
157
+ if (input.config) {
158
+ updateInput.config = JSON.stringify(JSON.parse(JSON.stringify(input.config)));
159
+ }
160
+
161
+ const { data, errors } = await (client as any).models.ProductInstance.update(updateInput);
162
+
163
+ if (errors) {
164
+ console.error("[updateProductInstance] GraphQL errors:", errors);
165
+ throw new AppError(
166
+ "Failed to update product instance",
167
+ "PRODUCT_INSTANCE_UPDATE_ERROR",
168
+ 500,
169
+ { errors }
170
+ );
171
+ }
172
+
173
+ return data as ProductInstance;
174
+ } catch (error) {
175
+ console.error("[updateProductInstance] Error updating product instance:", error);
176
+ if (error instanceof AppError) {
177
+ throw error;
178
+ }
179
+ throw new AppError(
180
+ "Failed to update product instance",
181
+ "PRODUCT_INSTANCE_UPDATE_ERROR",
182
+ 500,
183
+ { originalError: error }
184
+ );
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Delete a product instance
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * import { deleteProductInstance } from '@htlkg/data/mutations';
194
+ * import { generateClient } from '@htlkg/data/client';
195
+ *
196
+ * const client = generateClient<Schema>();
197
+ * await deleteProductInstance(client, 'instance-123');
198
+ * ```
199
+ */
200
+ export async function deleteProductInstance<TClient = any>(
201
+ client: TClient,
202
+ id: string,
203
+ ): Promise<boolean> {
204
+ try {
205
+ const { errors } = await (client as any).models.ProductInstance.delete({ id });
206
+
207
+ if (errors) {
208
+ console.error("[deleteProductInstance] GraphQL errors:", errors);
209
+ throw new AppError(
210
+ "Failed to delete product instance",
211
+ "PRODUCT_INSTANCE_DELETE_ERROR",
212
+ 500,
213
+ { errors }
214
+ );
215
+ }
216
+
217
+ return true;
218
+ } catch (error) {
219
+ console.error("[deleteProductInstance] Error deleting product instance:", error);
220
+ if (error instanceof AppError) {
221
+ throw error;
222
+ }
223
+ throw new AppError(
224
+ "Failed to delete product instance",
225
+ "PRODUCT_INSTANCE_DELETE_ERROR",
226
+ 500,
227
+ { originalError: error }
228
+ );
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Toggle the enabled status of a product instance
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * import { toggleProductInstanceEnabled } from '@htlkg/data/mutations';
238
+ * import { generateClient } from '@htlkg/data/client';
239
+ *
240
+ * const client = generateClient<Schema>();
241
+ * const instance = await toggleProductInstanceEnabled(client, 'instance-123', true);
242
+ * ```
243
+ */
244
+ export async function toggleProductInstanceEnabled<TClient = any>(
245
+ client: TClient,
246
+ id: string,
247
+ enabled: boolean,
248
+ ): Promise<ProductInstance | null> {
249
+ try {
250
+ const { data, errors } = await (client as any).models.ProductInstance.update({
251
+ id,
252
+ enabled,
253
+ lastUpdated: getCurrentTimestamp(),
254
+ updatedBy: await getUserIdentifier(),
255
+ });
256
+
257
+ if (errors) {
258
+ console.error("[toggleProductInstanceEnabled] GraphQL errors:", errors);
259
+ throw new AppError(
260
+ "Failed to toggle product instance",
261
+ "PRODUCT_INSTANCE_TOGGLE_ERROR",
262
+ 500,
263
+ { errors }
264
+ );
265
+ }
266
+
267
+ return data as ProductInstance;
268
+ } catch (error) {
269
+ console.error("[toggleProductInstanceEnabled] Error toggling product instance:", error);
270
+ if (error instanceof AppError) {
271
+ throw error;
272
+ }
273
+ throw new AppError(
274
+ "Failed to toggle product instance",
275
+ "PRODUCT_INSTANCE_TOGGLE_ERROR",
276
+ 500,
277
+ { originalError: error }
278
+ );
279
+ }
280
+ }