@aranova/tracking-next 1.1.0 → 1.2.1

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/dist/index.d.mts CHANGED
@@ -6,9 +6,9 @@ export { A as ALL_AUTOMATIC_EVENT_NAMES, a as ALL_LEAD_EVENT_NAMES, b as ALL_MAN
6
6
  export { A as AranovaApiError, f as formatDateInTz } from './date-BHetnL7s.mjs';
7
7
  export { AdPlatformTracking, AdPlatformTrackingProps, ConsentBanner, ConsentBannerProps, CreateTrackingOptions, CreateTrackingResult, GoogleAdsTracking, GoogleAdsTrackingProps, PhoneField, PhoneFieldApi, PhoneFieldProps, PhoneInputProps, TrackingProviderProps, UseConsentResult, UseCookiePreferencesOptions, UseCookiePreferencesResult, UsePhoneFieldOptions, createTracking, useConsent, useConsentState, useCookiePreferences, useGclid, usePhoneConfig, usePhoneField, useTrackingParams } from '@aranova/tracking-next/client';
8
8
  import { CalendarReadClient, ComputeSlotsOptions, OpeningHours, Slot } from './calendar.mjs';
9
- export { BusyQuery, CalendarReadClientConfig, ComputeSlotsResult, OpeningInterval, computeSlots, createCalendarReadClient, durationMinutes, endOfDayInTz, formatSlotRange, groupSlotsByDay, instantFromWallClock, isCalendarError, localDateKey, offsetMinutesAt, resolveBrowserTimeZone, startOfDayInTz } from './calendar.mjs';
10
- import { a as Booking, B as BookingCreateInput, d as BusyInterval } from './transport-I_cMSFQ6.mjs';
11
- export { e as BOOKING_SOURCES, f as BOOKING_STATUSES, g as BookingAttendee, c as BookingCancelInput, h as BookingCustomer, i as BookingLocation, j as BookingMetadata, k as BookingReminders, b as BookingRescheduleInput, l as BookingStatus, m as BusyResponse, n as CALENDAR_ERROR_CODES, o as CALENDAR_METADATA_SCHEMA_VERSION, p as CALENDAR_SYNC_STATUSES, q as CalendarErrorCode, r as CalendarSummary, s as CalendarSyncStatus, C as CalendarTransportConfig, G as GOOGLE_SYNC_STATES, t as GoogleSyncState, J as JsonScalar, M as MAX_ATTENDEES, u as MAX_BOOKING_MINUTES, v as MAX_REMINDER_MINUTES, w as MAX_REMINDER_OVERRIDES, x as bookingAttendeeSchema, y as bookingCancelSchema, z as bookingCreateSchema, A as bookingCustomerSchema, D as bookingLocationNullableSchema, E as bookingLocationSchema, F as bookingMetadataSchema, H as bookingReminderSchema, I as bookingRemindersSchema, K as bookingRescheduleSchema } from './transport-I_cMSFQ6.mjs';
9
+ export { BookingAttribution, BusyQuery, CalendarReadClientConfig, ComputeSlotsResult, OpeningInterval, computeSlots, createCalendarReadClient, durationMinutes, endOfDayInTz, formatSlotRange, getBookingAttribution, groupSlotsByDay, instantFromWallClock, isCalendarError, localDateKey, offsetMinutesAt, resolveBrowserTimeZone, startOfDayInTz } from './calendar.mjs';
10
+ import { a as Booking, B as BookingCreateInput, d as BusyInterval } from './transport-DvAEZ1xf.mjs';
11
+ export { e as BOOKING_SOURCES, f as BOOKING_STATUSES, g as BookingAttendee, c as BookingCancelInput, h as BookingCustomer, i as BookingLocation, j as BookingMetadata, k as BookingReminders, b as BookingRescheduleInput, l as BookingStatus, m as BusyResponse, n as CALENDAR_ERROR_CODES, o as CALENDAR_METADATA_SCHEMA_VERSION, p as CALENDAR_SYNC_STATUSES, q as CalendarErrorCode, r as CalendarSummary, s as CalendarSyncStatus, C as CalendarTransportConfig, G as GOOGLE_SYNC_STATES, t as GoogleSyncState, J as JsonScalar, M as MAX_ATTENDEES, u as MAX_BOOKING_MINUTES, v as MAX_REMINDER_MINUTES, w as MAX_REMINDER_OVERRIDES, x as bookingAttendeeSchema, y as bookingCancelSchema, z as bookingCreateSchema, A as bookingCustomerSchema, D as bookingLocationNullableSchema, E as bookingLocationSchema, F as bookingMetadataSchema, H as bookingReminderSchema, I as bookingRemindersSchema, K as bookingRescheduleSchema } from './transport-DvAEZ1xf.mjs';
12
12
  import { ReactNode } from 'react';
13
13
  export { CountryCode } from 'libphonenumber-js';
14
14
  import 'zod/mini';
@@ -154,7 +154,8 @@ interface UseBookingFormResult {
154
154
  * Submit state for a booking.
155
155
  *
156
156
  * Posts to the SITE's own route handler, not to us: a booking needs a secret
157
- * key, which must never reach a browser bundle.
157
+ * key, which must never reach a browser bundle. The visit's attribution fills any
158
+ * `metadata` key the caller left unset, so the booking links to its journey.
158
159
  */
159
160
  declare function useBookingForm(options?: UseBookingFormOptions): UseBookingFormResult;
160
161
 
package/dist/index.d.ts CHANGED
@@ -6,9 +6,9 @@ export { A as ALL_AUTOMATIC_EVENT_NAMES, a as ALL_LEAD_EVENT_NAMES, b as ALL_MAN
6
6
  export { A as AranovaApiError, f as formatDateInTz } from './date-BHetnL7s.js';
7
7
  export { AdPlatformTracking, AdPlatformTrackingProps, ConsentBanner, ConsentBannerProps, CreateTrackingOptions, CreateTrackingResult, GoogleAdsTracking, GoogleAdsTrackingProps, PhoneField, PhoneFieldApi, PhoneFieldProps, PhoneInputProps, TrackingProviderProps, UseConsentResult, UseCookiePreferencesOptions, UseCookiePreferencesResult, UsePhoneFieldOptions, createTracking, useConsent, useConsentState, useCookiePreferences, useGclid, usePhoneConfig, usePhoneField, useTrackingParams } from '@aranova/tracking-next/client';
8
8
  import { CalendarReadClient, ComputeSlotsOptions, OpeningHours, Slot } from './calendar.js';
9
- export { BusyQuery, CalendarReadClientConfig, ComputeSlotsResult, OpeningInterval, computeSlots, createCalendarReadClient, durationMinutes, endOfDayInTz, formatSlotRange, groupSlotsByDay, instantFromWallClock, isCalendarError, localDateKey, offsetMinutesAt, resolveBrowserTimeZone, startOfDayInTz } from './calendar.js';
10
- import { a as Booking, B as BookingCreateInput, d as BusyInterval } from './transport-CDmGOiCq.js';
11
- export { e as BOOKING_SOURCES, f as BOOKING_STATUSES, g as BookingAttendee, c as BookingCancelInput, h as BookingCustomer, i as BookingLocation, j as BookingMetadata, k as BookingReminders, b as BookingRescheduleInput, l as BookingStatus, m as BusyResponse, n as CALENDAR_ERROR_CODES, o as CALENDAR_METADATA_SCHEMA_VERSION, p as CALENDAR_SYNC_STATUSES, q as CalendarErrorCode, r as CalendarSummary, s as CalendarSyncStatus, C as CalendarTransportConfig, G as GOOGLE_SYNC_STATES, t as GoogleSyncState, J as JsonScalar, M as MAX_ATTENDEES, u as MAX_BOOKING_MINUTES, v as MAX_REMINDER_MINUTES, w as MAX_REMINDER_OVERRIDES, x as bookingAttendeeSchema, y as bookingCancelSchema, z as bookingCreateSchema, A as bookingCustomerSchema, D as bookingLocationNullableSchema, E as bookingLocationSchema, F as bookingMetadataSchema, H as bookingReminderSchema, I as bookingRemindersSchema, K as bookingRescheduleSchema } from './transport-CDmGOiCq.js';
9
+ export { BookingAttribution, BusyQuery, CalendarReadClientConfig, ComputeSlotsResult, OpeningInterval, computeSlots, createCalendarReadClient, durationMinutes, endOfDayInTz, formatSlotRange, getBookingAttribution, groupSlotsByDay, instantFromWallClock, isCalendarError, localDateKey, offsetMinutesAt, resolveBrowserTimeZone, startOfDayInTz } from './calendar.js';
10
+ import { a as Booking, B as BookingCreateInput, d as BusyInterval } from './transport-ChCL6vPv.js';
11
+ export { e as BOOKING_SOURCES, f as BOOKING_STATUSES, g as BookingAttendee, c as BookingCancelInput, h as BookingCustomer, i as BookingLocation, j as BookingMetadata, k as BookingReminders, b as BookingRescheduleInput, l as BookingStatus, m as BusyResponse, n as CALENDAR_ERROR_CODES, o as CALENDAR_METADATA_SCHEMA_VERSION, p as CALENDAR_SYNC_STATUSES, q as CalendarErrorCode, r as CalendarSummary, s as CalendarSyncStatus, C as CalendarTransportConfig, G as GOOGLE_SYNC_STATES, t as GoogleSyncState, J as JsonScalar, M as MAX_ATTENDEES, u as MAX_BOOKING_MINUTES, v as MAX_REMINDER_MINUTES, w as MAX_REMINDER_OVERRIDES, x as bookingAttendeeSchema, y as bookingCancelSchema, z as bookingCreateSchema, A as bookingCustomerSchema, D as bookingLocationNullableSchema, E as bookingLocationSchema, F as bookingMetadataSchema, H as bookingReminderSchema, I as bookingRemindersSchema, K as bookingRescheduleSchema } from './transport-ChCL6vPv.js';
12
12
  import { ReactNode } from 'react';
13
13
  export { CountryCode } from 'libphonenumber-js';
14
14
  import 'zod/mini';
@@ -154,7 +154,8 @@ interface UseBookingFormResult {
154
154
  * Submit state for a booking.
155
155
  *
156
156
  * Posts to the SITE's own route handler, not to us: a booking needs a secret
157
- * key, which must never reach a browser bundle.
157
+ * key, which must never reach a browser bundle. The visit's attribution fills any
158
+ * `metadata` key the caller left unset, so the booking links to its journey.
158
159
  */
159
160
  declare function useBookingForm(options?: UseBookingFormOptions): UseBookingFormResult;
160
161
 
package/dist/index.js CHANGED
@@ -82,6 +82,7 @@ __export(src_exports, {
82
82
  formatPhoneAsTyped: () => formatPhoneAsTyped,
83
83
  formatSlotRange: () => formatSlotRange,
84
84
  fromMinor: () => fromMinor,
85
+ getBookingAttribution: () => getBookingAttribution,
85
86
  getConsentChoice: () => getConsentChoice,
86
87
  getConsentState: () => getConsentState,
87
88
  getEventSemantics: () => getEventSemantics,
@@ -613,6 +614,35 @@ function buildLandingPayloadFields(sessionId, override) {
613
614
  };
614
615
  }
615
616
 
617
+ // ../tracking-core/src/session.ts
618
+ var VISITOR_STORAGE_KEY = "aranova_tracking_visitor";
619
+ var SESSION_STORAGE_KEY = "aranova_tracking_session";
620
+ var SESSION_IDLE_MS = 30 * 60 * 1e3;
621
+ function readLocalStorage(key) {
622
+ try {
623
+ return window.localStorage.getItem(key);
624
+ } catch {
625
+ return null;
626
+ }
627
+ }
628
+ function peekVisitorId() {
629
+ if (typeof window === "undefined") return null;
630
+ const existing = readLocalStorage(VISITOR_STORAGE_KEY);
631
+ return existing && existing.length > 0 ? existing : null;
632
+ }
633
+ function peekSessionId(now = Date.now()) {
634
+ if (typeof window === "undefined") return null;
635
+ const raw = readLocalStorage(SESSION_STORAGE_KEY);
636
+ if (!raw) return null;
637
+ try {
638
+ const parsed = JSON.parse(raw);
639
+ if (typeof parsed.id !== "string" || typeof parsed.last_event_at !== "number") return null;
640
+ return now - parsed.last_event_at <= SESSION_IDLE_MS ? parsed.id : null;
641
+ } catch {
642
+ return null;
643
+ }
644
+ }
645
+
616
646
  // ../tracking-core/src/cross-site-link.ts
617
647
  var LINK_PARAM = "_arv";
618
648
  var LINK_TOKEN_TTL_MS = 5 * 60 * 1e3;
@@ -1775,9 +1805,23 @@ var zErrorCode = z2.enum([
1775
1805
  "bad_request",
1776
1806
  "not_found",
1777
1807
  "conflict",
1808
+ "gone",
1778
1809
  "incompatible_payload",
1779
1810
  "repeat_confirmation_required",
1780
1811
  "idempotency_conflict",
1812
+ "slot_unavailable",
1813
+ "calendar_not_connected",
1814
+ "calendar_disconnected",
1815
+ "booking_not_found",
1816
+ "booking_not_cancellable",
1817
+ "booking_not_reschedulable",
1818
+ "manage_token_invalid",
1819
+ "google_error",
1820
+ "calendar_not_owned",
1821
+ "calendar_is_sandbox",
1822
+ "sandbox_exists",
1823
+ "sandbox_key_too_long",
1824
+ "sandbox_not_found",
1781
1825
  "validation_error",
1782
1826
  "unknown_service",
1783
1827
  "invalid_sale_properties",
@@ -1841,6 +1885,7 @@ var zSmsWithheldReason = z2.enum([
1841
1885
  "no_handler",
1842
1886
  "dispatch_already_recorded",
1843
1887
  "text_back_disabled",
1888
+ "number_text_back_disabled",
1844
1889
  "number_not_active",
1845
1890
  "a2p_registration_required",
1846
1891
  "alert_recipient_cannot_receive_sms",
@@ -2047,6 +2092,40 @@ function phoneField(name, raw, country) {
2047
2092
  // src/index.ts
2048
2093
  var import_client = require("@aranova/tracking-next/client");
2049
2094
 
2095
+ // ../tracking-core/src/resources/calendar/attribution.ts
2096
+ var LIMITS = {
2097
+ session_id: 64,
2098
+ visitor_id: 64,
2099
+ gclid: 256,
2100
+ fbclid: 256,
2101
+ utm_source: 128,
2102
+ utm_medium: 128,
2103
+ utm_campaign: 128,
2104
+ utm_term: 128,
2105
+ utm_content: 128
2106
+ };
2107
+ function getBookingAttribution() {
2108
+ if (typeof window === "undefined") return {};
2109
+ const params = getTrackingParamsFromCookieReader(getCookieValueFromDocument);
2110
+ const values = {
2111
+ session_id: peekSessionId(),
2112
+ visitor_id: peekVisitorId(),
2113
+ gclid: params.gclid,
2114
+ fbclid: params.fbclid,
2115
+ utm_source: params.utm_source,
2116
+ utm_medium: params.utm_medium,
2117
+ utm_campaign: params.utm_campaign,
2118
+ utm_term: params.utm_term,
2119
+ utm_content: params.utm_content
2120
+ };
2121
+ const attribution = {};
2122
+ for (const key of Object.keys(LIMITS)) {
2123
+ const value = values[key];
2124
+ if (value) attribution[key] = value.slice(0, LIMITS[key]);
2125
+ }
2126
+ return attribution;
2127
+ }
2128
+
2050
2129
  // ../tracking-core/src/resources/calendar/transport.ts
2051
2130
  async function calendarRequest(config, method, path, body) {
2052
2131
  return apiRequest(config, method, `/calendar${path}`, body);
@@ -2179,22 +2258,27 @@ var zBookingRescheduleSchema = z4.strictObject({
2179
2258
  time_zone: z4.string().check(z4.minLength(1), z4.maxLength(64), z4.regex(/^[A-Za-z0-9_+\-\/]+$/))
2180
2259
  });
2181
2260
  var zBookingResponse = z4.strictObject({
2261
+ all_day: z4.boolean(),
2182
2262
  appointment_type: z4.nullable(z4.string()),
2183
2263
  calendar_key: z4.string(),
2264
+ created_at: z4.iso.datetime({ offset: true }),
2184
2265
  customer: zBookingCustomerOutput,
2185
2266
  end_at: z4.iso.datetime({ offset: true }),
2267
+ google_event_id: z4.nullable(z4.string()),
2186
2268
  google_html_link: z4.nullable(z4.string()),
2187
- google_sync_state: z4.string(),
2269
+ google_sync_state: z4.enum(["queued", "synced", "uncertain", "failed", "drifted"]),
2270
+ ical_uid: z4.nullable(z4.string()),
2188
2271
  id: z4.string(),
2189
2272
  manage_token: z4.nullable(z4.string()),
2190
2273
  meet_url: z4.nullable(z4.string()),
2274
+ organizer_email: z4.nullable(z4.string()),
2191
2275
  start_at: z4.iso.datetime({ offset: true }),
2192
- status: z4.string(),
2276
+ status: z4.enum(["pending", "confirmed", "cancelled", "no_show"]),
2193
2277
  time_zone: z4.string(),
2194
2278
  title: z4.string()
2195
2279
  });
2196
2280
  var zBookingSource = z4.enum(["website", "phone", "walk_in", "import", "operator"]);
2197
- var zBookingMetadata = z4.strictObject({
2281
+ var zBookingMetadataInput = z4.strictObject({
2198
2282
  custom: z4.nullish(
2199
2283
  z4.record(z4.string(), z4.nullable(z4.union([z4.string(), z4.int(), z4.number(), z4.boolean()])))
2200
2284
  ),
@@ -2214,6 +2298,42 @@ var zBookingMetadata = z4.strictObject({
2214
2298
  utm_term: z4.nullish(z4.string().check(z4.maxLength(128))),
2215
2299
  visitor_id: z4.nullish(z4.string().check(z4.maxLength(64)))
2216
2300
  });
2301
+ var zBusySource = z4.enum(["google", "booking"]);
2302
+ var zBusyInterval = z4.strictObject({
2303
+ end_at: z4.iso.datetime({ offset: true }),
2304
+ source: zBusySource,
2305
+ start_at: z4.iso.datetime({ offset: true })
2306
+ });
2307
+ var zBusyWindow = z4.strictObject({
2308
+ since: z4.iso.datetime({ offset: true }),
2309
+ until: z4.iso.datetime({ offset: true })
2310
+ });
2311
+ var zBusyResponse = z4.strictObject({
2312
+ busy: z4.array(zBusyInterval),
2313
+ calendar_key: z4.string(),
2314
+ generated_at: z4.iso.datetime({ offset: true }),
2315
+ time_zone: z4.string(),
2316
+ window: zBusyWindow
2317
+ });
2318
+ var zCalendarSummary = z4.strictObject({
2319
+ allow_overlaps: z4.boolean(),
2320
+ calendar_key: z4.string(),
2321
+ connected_at: z4.nullable(z4.iso.datetime({ offset: true })),
2322
+ google_account_email: z4.nullable(z4.string()),
2323
+ granted_scopes: z4.nullable(z4.array(z4.string())),
2324
+ is_sandbox: z4.boolean(),
2325
+ label: z4.string(),
2326
+ sandbox_key: z4.nullable(z4.string()),
2327
+ status: z4.enum([
2328
+ "pending_invite",
2329
+ "awaiting_calendar_selection",
2330
+ "connected",
2331
+ "needs_reconnect",
2332
+ "revoked",
2333
+ "disabled"
2334
+ ]),
2335
+ time_zone: z4.string()
2336
+ });
2217
2337
  var zCustomLocation = z4.strictObject({
2218
2338
  kind: z4.literal("custom"),
2219
2339
  text: z4.string().check(z4.maxLength(1024))
@@ -2233,9 +2353,23 @@ var zErrorCode2 = z4.enum([
2233
2353
  "bad_request",
2234
2354
  "not_found",
2235
2355
  "conflict",
2356
+ "gone",
2236
2357
  "incompatible_payload",
2237
2358
  "repeat_confirmation_required",
2238
2359
  "idempotency_conflict",
2360
+ "slot_unavailable",
2361
+ "calendar_not_connected",
2362
+ "calendar_disconnected",
2363
+ "booking_not_found",
2364
+ "booking_not_cancellable",
2365
+ "booking_not_reschedulable",
2366
+ "manage_token_invalid",
2367
+ "google_error",
2368
+ "calendar_not_owned",
2369
+ "calendar_is_sandbox",
2370
+ "sandbox_exists",
2371
+ "sandbox_key_too_long",
2372
+ "sandbox_not_found",
2239
2373
  "validation_error",
2240
2374
  "unknown_service",
2241
2375
  "invalid_sale_properties",
@@ -2270,15 +2404,16 @@ var zBookingCreateSchema = z4.strictObject({
2270
2404
  buffer_before_minutes: z4._default(z4.optional(z4.int().check(z4.gte(0), z4.lte(1440))), 0),
2271
2405
  calendar_key: z4.string().check(z4.minLength(1), z4.maxLength(64)),
2272
2406
  customer: zBookingCustomerInput,
2407
+ date: z4.nullish(z4.iso.date()),
2273
2408
  description: z4.nullish(z4.string().check(z4.maxLength(8e3))),
2274
2409
  duration_minutes: z4.nullish(z4.int().check(z4.gt(0), z4.lte(1440))),
2275
2410
  end_at: z4.nullish(z4.iso.datetime({ offset: true })),
2276
2411
  idempotency_key: z4.nullish(z4.string().check(z4.maxLength(128))),
2277
2412
  location: z4.nullish(z4.union([zMeetLocation, zPhysicalLocation, zPhoneLocation, zCustomLocation])),
2278
- metadata: z4.nullish(zBookingMetadata),
2413
+ metadata: z4.nullish(zBookingMetadataInput),
2279
2414
  reminders: z4.nullish(zBookingReminders),
2280
2415
  send_invites: z4._default(z4.optional(z4.boolean()), true),
2281
- start_at: z4.iso.datetime({ offset: true }),
2416
+ start_at: z4.nullish(z4.iso.datetime({ offset: true })),
2282
2417
  time_zone: z4.string().check(z4.minLength(1), z4.maxLength(64), z4.regex(/^[A-Za-z0-9_+\-\/]+$/)),
2283
2418
  title: z4.nullish(z4.string().check(z4.maxLength(300)))
2284
2419
  });
@@ -2312,22 +2447,17 @@ var MAX_REMINDER_OVERRIDES = 5;
2312
2447
  var MAX_REMINDER_MINUTES = 40320;
2313
2448
  var MAX_BOOKING_MINUTES = 1440;
2314
2449
  var BOOKING_SOURCES = ["website", "phone", "walk_in", "import", "operator"];
2315
- var BOOKING_STATUSES = ["pending", "confirmed", "cancelled", "no_show"];
2316
- var GOOGLE_SYNC_STATES = ["queued", "synced", "uncertain", "failed", "drifted"];
2317
- var CALENDAR_SYNC_STATUSES = [
2318
- "pending_invite",
2319
- "awaiting_calendar_selection",
2320
- "connected",
2321
- "needs_reconnect",
2322
- "revoked",
2323
- "disabled"
2324
- ];
2450
+ var BOOKING_STATUSES = zBookingResponse.shape.status.options;
2451
+ var GOOGLE_SYNC_STATES = zBookingResponse.shape.google_sync_state.options;
2452
+ var CALENDAR_SYNC_STATUSES = zCalendarSummary.shape.status.options;
2325
2453
  var CALENDAR_ERROR_CODES = [
2326
2454
  "slot_unavailable",
2327
2455
  "calendar_not_connected",
2328
2456
  "calendar_disconnected",
2329
2457
  "booking_not_found",
2330
- "outside_booking_window",
2458
+ "booking_not_cancellable",
2459
+ "booking_not_reschedulable",
2460
+ "manage_token_invalid",
2331
2461
  "rate_limited",
2332
2462
  "google_error"
2333
2463
  ];
@@ -2348,7 +2478,7 @@ var ianaTz = z5.string().check(
2348
2478
  var bookingAttendeeSchema = zBookingAttendee;
2349
2479
  var bookingReminderSchema = zBookingReminder;
2350
2480
  var bookingCustomerSchema = zBookingCustomerInput;
2351
- var bookingMetadataSchema = z5.extend(zBookingMetadata, {
2481
+ var bookingMetadataSchema = z5.extend(zBookingMetadataInput, {
2352
2482
  custom: z5.nullish(
2353
2483
  z5.record(z5.string(), z5.union([z5.string(), z5.int(), z5.number(), z5.boolean(), z5.null()]))
2354
2484
  )
@@ -2377,6 +2507,24 @@ function refineEndXor(value, ctx) {
2377
2507
  addIssue2(ctx, ["end_at"], "end_at must be after start_at");
2378
2508
  }
2379
2509
  }
2510
+ function refineStartXor(value, ctx) {
2511
+ const hasStart = value.start_at !== void 0 && value.start_at !== null;
2512
+ const hasDate = value.date !== void 0 && value.date !== null;
2513
+ if (hasStart === hasDate) {
2514
+ addIssue2(ctx, ["start_at"], "provide exactly one of start_at or date");
2515
+ return;
2516
+ }
2517
+ if (hasStart) {
2518
+ refineEndXor(value, ctx);
2519
+ return;
2520
+ }
2521
+ if (value.end_at != null || value.duration_minutes != null) {
2522
+ addIssue2(ctx, ["date"], "an all-day booking (date) takes no end_at or duration_minutes");
2523
+ }
2524
+ if (value.buffer_before_minutes || value.buffer_after_minutes) {
2525
+ addIssue2(ctx, ["date"], "an all-day booking (date) takes no buffers");
2526
+ }
2527
+ }
2380
2528
  var bookingRemindersSchema = z5.extend(zBookingReminders, {
2381
2529
  overrides: z5._default(
2382
2530
  z5.array(bookingReminderSchema).check(z5.maxLength(MAX_REMINDER_OVERRIDES)),
@@ -2395,7 +2543,7 @@ var bookingCreateSchema = z5.extend(zBookingCreateSchema, {
2395
2543
  // our compositions into its own output.
2396
2544
  reminders: z5.nullish(bookingRemindersSchema),
2397
2545
  metadata: z5.nullish(bookingMetadataSchema)
2398
- }).check((ctx) => refineEndXor(ctx.value, ctx));
2546
+ }).check((ctx) => refineStartXor(ctx.value, ctx));
2399
2547
  var bookingRescheduleSchema = z5.extend(zBookingRescheduleSchema, { time_zone: ianaTz }).check((ctx) => refineEndXor(ctx.value, ctx));
2400
2548
  var bookingCancelSchema = zBookingCancelSchema;
2401
2549
 
@@ -2554,7 +2702,10 @@ function useBookingForm(options = {}) {
2554
2702
  const response = await fetch(endpoint, {
2555
2703
  method: "POST",
2556
2704
  headers: { "Content-Type": "application/json" },
2557
- body: JSON.stringify(input)
2705
+ body: JSON.stringify({
2706
+ ...input,
2707
+ metadata: { ...getBookingAttribution(), ...input.metadata }
2708
+ })
2558
2709
  });
2559
2710
  const body = await response.json().catch(() => null);
2560
2711
  if (!response.ok) {
@@ -2635,6 +2786,7 @@ var import_client2 = require("@aranova/tracking-next/client");
2635
2786
  formatPhoneAsTyped,
2636
2787
  formatSlotRange,
2637
2788
  fromMinor,
2789
+ getBookingAttribution,
2638
2790
  getConsentChoice,
2639
2791
  getConsentState,
2640
2792
  getEventSemantics,