@htlkg/data 0.0.19 → 0.0.21

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 (39) hide show
  1. package/dist/client/index.d.ts +257 -1
  2. package/dist/client/index.js +59 -1
  3. package/dist/client/index.js.map +1 -1
  4. package/dist/common-DSxswsZ3.d.ts +40 -0
  5. package/dist/hooks/index.d.ts +162 -10
  6. package/dist/hooks/index.js +191 -33
  7. package/dist/hooks/index.js.map +1 -1
  8. package/dist/index.d.ts +9 -5
  9. package/dist/index.js +789 -13
  10. package/dist/index.js.map +1 -1
  11. package/dist/mutations/index.d.ts +342 -4
  12. package/dist/mutations/index.js +486 -0
  13. package/dist/mutations/index.js.map +1 -1
  14. package/dist/{productInstances-BA3cNsYc.d.ts → productInstances-BpQv1oLS.d.ts} +2 -40
  15. package/dist/queries/index.d.ts +113 -2
  16. package/dist/queries/index.js +192 -1
  17. package/dist/queries/index.js.map +1 -1
  18. package/dist/reservations-C0FNm__0.d.ts +154 -0
  19. package/dist/reservations-CdDfkcZ_.d.ts +172 -0
  20. package/package.json +14 -13
  21. package/src/client/index.ts +18 -0
  22. package/src/client/reservations.ts +336 -0
  23. package/src/hooks/createDataHook.test.ts +534 -0
  24. package/src/hooks/createDataHook.ts +20 -13
  25. package/src/hooks/index.ts +2 -0
  26. package/src/hooks/useContacts.test.ts +159 -0
  27. package/src/hooks/useContacts.ts +176 -0
  28. package/src/hooks/useReservations.ts +145 -0
  29. package/src/mutations/contacts.test.ts +604 -0
  30. package/src/mutations/contacts.ts +554 -0
  31. package/src/mutations/index.ts +32 -0
  32. package/src/mutations/productInstances/productInstances.test.ts +3 -3
  33. package/src/mutations/reservations.test.ts +459 -0
  34. package/src/mutations/reservations.ts +452 -0
  35. package/src/queries/contacts.test.ts +505 -0
  36. package/src/queries/contacts.ts +237 -0
  37. package/src/queries/index.ts +21 -0
  38. package/src/queries/reservations.test.ts +374 -0
  39. package/src/queries/reservations.ts +247 -0
package/dist/index.js CHANGED
@@ -487,6 +487,185 @@ function checkRestoreEligibility(deletedAt, retentionDays) {
487
487
  };
488
488
  }
489
489
 
