@aranova/tracking-next 1.0.0 → 1.2.0

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 (48) hide show
  1. package/README.md +48 -1
  2. package/dist/blog-server.js.map +1 -1
  3. package/dist/blog-server.mjs.map +1 -1
  4. package/dist/blog.js.map +1 -1
  5. package/dist/blog.mjs.map +1 -1
  6. package/dist/calendar-server.d.mts +1 -1
  7. package/dist/calendar-server.d.ts +1 -1
  8. package/dist/calendar-server.js.map +1 -1
  9. package/dist/calendar-server.mjs.map +1 -1
  10. package/dist/calendar.d.mts +14 -3
  11. package/dist/calendar.d.ts +14 -3
  12. package/dist/calendar.js +212 -18
  13. package/dist/calendar.js.map +1 -1
  14. package/dist/calendar.mjs +211 -18
  15. package/dist/calendar.mjs.map +1 -1
  16. package/dist/client.d.mts +9 -3
  17. package/dist/client.d.ts +9 -3
  18. package/dist/client.js +550 -194
  19. package/dist/client.js.map +1 -1
  20. package/dist/client.mjs +550 -194
  21. package/dist/client.mjs.map +1 -1
  22. package/dist/index.d.mts +10 -9
  23. package/dist/index.d.ts +10 -9
  24. package/dist/index.js +491 -284
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.mjs +490 -284
  27. package/dist/index.mjs.map +1 -1
  28. package/dist/{ingest-typed-BdKmlouW.d.ts → ingest-typed-MBuMe9Pn.d.ts} +94 -2
  29. package/dist/{ingest-typed-Bo7WPmpU.d.mts → ingest-typed-UA13xTfI.d.mts} +94 -2
  30. package/dist/{phone-utils-CubQif9Z.d.mts → phone-utils-C0ds6cqZ.d.mts} +6 -0
  31. package/dist/{phone-utils-CubQif9Z.d.ts → phone-utils-C0ds6cqZ.d.ts} +6 -0
  32. package/dist/phone.d.mts +1 -1
  33. package/dist/phone.d.ts +1 -1
  34. package/dist/{sales-DG150g3o.d.ts → sales-DQC815f3.d.ts} +1 -1
  35. package/dist/{sales-D7KstKA-.d.mts → sales-w1reW_Y3.d.mts} +1 -1
  36. package/dist/sales.d.mts +2 -2
  37. package/dist/sales.d.ts +2 -2
  38. package/dist/sales.js +17 -1
  39. package/dist/sales.js.map +1 -1
  40. package/dist/sales.mjs +17 -1
  41. package/dist/sales.mjs.map +1 -1
  42. package/dist/server.d.mts +1 -1
  43. package/dist/server.d.ts +1 -1
  44. package/dist/{tracking-config-runtime-D7prdTE1.d.mts → tracking-config-runtime-C6H7ofmo.d.mts} +6 -0
  45. package/dist/{tracking-config-runtime-D7prdTE1.d.ts → tracking-config-runtime-C6H7ofmo.d.ts} +6 -0
  46. package/dist/{transport-I_cMSFQ6.d.mts → transport-BlXQZs9Z.d.mts} +120 -50
  47. package/dist/{transport-CDmGOiCq.d.ts → transport-CAZYrZbB.d.ts} +120 -50
  48. package/package.json +1 -1
