@htlkg/data 0.0.23 → 0.0.25

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.
@@ -14,70 +14,16 @@ import {
14
14
  import { getContact } from "../queries/contacts";
15
15
  import type { CreateAuditFields, UpdateWithSoftDeleteFields } from "./common";
16
16
 
17
- // ============================================
18
- // Added Zod Validation Schemas
19
- // ============================================
20
-
21
- /**
22
- * Zod schema for creating a contact
23
- */
24
- export const createContactSchema = z.object({
25
- brandId: z.string().min(1, "Brand ID is required"),
26
- email: z.string().email("Invalid email address"),
27
- phone: z.string().optional(),
28
- firstName: z.string().min(1, "First name is required"),
29
- lastName: z.string().min(1, "Last name is required"),
30
- locale: z.string().optional(),
31
- gdprConsent: z.boolean(),
32
- gdprConsentDate: z.string().optional(),
33
- marketingOptIn: z.boolean().optional(),
34
- preferences: z.record(z.any()).optional(),
35
- tags: z.array(z.string()).optional(),
36
- totalVisits: z.number().int().min(0).optional(),
37
- lastVisitDate: z.string().optional(),
38
- firstVisitDate: z.string().optional(),
39
- legacyId: z.string().optional(),
40
- // Audit fields
41
- createdAt: z.string().optional(),
42
- createdBy: z.string().optional(),
43
- updatedAt: z.string().optional(),
44
- updatedBy: z.string().optional(),
45
- });
46
-
47
- /**
48
- * Zod schema for updating a contact
49
- */
50
- export const updateContactSchema = z.object({
51
- id: z.string().min(1, "Contact ID is required"),
52
- brandId: z.string().min(1).optional(),
53
- email: z.string().email("Invalid email address").optional(),
54
- phone: z.string().optional(),
55
- firstName: z.string().min(1).optional(),
56
- lastName: z.string().min(1).optional(),
57
- locale: z.string().optional(),
58
- gdprConsent: z.boolean().optional(),
59
- gdprConsentDate: z.string().optional(),
60
- marketingOptIn: z.boolean().optional(),
61
- preferences: z.record(z.any()).optional(),
62
- tags: z.array(z.string()).optional(),
63
- totalVisits: z.number().int().min(0).optional(),
64
- lastVisitDate: z.string().optional(),
65
- firstVisitDate: z.string().optional(),
66
- legacyId: z.string().optional(),
67
- // Audit fields
68
- updatedAt: z.string().optional(),
69
- updatedBy: z.string().optional(),
70
- deletedAt: z.string().nullable().optional(),
71
- deletedBy: z.string().nullable().optional(),
72
- });
17
+ // Import comprehensive validation schemas from validation module
18
+ import {
19
+ createContactSchema,
20
+ updateContactSchema,
21
+ mergeContactsSchema,
22
+ formatValidationErrors,
23
+ } from "../validation/contact.schemas";
73
24
 
74
- /**
75
- * Zod schema for merging contacts
76
- */
77
- export const mergeContactsSchema = z.object({
78
- primaryId: z.string().min(1, "Primary contact ID is required"),
79
- duplicateIds: z.array(z.string().min(1)).min(1, "At least one duplicate ID is required"),
80
- });
25
+ // Re-export validation schemas for backwards compatibility
26
+ export { createContactSchema, updateContactSchema, mergeContactsSchema };
81
27
 
82
28
  // ============================================
83
29
  // Validation Error Class
@@ -195,11 +141,8 @@ export async function createContact<TClient = any>(
195
141
  const validationResult = createContactSchema.safeParse(input);
196
142
 
197
143
  if (!validationResult.success) {
198
- const errorMessage = validationResult.error.issues
199
- .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
200
- .join(", ");
201
144
  throw new ContactValidationError(
202
- `Validation failed: ${errorMessage}`,
145
+ `Validation failed: ${formatValidationErrors(validationResult.error)}`,
203
146
  validationResult.error.issues
204
147
  );
205
148
  }
@@ -249,11 +192,8 @@ export async function updateContact<TClient = any>(
249
192
  const validationResult = updateContactSchema.safeParse(input);
250
193
 
251
194
  if (!validationResult.success) {
252
- const errorMessage = validationResult.error.issues
253
- .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
254
- .join(", ");
255
195
  throw new ContactValidationError(
256
- `Validation failed: ${errorMessage}`,
196
+ `Validation failed: ${formatValidationErrors(validationResult.error)}`,
257
197
  validationResult.error.issues
258
198
  );
259
199
  }
@@ -444,11 +384,8 @@ export async function mergeContacts<TClient = any>(
444
384
  const validationResult = mergeContactsSchema.safeParse(input);
445
385
 
446
386
  if (!validationResult.success) {
447
- const errorMessage = validationResult.error.issues
448
- .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
449
- .join(", ");
450
387
  throw new ContactValidationError(
451
- `Validation failed: ${errorMessage}`,
388
+ `Validation failed: ${formatValidationErrors(validationResult.error)}`,
452
389
  validationResult.error.issues
453
390
  );
454
391
  }
@@ -93,3 +93,4 @@ export {
93
93
  type MergeContactsInput,
94
94
  type MergeContactsResult,
95
95
  } from "./contacts";
96
+
@@ -0,0 +1,87 @@
1
+ /**
2
+ * ActivityLog Query Functions
3
+ *
4
+ * Provides query functions for fetching activity log data.
5
+ * ActivityLogs are immutable — no updates or deletes.
6
+ */
7
+
8
+ import type { ActivityLog } from "@htlkg/core/types";
9
+
10
+ /**
11
+ * List activity logs with optional filtering
12
+ */
13
+ export async function listActivityLogs<TClient = any>(
14
+ client: TClient,
15
+ options?: {
16
+ filter?: any;
17
+ limit?: number;
18
+ nextToken?: string;
19
+ },
20
+ ): Promise<{ items: ActivityLog[]; nextToken?: string }> {
21
+ try {
22
+ const { data, errors, nextToken } = await (
23
+ client as any
24
+ ).models.ActivityLog.list(options);
25
+
26
+ if (errors) {
27
+ console.error("[listActivityLogs] GraphQL errors:", errors);
28
+ return { items: [], nextToken: undefined };
29
+ }
30
+
31
+ return {
32
+ items: (data || []) as ActivityLog[],
33
+ nextToken,
34
+ };
35
+ } catch (error) {
36
+ console.error("[listActivityLogs] Error:", error);
37
+ throw error;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * List activity logs by account ID (for Account Admins)
43
+ */
44
+ export async function listActivityLogsByAccount<TClient = any>(
45
+ client: TClient,
46
+ accountId: string,
47
+ options?: { limit?: number; nextToken?: string },
48
+ ): Promise<{ items: ActivityLog[]; nextToken?: string }> {
49
+ return listActivityLogs(client, {
50
+ filter: { accountId: { eq: accountId } },
51
+ ...options,
52
+ });
53
+ }
54
+
55
+ /**
56
+ * List activity logs by brand ID (for Brand Admins)
57
+ */
58
+ export async function listActivityLogsByBrand<TClient = any>(
59
+ client: TClient,
60
+ brandId: string,
61
+ options?: { limit?: number; nextToken?: string },
62
+ ): Promise<{ items: ActivityLog[]; nextToken?: string }> {
63
+ return listActivityLogs(client, {
64
+ filter: { brandId: { eq: brandId } },
65
+ ...options,
66
+ });
67
+ }
68
+
69
+ /**
70
+ * List recent activity logs sorted by createdAt descending
71
+ */
72
+ export async function listRecentActivityLogs<TClient = any>(
73
+ client: TClient,
74
+ options?: {
75
+ filter?: any;
76
+ limit?: number;
77
+ },
78
+ ): Promise<ActivityLog[]> {
79
+ const { items } = await listActivityLogs(client, {
80
+ filter: options?.filter,
81
+ limit: options?.limit || 20,
82
+ });
83
+
84
+ return items.sort(
85
+ (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
86
+ );
87
+ }
@@ -73,3 +73,11 @@ export {
73
73
  getContactByPhone,
74
74
  searchContacts,
75
75
  } from "./contacts";
76
+
77
+ // ActivityLog queries
78
+ export {
79
+ listActivityLogs,
80
+ listActivityLogsByAccount,
81
+ listActivityLogsByBrand,
82
+ listRecentActivityLogs,
83
+ } from "./activityLogs";