490
+ // src/queries/reservations.ts
491
+ async function getReservation2(client, id) {
492
+ try {
493
+ const { data, errors } = await client.models.Reservation.get({ id });
494
+ if (errors) {
495
+ console.error("[getReservation] GraphQL errors:", errors);
496
+ return null;
497
+ }
498
+ return data;
499
+ } catch (error) {
500
+ console.error("[getReservation] Error fetching reservation:", error);
501
+ throw error;
502
+ }
503
+ }
504
+ async function listReservations2(client, options) {
505
+ try {
506
+ const { data, errors, nextToken } = await client.models.Reservation.list(
507
+ options
508
+ );
509
+ if (errors) {
510
+ console.error("[listReservations] GraphQL errors:", errors);
511
+ return { items: [], nextToken: void 0 };
512
+ }
513
+ return {
514
+ items: data || [],
515
+ nextToken
516
+ };
517
+ } catch (error) {
518
+ console.error("[listReservations] Error fetching reservations:", error);
519
+ throw error;
520
+ }
521
+ }
522
+ async function listReservationsByBrand(client, brandId, options) {
523
+ const filter = options?.filter ? { and: [{ brandId: { eq: brandId } }, options.filter] } : { brandId: { eq: brandId } };
524
+ return listReservations2(client, {
525
+ filter,
526
+ limit: options?.limit,
527
+ nextToken: options?.nextToken
528
+ });
529
+ }
530
+ async function listReservationsByContact(client, contactId, options) {
531
+ return listReservations2(client, {
532
+ filter: { visitId: { eq: contactId } },
533
+ ...options
534
+ });
535
+ }
536
+ async function listReservationsByDateRange(client, brandId, startDate, endDate, options) {
537
+ return listReservations2(client, {
538
+ filter: {
539
+ and: [
540
+ { brandId: { eq: brandId } },
541
+ { checkIn: { ge: startDate } },
542
+ { checkIn: { le: endDate } }
543
+ ]
544
+ },
545
+ ...options
546
+ });
547
+ }
548
+ async function getReservationByConfirmation(client, confirmationCode, brandId) {
549
+ try {
550
+ const { items } = await listReservations2(client, {
551
+ filter: {
552
+ and: [
553
+ { confirmationCode: { eq: confirmationCode } },
554
+ { brandId: { eq: brandId } }
555
+ ]
556
+ },
557
+ limit: 1
558
+ });
559
+ return items.length > 0 ? items[0] : null;
560
+ } catch (error) {
561
+ console.error("[getReservationByConfirmation] Error fetching reservation:", error);
562
+ throw error;
563
+ }
564
+ }
565
+
566
+ // src/queries/contacts.ts
567
+ async function getContact(client, id) {
568
+ try {
569
+ const { data, errors } = await client.models.Contact.get({ id });
570
+ if (errors) {
571
+ console.error("[getContact] GraphQL errors:", errors);
572
+ return null;
573
+ }
574
+ return data;
575
+ } catch (error) {
576
+ console.error("[getContact] Error fetching contact:", error);
577
+ throw error;
578
+ }
579
+ }
580
+ async function listContacts(client, options) {
581
+ try {
582
+ const { data, errors, nextToken } = await client.models.Contact.list(options);
583
+ if (errors) {
584
+ console.error("[listContacts] GraphQL errors:", errors);
585
+ return { items: [], nextToken: void 0 };
586
+ }
587
+ return {
588
+ items: data || [],
589
+ nextToken
590
+ };
591
+ } catch (error) {
592
+ console.error("[listContacts] Error fetching contacts:", error);
593
+ throw error;
594
+ }
595
+ }
596
+ async function listContactsByBrand(client, brandId, options) {
597
+ return listContacts(client, {
598
+ filter: { brandId: { eq: brandId } },
599
+ ...options
600
+ });
601
+ }
602
+ async function getContactByEmail(client, email, brandId) {
603
+ try {
604
+ const { data, errors } = await client.models.Contact.list({
605
+ filter: {
606
+ and: [{ email: { eq: email } }, { brandId: { eq: brandId } }]
607
+ },
608
+ limit: 1
609
+ });
610
+ if (errors) {
611
+ console.error("[getContactByEmail] GraphQL errors:", errors);
612
+ return null;
613
+ }
614
+ return data?.[0];
615
+ } catch (error) {
616
+ console.error("[getContactByEmail] Error fetching contact:", error);
617
+ throw error;
618
+ }
619
+ }
620
+ async function getContactByPhone(client, phone, brandId) {
621
+ try {
622
+ const { data, errors } = await client.models.Contact.list({
623
+ filter: {
624
+ and: [{ phone: { eq: phone } }, { brandId: { eq: brandId } }]
625
+ },
626
+ limit: 1
627
+ });
628
+ if (errors) {
629
+ console.error("[getContactByPhone] GraphQL errors:", errors);
630
+ return null;
631
+ }
632
+ return data?.[0];
633
+ } catch (error) {
634
+ console.error("[getContactByPhone] Error fetching contact:", error);
635
+ throw error;
636
+ }
637
+ }
638
+ async function searchContacts(client, query2, brandId, options) {
639
+ try {
640
+ const { data, errors, nextToken } = await client.models.Contact.list({
641
+ filter: {
642
+ and: [
643
+ { brandId: { eq: brandId } },
644
+ {
645
+ or: [
646
+ { email: { contains: query2 } },
647
+ { firstName: { contains: query2 } },
648
+ { lastName: { contains: query2 } }
649
+ ]
650
+ }
651
+ ]
652
+ },
653
+ ...options
654
+ });
655
+ if (errors) {
656
+ console.error("[searchContacts] GraphQL errors:", errors);
657
+ return { items: [], nextToken: void 0 };
658
+ }
659
+ return {
660
+ items: data || [],
661
+ nextToken
662
+ };
663
+ } catch (error) {
664
+ console.error("[searchContacts] Error searching contacts:", error);
665
+ throw error;
666
+ }
667
+ }
668
+
490
669
  // src/mutations/brands.ts