package/dist/calendar.js CHANGED
@@ -57,6 +57,7 @@ __export(calendar_exports, {
57
57
  endOfDayInTz: () => endOfDayInTz,
58
58
  formatDateInTz: () => formatDateInTz,
59
59
  formatSlotRange: () => formatSlotRange,
60
+ getBookingAttribution: () => getBookingAttribution,
60
61
  groupSlotsByDay: () => groupSlotsByDay,
61
62
  instantFromWallClock: () => instantFromWallClock,
62
63
  isCalendarError: () => isCalendarError,
@@ -67,6 +68,135 @@ __export(calendar_exports, {
67
68
  });
68
69
  module.exports = __toCommonJS(calendar_exports);
69
70
 
71
+ // ../tracking-core/src/tracking.ts
72
+ var TRACKING_PARAM_KEYS = [
73
+ "gclid",
74
+ // Google's iOS/Safari replacement click IDs — issued when privacy features
75
+ // withhold gclid (wbraid: web-to-web, gbraid: app-to-web). First-class
76
+ // citizens: captured, persisted, and attributed exactly like gclid.
77
+ "wbraid",
78
+ "gbraid",
79
+ // Yelp Ads click id (40 hex chars), appended to ad-click URLs.
80
+ "ylpcid",
81
+ "fbclid",
82
+ "utm_source",
83
+ "utm_medium",
84
+ "utm_campaign",
85
+ "utm_term",
86
+ "utm_content"
87
+ ];
88
+ function createEmptyTrackingParams() {
89
+ return {
90
+ gclid: null,
91
+ wbraid: null,
92
+ gbraid: null,
93
+ ylpcid: null,
94
+ fbclid: null,
95
+ utm_source: null,
96
+ utm_medium: null,
97
+ utm_campaign: null,
98
+ utm_term: null,
99
+ utm_content: null
100
+ };
101
+ }
102
+ function normalizeTrackingCookieValue(value) {
103
+ return typeof value === "string" && value.length > 0 ? value : null;
104
+ }
105
+ function getTrackingParamsFromCookieReader(readCookie) {
106
+ return TRACKING_PARAM_KEYS.reduce((params, key) => {
107
+ params[key] = normalizeTrackingCookieValue(readCookie(key));
108
+ return params;
109
+ }, createEmptyTrackingParams());
110
+ }
111
+ var FALLBACK_STORAGE_PREFIX = "_aranova_track_";
112
+ function fallbackKey(name) {
113
+ return `${FALLBACK_STORAGE_PREFIX}${name}`;
114
+ }
115
+ function readCookieValue(name) {
116
+ if (typeof document !== "undefined") {
117
+ const cookies = document.cookie ? document.cookie.split("; ") : [];
118
+ const match = cookies.find((cookie) => cookie.startsWith(`${name}=`));
119
+ if (match) {
120
+ const [, rawValue = ""] = match.split("=");
121
+ return normalizeTrackingCookieValue(decodeURIComponent(rawValue));
122
+ }
123
+ }
124
+ if (typeof window !== "undefined") {
125
+ try {
126
+ const stored = window.localStorage.getItem(fallbackKey(name));
127
+ if (stored) return normalizeTrackingCookieValue(decodeURIComponent(stored));
128
+ } catch {
129
+ }
130
+ }
131
+ return null;
132
+ }
133
+ function getCookieValueFromDocument(key) {
134
+ return readCookieValue(key);
135
+ }
136
+
137
+ // ../tracking-core/src/session.ts
138
+ var VISITOR_STORAGE_KEY = "aranova_tracking_visitor";
139
+ var SESSION_STORAGE_KEY = "aranova_tracking_session";
140
+ var SESSION_IDLE_MS = 30 * 60 * 1e3;
141
+ function readLocalStorage(key) {
142
+ try {
143
+ return window.localStorage.getItem(key);
144
+ } catch {
145
+ return null;
146
+ }
147
+ }
148
+ function peekVisitorId() {
149
+ if (typeof window === "undefined") return null;
150
+ const existing = readLocalStorage(VISITOR_STORAGE_KEY);
151
+ return existing && existing.length > 0 ? existing : null;
152
+ }
153
+ function peekSessionId(now = Date.now()) {
154
+ if (typeof window === "undefined") return null;
155
+ const raw = readLocalStorage(SESSION_STORAGE_KEY);
156
+ if (!raw) return null;
157
+ try {
158
+ const parsed = JSON.parse(raw);
159
+ if (typeof parsed.id !== "string" || typeof parsed.last_event_at !== "number") return null;
160
+ return now - parsed.last_event_at <= SESSION_IDLE_MS ? parsed.id : null;
161
+ } catch {
162
+ return null;
163
+ }
164
+ }
165
+
166
+ // ../tracking-core/src/resources/calendar/attribution.ts
167
+ var LIMITS = {
168
+ session_id: 64,
169
+ visitor_id: 64,
170
+ gclid: 256,
171
+ fbclid: 256,
172
+ utm_source: 128,
173
+ utm_medium: 128,
174
+ utm_campaign: 128,
175
+ utm_term: 128,
176
+ utm_content: 128
177
+ };
178
+ function getBookingAttribution() {
179
+ if (typeof window === "undefined") return {};
180
+ const params = getTrackingParamsFromCookieReader(getCookieValueFromDocument);
181
+ const values = {
182
+ session_id: peekSessionId(),
183
+ visitor_id: peekVisitorId(),
184
+ gclid: params.gclid,
185
+ fbclid: params.fbclid,
186
+ utm_source: params.utm_source,
187
+ utm_medium: params.utm_medium,
188
+ utm_campaign: params.utm_campaign,
189
+ utm_term: params.utm_term,
190
+ utm_content: params.utm_content
191
+ };
192
+ const attribution = {};
193
+ for (const key of Object.keys(LIMITS)) {
194
+ const value = values[key];
195
+ if (value) attribution[key] = value.slice(0, LIMITS[key]);
196
+ }
197
+ return attribution;
198
+ }
199
+
70
200
  // ../tracking-core/src/capabilities.ts
71
201
  var registered = /* @__PURE__ */ new Set();
72
202
  function registerCapability(capability) {
@@ -280,22 +410,27 @@ var zBookingRescheduleSchema = z.strictObject({
280
410
  time_zone: z.string().check(z.minLength(1), z.maxLength(64), z.regex(/^[A-Za-z0-9_+\-\/]+$/))
281
411
  });
282
412
  var zBookingResponse = z.strictObject({
413
+ all_day: z.boolean(),
283
414
  appointment_type: z.nullable(z.string()),
284
415
  calendar_key: z.string(),
416
+ created_at: z.iso.datetime({ offset: true }),
285
417
  customer: zBookingCustomerOutput,
286
418
  end_at: z.iso.datetime({ offset: true }),
419
+ google_event_id: z.nullable(z.string()),
287
420
  google_html_link: z.nullable(z.string()),
288
- google_sync_state: z.string(),
421
+ google_sync_state: z.enum(["queued", "synced", "uncertain", "failed", "drifted"]),
422
+ ical_uid: z.nullable(z.string()),
289
423
  id: z.string(),
290
424
  manage_token: z.nullable(z.string()),
291
425
  meet_url: z.nullable(z.string()),
426
+ organizer_email: z.nullable(z.string()),
292
427
  start_at: z.iso.datetime({ offset: true }),
293
- status: z.string(),
428
+ status: z.enum(["pending", "confirmed", "cancelled", "no_show"]),
294
429
  time_zone: z.string(),
295
430
  title: z.string()
296
431
  });
297
432
  var zBookingSource = z.enum(["website", "phone", "walk_in", "import", "operator"]);
298
- var zBookingMetadata = z.strictObject({
433
+ var zBookingMetadataInput = z.strictObject({
299
434
  custom: z.nullish(
300
435
  z.record(z.string(), z.nullable(z.union([z.string(), z.int(), z.number(), z.boolean()])))
301
436
  ),
@@ -315,6 +450,40 @@ var zBookingMetadata = z.strictObject({
315
450
  utm_term: z.nullish(z.string().check(z.maxLength(128))),
316
451
  visitor_id: z.nullish(z.string().check(z.maxLength(64)))
317
452
  });
453
+ var zBusySource = z.enum(["google", "booking"]);
454
+ var zBusyInterval = z.strictObject({
455
+ end_at: z.iso.datetime({ offset: true }),
456
+ source: zBusySource,
457
+ start_at: z.iso.datetime({ offset: true })
458
+ });
459
+ var zBusyWindow = z.strictObject({
460
+ since: z.iso.datetime({ offset: true }),
461
+ until: z.iso.datetime({ offset: true })
462
+ });
463
+ var zBusyResponse = z.strictObject({
464
+ busy: z.array(zBusyInterval),
465
+ calendar_key: z.string(),
466
+ generated_at: z.iso.datetime({ offset: true }),
467
+ time_zone: z.string(),
468
+ window: zBusyWindow
469
+ });
470
+ var zCalendarSummary = z.strictObject({
471
+ allow_overlaps: z.boolean(),
472
+ calendar_key: z.string(),
473
+ connected_at: z.nullable(z.iso.datetime({ offset: true })),
474
+ google_account_email: z.nullable(z.string()),
475
+ granted_scopes: z.nullable(z.array(z.string())),
476
+ label: z.string(),
477
+ status: z.enum([
478
+ "pending_invite",
479
+ "awaiting_calendar_selection",
480
+ "connected",
481
+ "needs_reconnect",
482
+ "revoked",
483
+ "disabled"
484
+ ]),
485
+ time_zone: z.string()
486
+ });
318
487
  var zCustomLocation = z.strictObject({
319
488
  kind: z.literal("custom"),
320
489
  text: z.string().check(z.maxLength(1024))
@@ -334,9 +503,19 @@ var zErrorCode = z.enum([
334
503
  "bad_request",
335
504
  "not_found",
336
505
  "conflict",
506
+ "gone",
337
507
  "incompatible_payload",
338
508
  "repeat_confirmation_required",
339
509
  "idempotency_conflict",
510
+ "slot_unavailable",
511
+ "calendar_not_connected",
512
+ "calendar_disconnected",
513
+ "booking_not_found",
514
+ "booking_not_cancellable",
515
+ "booking_not_reschedulable",
516
+ "manage_token_invalid",
517
+ "google_error",
518
+ "calendar_not_owned",
340
519
  "validation_error",
341
520
  "unknown_service",
342
521
  "invalid_sale_properties",
@@ -371,15 +550,16 @@ var zBookingCreateSchema = z.strictObject({
371
550
  buffer_before_minutes: z._default(z.optional(z.int().check(z.gte(0), z.lte(1440))), 0),
372
551
  calendar_key: z.string().check(z.minLength(1), z.maxLength(64)),
373
552
  customer: zBookingCustomerInput,
553
+ date: z.nullish(z.iso.date()),
374
554
  description: z.nullish(z.string().check(z.maxLength(8e3))),
375
555
  duration_minutes: z.nullish(z.int().check(z.gt(0), z.lte(1440))),
376
556
  end_at: z.nullish(z.iso.datetime({ offset: true })),
377
557
  idempotency_key: z.nullish(z.string().check(z.maxLength(128))),
378
558
  location: z.nullish(z.union([zMeetLocation, zPhysicalLocation, zPhoneLocation, zCustomLocation])),
379
- metadata: z.nullish(zBookingMetadata),
559
+ metadata: z.nullish(zBookingMetadataInput),
380
560
  reminders: z.nullish(zBookingReminders),
381
561
  send_invites: z._default(z.optional(z.boolean()), true),
382
- start_at: z.iso.datetime({ offset: true }),
562
+ start_at: z.nullish(z.iso.datetime({ offset: true })),
383
563
  time_zone: z.string().check(z.minLength(1), z.maxLength(64), z.regex(/^[A-Za-z0-9_+\-\/]+$/)),
384
564
  title: z.nullish(z.string().check(z.maxLength(300)))
385
565
  });
@@ -413,22 +593,17 @@ var MAX_REMINDER_OVERRIDES = 5;
413
593
  var MAX_REMINDER_MINUTES = 40320;
414
594
  var MAX_BOOKING_MINUTES = 1440;
415
595
  var BOOKING_SOURCES = ["website", "phone", "walk_in", "import", "operator"];
416
- var BOOKING_STATUSES = ["pending", "confirmed", "cancelled", "no_show"];
417
- var GOOGLE_SYNC_STATES = ["queued", "synced", "uncertain", "failed", "drifted"];
418
- var CALENDAR_SYNC_STATUSES = [
419
- "pending_invite",
420
- "awaiting_calendar_selection",
421
- "connected",
422
- "needs_reconnect",
423
- "revoked",
424
- "disabled"
425
- ];
596
+ var BOOKING_STATUSES = zBookingResponse.shape.status.options;
597
+ var GOOGLE_SYNC_STATES = zBookingResponse.shape.google_sync_state.options;
598
+ var CALENDAR_SYNC_STATUSES = zCalendarSummary.shape.status.options;
426
599
  var CALENDAR_ERROR_CODES = [
427
600
  "slot_unavailable",
428
601
  "calendar_not_connected",
429
602
  "calendar_disconnected",
430
603
  "booking_not_found",
431
- "outside_booking_window",
604
+ "booking_not_cancellable",
605
+ "booking_not_reschedulable",
606
+ "manage_token_invalid",
432
607
  "rate_limited",
433
608
  "google_error"
434
609
  ];
@@ -449,7 +624,7 @@ var ianaTz = z2.string().check(
449
624
  var bookingAttendeeSchema = zBookingAttendee;
450
625
  var bookingReminderSchema = zBookingReminder;
451
626
  var bookingCustomerSchema = zBookingCustomerInput;
452
- var bookingMetadataSchema = z2.extend(zBookingMetadata, {
627
+ var bookingMetadataSchema = z2.extend(zBookingMetadataInput, {
453
628
  custom: z2.nullish(
454
629
  z2.record(z2.string(), z2.union([z2.string(), z2.int(), z2.number(), z2.boolean(), z2.null()]))
455
630
  )
@@ -478,6 +653,24 @@ function refineEndXor(value, ctx) {
478
653
  addIssue(ctx, ["end_at"], "end_at must be after start_at");
479
654
  }
480
655
  }
656
+ function refineStartXor(value, ctx) {
657
+ const hasStart = value.start_at !== void 0 && value.start_at !== null;
658
+ const hasDate = value.date !== void 0 && value.date !== null;
659
+ if (hasStart === hasDate) {
660
+ addIssue(ctx, ["start_at"], "provide exactly one of start_at or date");
661
+ return;
662
+ }
663
+ if (hasStart) {
664
+ refineEndXor(value, ctx);
665
+ return;
666
+ }
667
+ if (value.end_at != null || value.duration_minutes != null) {
668
+ addIssue(ctx, ["date"], "an all-day booking (date) takes no end_at or duration_minutes");
669
+ }
670
+ if (value.buffer_before_minutes || value.buffer_after_minutes) {
671
+ addIssue(ctx, ["date"], "an all-day booking (date) takes no buffers");
672
+ }
673
+ }
481
674
  var bookingRemindersSchema = z2.extend(zBookingReminders, {
482
675
  overrides: z2._default(
483
676
  z2.array(bookingReminderSchema).check(z2.maxLength(MAX_REMINDER_OVERRIDES)),
@@ -496,7 +689,7 @@ var bookingCreateSchema = z2.extend(zBookingCreateSchema, {
496
689
  // our compositions into its own output.
497
690
  reminders: z2.nullish(bookingRemindersSchema),
498
691
  metadata: z2.nullish(bookingMetadataSchema)
499
- }).check((ctx) => refineEndXor(ctx.value, ctx));
692
+ }).check((ctx) => refineStartXor(ctx.value, ctx));
500
693
  var bookingRescheduleSchema = z2.extend(zBookingRescheduleSchema, { time_zone: ianaTz }).check((ctx) => refineEndXor(ctx.value, ctx));
501
694
  var bookingCancelSchema = zBookingCancelSchema;
502
695
 
@@ -614,6 +807,7 @@ function groupSlotsByDay(slots, timeZone) {
614
807
  endOfDayInTz,
615
808
  formatDateInTz,
616
809
  formatSlotRange,
810
+ getBookingAttribution,
617
811
  groupSlotsByDay,
618
812
  instantFromWallClock,
619
813
  isCalendarError,