491
670
  async function createBrand(client, input) {
492
671
  try {
@@ -965,15 +1144,469 @@ async function initializeSystemSettings(client, initializedBy) {
965
1144
  }
966
1145
  }
967
1146
 
1147
+ // src/mutations/reservations.ts
1148
+ var STATUS_TRANSITIONS = {
1149
+ confirmed: ["checked_in", "cancelled", "no_show"],
1150
+ checked_in: ["checked_out", "cancelled"],
1151
+ checked_out: [],
1152
+ // Terminal state - no transitions allowed
1153
+ cancelled: [],
1154
+ // Terminal state - no transitions allowed
1155
+ no_show: []
1156
+ // Terminal state - no transitions allowed
1157
+ };
1158
+ var ReservationValidationError = class extends Error {
1159
+ constructor(message) {
1160
+ super(message);
1161
+ this.name = "ReservationValidationError";
1162
+ }
1163
+ };
1164
+ function validateDates(checkIn, checkOut) {
1165
+ const checkInDate = new Date(checkIn);
1166
+ const checkOutDate = new Date(checkOut);
1167
+ if (isNaN(checkInDate.getTime())) {
1168
+ throw new ReservationValidationError("Invalid check-in date");
1169
+ }
1170
+ if (isNaN(checkOutDate.getTime())) {
1171
+ throw new ReservationValidationError("Invalid check-out date");
1172
+ }
1173
+ if (checkOutDate <= checkInDate) {
1174
+ throw new ReservationValidationError(
1175
+ "Check-out date must be after check-in date"
1176
+ );
1177
+ }
1178
+ const minStayHours = 4;
1179
+ const stayDuration = checkOutDate.getTime() - checkInDate.getTime();
1180
+ const hoursDiff = stayDuration / (1e3 * 60 * 60);
1181
+ if (hoursDiff < minStayHours) {
1182
+ throw new ReservationValidationError(
1183
+ `Minimum stay is ${minStayHours} hours`
1184
+ );
1185
+ }
1186
+ }
1187
+ function validateStatusTransition(currentStatus, newStatus) {
1188
+ const allowedTransitions = STATUS_TRANSITIONS[currentStatus];
1189
+ if (!allowedTransitions.includes(newStatus)) {
1190
+ throw new ReservationValidationError(
1191
+ `Invalid status transition from '${currentStatus}' to '${newStatus}'. Allowed transitions: ${allowedTransitions.length > 0 ? allowedTransitions.join(", ") : "none (terminal state)"}`
1192
+ );
1193
+ }
1194
+ }
1195
+ async function createReservation2(client, input) {
1196
+ try {
1197
+ validateDates(input.checkIn, input.checkOut);
1198
+ if (!input.nights) {
1199
+ const checkInDate = new Date(input.checkIn);
1200
+ const checkOutDate = new Date(input.checkOut);
1201
+ const diffTime = checkOutDate.getTime() - checkInDate.getTime();
1202
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
1203
+ input.nights = diffDays;
1204
+ }
1205
+ const { data, errors } = await client.models.Reservation.create(input);
1206
+ if (errors) {
1207
+ console.error("[createReservation] GraphQL errors:", errors);
1208
+ return null;
1209
+ }
1210
+ return data;
1211
+ } catch (error) {
1212
+ if (error instanceof ReservationValidationError) {
1213
+ console.error("[createReservation] Validation error:", error.message);
1214
+ throw error;
1215
+ }
1216
+ console.error("[createReservation] Error creating reservation:", error);
1217
+ throw error;
1218
+ }
1219
+ }
1220
+ async function updateReservation2(client, input) {
1221
+ try {
1222
+ if (input.checkIn && input.checkOut) {
1223
+ validateDates(input.checkIn, input.checkOut);
1224
+ const checkInDate = new Date(input.checkIn);
1225
+ const checkOutDate = new Date(input.checkOut);
1226
+ const diffTime = checkOutDate.getTime() - checkInDate.getTime();
1227
+ const diffDays = Math.ceil(diffTime / (1e3 * 60 * 60 * 24));
1228
+ input.nights = diffDays;
1229
+ }
1230
+ if (input.status) {
1231
+ const { data: currentReservation, errors: getErrors } = await client.models.Reservation.get({ id: input.id });
1232
+ if (getErrors || !currentReservation) {
1233
+ console.error("[updateReservation] Error fetching current reservation:", getErrors);
1234
+ return null;
1235
+ }
1236
+ const currentStatus = currentReservation.status;
1237
+ validateStatusTransition(currentStatus, input.status);
1238
+ }
1239
+ const { data, errors } = await client.models.Reservation.update(input);
1240
+ if (errors) {
1241
+ console.error("[updateReservation] GraphQL errors:", errors);
1242
+ return null;
1243
+ }
1244
+ return data;
1245
+ } catch (error) {
1246
+ if (error instanceof ReservationValidationError) {
1247
+ console.error("[updateReservation] Validation error:", error.message);
1248
+ throw error;
1249
+ }
1250
+ console.error("[updateReservation] Error updating reservation:", error);
1251
+ throw error;
1252
+ }
1253
+ }
1254
+ async function softDeleteReservation2(client, id, deletedBy) {
1255
+ try {
1256
+ const { errors } = await client.models.Reservation.update({
1257
+ id,
1258
+ deletedAt: (/* @__PURE__ */ new Date()).toISOString(),
1259
+ deletedBy
1260
+ });
1261
+ if (errors) {
1262
+ console.error("[softDeleteReservation] GraphQL errors:", errors);
1263
+ return false;
1264
+ }
1265
+ return true;
1266
+ } catch (error) {
1267
+ console.error("[softDeleteReservation] Error soft-deleting reservation:", error);
1268
+ throw error;
1269
+ }
1270
+ }
1271
+ async function restoreReservation2(client, id, retentionDays = DEFAULT_SOFT_DELETE_RETENTION_DAYS) {
1272
+ try {
1273
+ const { data: reservation, errors: getErrors } = await client.models.Reservation.get({ id });
1274
+ if (getErrors || !reservation) {
1275
+ console.error("[restoreReservation] Error fetching reservation:", getErrors);
1276
+ return { success: false, error: "Reservation not found" };
1277
+ }
1278
+ const eligibility = checkRestoreEligibility(reservation.deletedAt, retentionDays);
1279
+ if (!eligibility.canRestore) {
1280
+ const errorMsg = `Cannot restore reservation. Retention period of ${retentionDays} days has expired. Item was deleted ${eligibility.daysExpired} days ago.`;
1281
+ console.error("[restoreReservation]", errorMsg);
1282
+ return { success: false, error: errorMsg };
1283
+ }
1284
+ const { errors } = await client.models.Reservation.update({
1285
+ id,
1286
+ deletedAt: null,
1287
+ deletedBy: null
1288
+ });
1289
+ if (errors) {
1290
+ console.error("[restoreReservation] GraphQL errors:", errors);
1291
+ return { success: false, error: "Failed to restore reservation" };
1292
+ }
1293
+ return { success: true };
1294
+ } catch (error) {
1295
+ console.error("[restoreReservation] Error restoring reservation:", error);
1296
+ throw error;
1297
+ }
1298
+ }
1299
+ async function deleteReservation2(client, id) {
1300
+ try {
1301
+ const { errors } = await client.models.Reservation.delete({ id });
1302
+ if (errors) {
1303
+ console.error("[deleteReservation] GraphQL errors:", errors);
1304
+ return false;
1305
+ }
1306
+ return true;
1307
+ } catch (error) {
1308
+ console.error("[deleteReservation] Error deleting reservation:", error);
1309
+ throw error;
1310
+ }
1311
+ }
1312
+ async function updateReservationStatus2(client, id, newStatus) {
1313
+ try {
1314
+ const { data: currentReservation, errors: getErrors } = await client.models.Reservation.get({ id });
1315
+ if (getErrors || !currentReservation) {
1316
+ console.error("[updateReservationStatus] Error fetching reservation:", getErrors);
1317
+ return null;
1318
+ }
1319
+ const currentStatus = currentReservation.status;
1320
+ validateStatusTransition(currentStatus, newStatus);
1321
+ const { data, errors } = await client.models.Reservation.update({
1322
+ id,
1323
+ status: newStatus
1324
+ });
1325
+ if (errors) {
1326
+ console.error("[updateReservationStatus] GraphQL errors:", errors);
1327
+ return null;
1328
+ }
1329
+ return data;
1330
+ } catch (error) {
1331
+ if (error instanceof ReservationValidationError) {
1332
+ console.error("[updateReservationStatus] Validation error:", error.message);
1333
+ throw error;
1334
+ }
1335
+ console.error("[updateReservationStatus] Error updating status:", error);
1336
+ throw error;
1337
+ }
1338
+ }
1339
+
1340
+ // src/mutations/contacts.ts
1341
+ import { z } from "zod";
1342
+ var createContactSchema = z.object({
1343
+ brandId: z.string().min(1, "Brand ID is required"),
1344
+ email: z.string().email("Invalid email address"),
1345
+ phone: z.string().optional(),
1346
+ firstName: z.string().min(1, "First name is required"),
1347
+ lastName: z.string().min(1, "Last name is required"),
1348
+ locale: z.string().optional(),
1349
+ gdprConsent: z.boolean(),
1350
+ gdprConsentDate: z.string().optional(),
1351
+ marketingOptIn: z.boolean().optional(),
1352
+ preferences: z.record(z.any()).optional(),
1353
+ tags: z.array(z.string()).optional(),
1354
+ totalVisits: z.number().int().min(0).optional(),
1355
+ lastVisitDate: z.string().optional(),
1356
+ firstVisitDate: z.string().optional(),
1357
+ legacyId: z.string().optional(),
1358
+ // Audit fields
1359
+ createdAt: z.string().optional(),
1360
+ createdBy: z.string().optional(),
1361
+ updatedAt: z.string().optional(),
1362
+ updatedBy: z.string().optional()
1363
+ });
1364
+ var updateContactSchema = z.object({
1365
+ id: z.string().min(1, "Contact ID is required"),
1366
+ brandId: z.string().min(1).optional(),
1367
+ email: z.string().email("Invalid email address").optional(),
1368
+ phone: z.string().optional(),
1369
+ firstName: z.string().min(1).optional(),
1370
+ lastName: z.string().min(1).optional(),
1371
+ locale: z.string().optional(),
1372
+ gdprConsent: z.boolean().optional(),
1373
+ gdprConsentDate: z.string().optional(),
1374
+ marketingOptIn: z.boolean().optional(),
1375
+ preferences: z.record(z.any()).optional(),
1376
+ tags: z.array(z.string()).optional(),
1377
+ totalVisits: z.number().int().min(0).optional(),
1378
+ lastVisitDate: z.string().optional(),
1379
+ firstVisitDate: z.string().optional(),
1380
+ legacyId: z.string().optional(),
1381
+ // Audit fields
1382
+ updatedAt: z.string().optional(),
1383
+ updatedBy: z.string().optional(),
1384
+ deletedAt: z.string().nullable().optional(),
1385
+ deletedBy: z.string().nullable().optional()
1386
+ });
1387
+ var mergeContactsSchema = z.object({
1388
+ primaryId: z.string().min(1, "Primary contact ID is required"),
1389
+ duplicateIds: z.array(z.string().min(1)).min(1, "At least one duplicate ID is required")
1390
+ });
1391
+ var ContactValidationError = class extends Error {
1392
+ issues;
1393
+ constructor(message, issues = []) {
1394
+ super(message);
1395
+ this.name = "ContactValidationError";
1396
+ this.issues = issues;
1397
+ }
1398
+ };
1399
+ async function createContact(client, input) {
1400
+ try {
1401
+ const validationResult = createContactSchema.safeParse(input);
1402
+ if (!validationResult.success) {
1403
+ const errorMessage = validationResult.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join(", ");
1404
+ throw new ContactValidationError(
1405
+ `Validation failed: ${errorMessage}`,
1406
+ validationResult.error.issues
1407
+ );
1408
+ }
1409
+ const { data, errors } = await client.models.Contact.create(input);
1410
+ if (errors) {
1411
+ console.error("[createContact] GraphQL errors:", errors);
1412
+ return null;
1413
+ }
1414
+ return data;
1415
+ } catch (error) {
1416
+ if (error instanceof ContactValidationError) {
1417
+ console.error("[createContact] Validation error:", error.message);
1418
+ throw error;
1419
+ }
1420
+ console.error("[createContact] Error creating contact:", error);
1421
+ throw error;
1422
+ }
1423
+ }
1424
+ async function updateContact(client, input) {
1425
+ try {
1426
+ const validationResult = updateContactSchema.safeParse(input);
1427
+ if (!validationResult.success) {
1428
+ const errorMessage = validationResult.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join(", ");
1429
+ throw new ContactValidationError(
1430
+ `Validation failed: ${errorMessage}`,
1431
+ validationResult.error.issues
1432
+ );
1433
+ }
1434
+ const { data, errors } = await client.models.Contact.update(input);
1435
+ if (errors) {
1436
+ console.error("[updateContact] GraphQL errors:", errors);
1437
+ return null;
1438
+ }
1439
+ return data;
1440
+ } catch (error) {
1441
+ if (error instanceof ContactValidationError) {
1442
+ console.error("[updateContact] Validation error:", error.message);
1443
+ throw error;
1444
+ }
1445
+ console.error("[updateContact] Error updating contact:", error);
1446
+ throw error;
1447
+ }
1448
+ }
1449
+ async function softDeleteContact(client, id, deletedBy) {
1450
+ try {
1451
+ const { errors } = await client.models.Contact.update({
1452
+ id,
1453
+ deletedAt: (/* @__PURE__ */ new Date()).toISOString(),
1454
+ deletedBy
1455
+ });
1456
+ if (errors) {
1457
+ console.error("[softDeleteContact] GraphQL errors:", errors);
1458
+ return false;
1459
+ }
1460
+ return true;
1461
+ } catch (error) {
1462
+ console.error("[softDeleteContact] Error soft-deleting contact:", error);
1463
+ throw error;
1464
+ }
1465
+ }
1466
+ async function restoreContact(client, id, retentionDays = DEFAULT_SOFT_DELETE_RETENTION_DAYS) {
1467
+ try {
1468
+ const contact = await getContact(client, id);
1469
+ if (!contact) {
1470
+ console.error("[restoreContact] Contact not found");
1471
+ return { success: false, error: "Contact not found" };
1472
+ }
1473
+ const eligibility = checkRestoreEligibility(
1474
+ contact.deletedAt,
1475
+ retentionDays
1476
+ );
1477
+ if (!eligibility.canRestore) {
1478
+ const errorMsg = `Cannot restore contact. Retention period of ${retentionDays} days has expired. Item was deleted ${eligibility.daysExpired} days ago.`;
1479
+ console.error("[restoreContact]", errorMsg);
1480
+ return { success: false, error: errorMsg };
1481
+ }
1482
+ const { errors } = await client.models.Contact.update({
1483
+ id,
1484
+ deletedAt: null,
1485
+ deletedBy: null
1486
+ });
1487
+ if (errors) {
1488
+ console.error("[restoreContact] GraphQL errors:", errors);
1489
+ return { success: false, error: "Failed to restore contact" };
1490
+ }
1491
+ return { success: true };
1492
+ } catch (error) {
1493
+ console.error("[restoreContact] Error restoring contact:", error);
1494
+ throw error;
1495
+ }
1496
+ }
1497
+ async function deleteContact(client, id) {
1498
+ try {
1499
+ const { errors } = await client.models.Contact.delete({ id });
1500
+ if (errors) {
1501
+ console.error("[deleteContact] GraphQL errors:", errors);
1502
+ return false;
1503
+ }
1504
+ return true;
1505
+ } catch (error) {
1506
+ console.error("[deleteContact] Error deleting contact:", error);
1507
+ throw error;
1508
+ }
1509
+ }
1510
+ async function mergeContacts(client, input, mergedBy) {
1511
+ try {
1512
+ const validationResult = mergeContactsSchema.safeParse(input);
1513
+ if (!validationResult.success) {
1514
+ const errorMessage = validationResult.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join(", ");
1515
+ throw new ContactValidationError(
1516
+ `Validation failed: ${errorMessage}`,
1517
+ validationResult.error.issues
1518
+ );
1519
+ }
1520
+ const { primaryId, duplicateIds } = input;
1521
+ const primaryContact = await getContact(client, primaryId);
1522
+ if (!primaryContact) {
1523
+ return {
1524
+ success: false,
1525
+ error: `Primary contact not found: ${primaryId}`
1526
+ };
1527
+ }
1528
+ const duplicateContacts = [];
1529
+ for (const duplicateId of duplicateIds) {
1530
+ const duplicate = await getContact(client, duplicateId);
1531
+ if (!duplicate) {
1532
+ return {
1533
+ success: false,
1534
+ error: `Duplicate contact not found: ${duplicateId}`
1535
+ };
1536
+ }
1537
+ duplicateContacts.push(duplicate);
1538
+ }
1539
+ let totalVisits = primaryContact.totalVisits || 0;
1540
+ let firstVisitDate = primaryContact.firstVisitDate;
1541
+ let lastVisitDate = primaryContact.lastVisitDate;
1542
+ const allTags = new Set(primaryContact.tags || []);
1543
+ for (const duplicate of duplicateContacts) {
1544
+ totalVisits += duplicate.totalVisits || 0;
1545
+ if (duplicate.firstVisitDate) {
1546
+ if (!firstVisitDate || duplicate.firstVisitDate < firstVisitDate) {
1547
+ firstVisitDate = duplicate.firstVisitDate;
1548
+ }
1549
+ }
1550
+ if (duplicate.lastVisitDate) {
1551
+ if (!lastVisitDate || duplicate.lastVisitDate > lastVisitDate) {
1552
+ lastVisitDate = duplicate.lastVisitDate;
1553
+ }
1554
+ }
1555
+ if (duplicate.tags) {
1556
+ duplicate.tags.forEach((tag) => allTags.add(tag));
1557
+ }
1558
+ }
1559
+ const updateInput = {
1560
+ id: primaryId,
1561
+ totalVisits,
1562
+ firstVisitDate,
1563
+ lastVisitDate,
1564
+ tags: Array.from(allTags),
1565
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1566
+ updatedBy: mergedBy
1567
+ };
1568
+ const updatedPrimary = await updateContact(client, updateInput);
1569
+ if (!updatedPrimary) {
1570
+ return {
1571
+ success: false,
1572
+ error: "Failed to update primary contact with merged data"
1573
+ };
1574
+ }
1575
+ const deletedIds = [];
1576
+ for (const duplicateId of duplicateIds) {
1577
+ const deleted = await softDeleteContact(client, duplicateId, mergedBy);
1578
+ if (deleted) {
1579
+ deletedIds.push(duplicateId);
1580
+ } else {
1581
+ console.error(`[mergeContacts] Failed to soft-delete duplicate: ${duplicateId}`);
1582
+ }
1583
+ }
1584
+ return {
1585
+ success: true,
1586
+ mergedContact: updatedPrimary,
1587
+ deletedIds
1588
+ };
1589
+ } catch (error) {
1590
+ if (error instanceof ContactValidationError) {
1591
+ console.error("[mergeContacts] Validation error:", error.message);
1592
+ throw error;
1593
+ }
1594
+ console.error("[mergeContacts] Error merging contacts:", error);
1595
+ throw error;
1596
+ }
1597
+ }
1598
+
968
1599
  // src/hooks/createDataHook.ts
969
1600
  import { ref, computed, onMounted } from "vue";
1601
+ function resetClientInstance() {
1602
+ }
970
1603
  function createDataHook(config) {
971
1604
  const {
972
1605
  model,
973
1606
  defaultLimit,
974
1607
  selectionSet,
975
1608
  transform,
976
- buildFilter: buildFilter5,
1609
+ buildFilter: buildFilter7,
977
1610
  computedProperties,
978
1611
  dataPropertyName = "data"
979
1612
  } = config;
@@ -983,8 +1616,8 @@ function createDataHook(config) {
983
1616
  const loading = ref(false);
984
1617
  const error = ref(null);
985
1618
  const getFilter = () => {
986
- if (buildFilter5) {
987
- return buildFilter5(options);
1619
+ if (buildFilter7) {
1620
+ return buildFilter7(options);
988
1621
  }
989
1622
  return baseFilter && Object.keys(baseFilter).length > 0 ? baseFilter : void 0;
990
1623
  };
@@ -992,19 +1625,22 @@ function createDataHook(config) {
992
1625
  loading.value = true;
993
1626
  error.value = null;
994
1627
  try {
995
- const client = getSharedClient();
996
- const queryOptions = {
997
- filter: getFilter(),
998
- limit
999
- };
1628
+ const queryOptions = {};
1629
+ const filter = getFilter();
1630
+ if (filter) {
1631
+ queryOptions.filter = filter;
1632
+ }
1633
+ if (limit) {
1634
+ queryOptions.limit = limit;
1635
+ }
1000
1636
  if (selectionSet) {
1001
1637
  queryOptions.selectionSet = selectionSet;
1002
1638
  }
1003
- const { data: responseData, errors } = await client.models[model].list(queryOptions);
1004
- if (errors) {
1005
- throw new Error(errors[0]?.message || `Failed to fetch ${model}`);
1639
+ const response = await query(model, "list", queryOptions);
1640
+ if (hasErrors(response)) {
1641
+ throw new Error(getErrorMessage(response) || `Failed to fetch ${model}`);
1006
1642
  }
1007
- const items = responseData || [];
1643
+ const items = response.data || [];
1008
1644
  data.value = transform ? items.map(transform) : items;
1009
1645
  } catch (e) {
1010
1646
  error.value = e;
@@ -1207,6 +1843,115 @@ function useProductInstances(options = {}) {
1207
1843
  };
1208
1844
  }
1209
1845
 
1846
+ // src/hooks/useReservations.ts
1847
+ function buildFilter5(options) {
1848
+ const conditions = [];
1849
+ if (options.brandId) {
1850
+ conditions.push({ brandId: { eq: options.brandId } });
1851
+ }
1852
+ if (options.status) {
1853
+ conditions.push({ status: { eq: options.status } });
1854
+ }
1855
+ if (options.contactId) {
1856
+ conditions.push({ visitId: { eq: options.contactId } });
1857
+ }
1858
+ if (options.startDate) {
1859
+ conditions.push({ checkIn: { ge: options.startDate } });
1860
+ }
1861
+ if (options.endDate) {
1862
+ conditions.push({ checkIn: { le: options.endDate } });
1863
+ }
1864
+ if (options.filter) {
1865
+ conditions.push(options.filter);
1866
+ }
1867
+ if (conditions.length === 0) {
1868
+ return void 0;
1869
+ }
1870
+ if (conditions.length === 1) {
1871
+ return conditions[0];
1872
+ }
1873
+ return { and: conditions };
1874
+ }
1875
+ var useReservationsInternal = createDataHook({
1876
+ model: "Reservation",
1877
+ dataPropertyName: "reservations",
1878
+ buildFilter: buildFilter5,
1879
+ computedProperties: {
1880
+ confirmedReservations: (reservations) => reservations.filter((r) => r.status === "confirmed"),
1881
+ activeReservations: (reservations) => reservations.filter((r) => r.status === "confirmed" || r.status === "checked_in")
1882
+ }
1883
+ });
1884
+ function useReservations(options = {}) {
1885
+ const result = useReservationsInternal(options);
1886
+ return {
1887
+ reservations: result.reservations,
1888
+ confirmedReservations: result.confirmedReservations,
1889
+ activeReservations: result.activeReservations,
1890
+ loading: result.loading,
1891
+ error: result.error,
1892
+ refetch: result.refetch
1893
+ };
1894
+ }
1895
+
1896
+ // src/hooks/useContacts.ts
1897
+ function buildFilter6(options) {
1898
+ const conditions = [];
1899
+ if (options.brandId) {
1900
+ conditions.push({ brandId: { eq: options.brandId } });
1901
+ }
1902
+ if (options.search) {
1903
+ conditions.push({
1904
+ or: [
1905
+ { email: { contains: options.search } },
1906
+ { firstName: { contains: options.search } },
1907
+ { lastName: { contains: options.search } }
1908
+ ]
1909
+ });
1910
+ }
1911
+ if (options.gdprConsent !== void 0) {
1912
+ conditions.push({ gdprConsent: { eq: options.gdprConsent } });
1913
+ }
1914
+ if (options.marketingOptIn !== void 0) {
1915
+ conditions.push({ marketingOptIn: { eq: options.marketingOptIn } });
1916
+ }
1917
+ if (options.tags && options.tags.length > 0) {
1918
+ const tagConditions = options.tags.map((tag) => ({
1919
+ tags: { contains: tag }
1920
+ }));
1921
+ conditions.push({ or: tagConditions });
1922
+ }
1923
+ if (options.filter) {
1924
+ conditions.push(options.filter);
1925
+ }
1926
+ if (conditions.length === 0) {
1927
+ return void 0;
1928
+ }
1929
+ if (conditions.length === 1) {
1930
+ return conditions[0];
1931
+ }
1932
+ return { and: conditions };
1933
+ }
1934
+ var useContactsInternal = createDataHook({
1935
+ model: "Contact",
1936
+ dataPropertyName: "contacts",
1937
+ buildFilter: buildFilter6,
1938
+ computedProperties: {
1939
+ consentedContacts: (contacts) => contacts.filter((c) => c.gdprConsent === true),
1940
+ marketingContacts: (contacts) => contacts.filter((c) => c.marketingOptIn === true)
1941
+ }
1942
+ });
1943
+ function useContacts(options = {}) {
1944
+ const result = useContactsInternal(options);
1945
+ return {
1946
+ contacts: result.contacts,
1947
+ consentedContacts: result.consentedContacts,
1948
+ marketingContacts: result.marketingContacts,
1949
+ loading: result.loading,
1950
+ error: result.error,
1951
+ refetch: result.refetch
1952
+ };
1953
+ }
1954
+
1210
1955
  // ../../node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/clean-stores/index.js
1211
1956
  var clean = /* @__PURE__ */ Symbol("clean");
1212
1957
 
@@ -1310,20 +2055,27 @@ function createSingleStore(shared, name, defaultValue) {
1310
2055
  return shared(name, atom(defaultValue));
1311
2056
  }
1312
2057
  export {
2058
+ ContactValidationError,
1313
2059
  DEFAULT_SOFT_DELETE_RETENTION_DAYS,
2060
+ ReservationValidationError,
1314
2061
  SYSTEM_SETTINGS_KEY,
1315
2062
  checkRestoreEligibility,
1316
2063
  createAccount,
1317
2064
  createBrand,
2065
+ createContact,
2066
+ createContactSchema,
1318
2067
  createDataHook,
1319
2068
  createProductInstance,
2069
+ createReservation2 as createReservation,
1320
2070
  createResourceStores,
1321
2071
  createSingleStore,
1322
2072
  createStore,
1323
2073
  createUser,
1324
2074
  deleteAccount,
1325
2075
  deleteBrand,
2076
+ deleteContact,
1326
2077
  deleteProductInstance,
2078
+ deleteReservation2 as deleteReservation,
1327
2079
  deleteUser,
1328
2080
  executePublicQuery,
1329
2081
  executeServerQuery,
@@ -1333,9 +2085,14 @@ export {
1333
2085
  getAccountWithBrands,
1334
2086
  getBrand,
1335
2087
  getBrandWithProducts,
2088
+ getContact,
2089
+ getContactByEmail,
2090
+ getContactByPhone,
1336
2091
  getErrorMessage,
1337
2092
  getProduct,
1338
2093
  getProductInstance,
2094
+ getReservation2 as getReservation,
2095
+ getReservationByConfirmation,
1339
2096
  getSharedClient,
1340
2097
  getSoftDeleteRetentionDays,
1341
2098
  getSystemSettings,
@@ -1350,32 +2107,51 @@ export {
1350
2107
  listActiveUsers,
1351
2108
  listBrands,
1352
2109
  listBrandsByAccount,
2110
+ listContacts,
2111
+ listContactsByBrand,
1353
2112
  listEnabledProductInstancesByBrand,
1354
2113
  listProductInstancesByAccount,
1355
2114
  listProductInstancesByBrand,
1356
2115
  listProducts,
2116
+ listReservations2 as listReservations,
2117
+ listReservationsByBrand,
2118
+ listReservationsByContact,
2119
+ listReservationsByDateRange,
1357
2120
  listUsers,
1358
2121
  listUsersByAccount,
2122
+ mergeContacts,
2123
+ mergeContactsSchema,
1359
2124
  mutate,
1360
2125
  query,
1361
- resetSharedClient as resetClientInstance,
2126
+ resetClientInstance,
1362
2127
  resetSharedClient,
1363
2128
  restoreAccount,
1364
2129
  restoreBrand,
2130
+ restoreContact,
2131
+ restoreReservation2 as restoreReservation,
1365
2132
  restoreUser,
2133
+ searchContacts,
1366
2134
  softDeleteAccount,
1367
2135
  softDeleteBrand,
2136
+ softDeleteContact,
2137
+ softDeleteReservation2 as softDeleteReservation,
1368
2138
  softDeleteUser,
1369
2139
  toggleProductInstanceEnabled,
1370
2140
  updateAccount,
1371
2141
  updateBrand,
2142
+ updateContact,
2143
+ updateContactSchema,
1372
2144
  updateProductInstance,
2145
+ updateReservation2 as updateReservation,
2146
+ updateReservationStatus2 as updateReservationStatus,
1373
2147
  updateSystemSettings,
1374
2148
  updateUser,
1375
2149
  useAccounts,
1376
2150
  useBrands,
2151
+ useContacts,
1377
2152
  useProductInstances,
1378
2153
  useProducts,
2154
+ useReservations,
1379
2155
  useUsers
1380
2156
  };
1381
2157
  //# sourceMappingURL=index.js.map