@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.mjs CHANGED
@@ -487,6 +487,35 @@ function buildLandingPayloadFields(sessionId, override) {
487
487
  };
488
488
  }
489
489
 
490
+ // ../tracking-core/src/session.ts
491
+ var VISITOR_STORAGE_KEY = "aranova_tracking_visitor";
492
+ var SESSION_STORAGE_KEY = "aranova_tracking_session";
493
+ var SESSION_IDLE_MS = 30 * 60 * 1e3;
494
+ function readLocalStorage(key) {
495
+ try {
496
+ return window.localStorage.getItem(key);
497
+ } catch {
498
+ return null;
499
+ }
500
+ }
501
+ function peekVisitorId() {
502
+ if (typeof window === "undefined") return null;
503
+ const existing = readLocalStorage(VISITOR_STORAGE_KEY);
504
+ return existing && existing.length > 0 ? existing : null;
505
+ }
506
+ function peekSessionId(now = Date.now()) {
507
+ if (typeof window === "undefined") return null;
508
+ const raw = readLocalStorage(SESSION_STORAGE_KEY);
509
+ if (!raw) return null;
510
+ try {
511
+ const parsed = JSON.parse(raw);
512
+ if (typeof parsed.id !== "string" || typeof parsed.last_event_at !== "number") return null;
513
+ return now - parsed.last_event_at <= SESSION_IDLE_MS ? parsed.id : null;
514
+ } catch {
515
+ return null;
516
+ }
517
+ }
518
+
490
519
  // ../tracking-core/src/cross-site-link.ts
491
520
  var LINK_PARAM = "_arv";
492
521
  var LINK_TOKEN_TTL_MS = 5 * 60 * 1e3;
@@ -1649,9 +1678,23 @@ var zErrorCode = z2.enum([
1649
1678
  "bad_request",
1650
1679
  "not_found",
1651
1680
  "conflict",
1681
+ "gone",
1652
1682
  "incompatible_payload",
1653
1683
  "repeat_confirmation_required",
1654
1684
  "idempotency_conflict",
1685
+ "slot_unavailable",
1686
+ "calendar_not_connected",
1687
+ "calendar_disconnected",
1688
+ "booking_not_found",
1689
+ "booking_not_cancellable",
1690
+ "booking_not_reschedulable",
1691
+ "manage_token_invalid",
1692
+ "google_error",
1693
+ "calendar_not_owned",
1694
+ "calendar_is_sandbox",
1695
+ "sandbox_exists",
1696
+ "sandbox_key_too_long",
1697
+ "sandbox_not_found",
1655
1698
  "validation_error",
1656
1699
  "unknown_service",
1657
1700
  "invalid_sale_properties",
@@ -1715,6 +1758,7 @@ var zSmsWithheldReason = z2.enum([
1715
1758
  "no_handler",
1716
1759
  "dispatch_already_recorded",
1717
1760
  "text_back_disabled",
1761
+ "number_text_back_disabled",
1718
1762
  "number_not_active",
1719
1763
  "a2p_registration_required",
1720
1764
  "alert_recipient_cannot_receive_sms",
@@ -1931,6 +1975,40 @@ import {
1931
1975
  useTrackingParams
1932
1976
  } from "@aranova/tracking-next/client";
1933
1977
 
1978
+ // ../tracking-core/src/resources/calendar/attribution.ts
1979
+ var LIMITS = {
1980
+ session_id: 64,
1981
+ visitor_id: 64,
1982
+ gclid: 256,
1983
+ fbclid: 256,
1984
+ utm_source: 128,
1985
+ utm_medium: 128,
1986
+ utm_campaign: 128,
1987
+ utm_term: 128,
1988
+ utm_content: 128
1989
+ };
1990
+ function getBookingAttribution() {
1991
+ if (typeof window === "undefined") return {};
1992
+ const params = getTrackingParamsFromCookieReader(getCookieValueFromDocument);
1993
+ const values = {
1994
+ session_id: peekSessionId(),
1995
+ visitor_id: peekVisitorId(),
1996
+ gclid: params.gclid,
1997
+ fbclid: params.fbclid,
1998
+ utm_source: params.utm_source,
1999
+ utm_medium: params.utm_medium,
2000
+ utm_campaign: params.utm_campaign,
2001
+ utm_term: params.utm_term,
2002
+ utm_content: params.utm_content
2003
+ };
2004
+ const attribution = {};
2005
+ for (const key of Object.keys(LIMITS)) {
2006
+ const value = values[key];
2007
+ if (value) attribution[key] = value.slice(0, LIMITS[key]);
2008
+ }
2009
+ return attribution;
2010
+ }
2011
+
1934
2012
  // ../tracking-core/src/resources/calendar/transport.ts
1935
2013
  async function calendarRequest(config, method, path, body) {
1936
2014
  return apiRequest(config, method, `/calendar${path}`, body);
@@ -2063,22 +2141,27 @@ var zBookingRescheduleSchema = z4.strictObject({
2063
2141
  time_zone: z4.string().check(z4.minLength(1), z4.maxLength(64), z4.regex(/^[A-Za-z0-9_+\-\/]+$/))
2064
2142
  });
2065
2143
  var zBookingResponse = z4.strictObject({
2144
+ all_day: z4.boolean(),
2066
2145
  appointment_type: z4.nullable(z4.string()),
2067
2146
  calendar_key: z4.string(),
2147
+ created_at: z4.iso.datetime({ offset: true }),
2068
2148
  customer: zBookingCustomerOutput,
2069
2149
  end_at: z4.iso.datetime({ offset: true }),
2150
+ google_event_id: z4.nullable(z4.string()),
2070
2151
  google_html_link: z4.nullable(z4.string()),
2071
- google_sync_state: z4.string(),
2152
+ google_sync_state: z4.enum(["queued", "synced", "uncertain", "failed", "drifted"]),
2153
+ ical_uid: z4.nullable(z4.string()),
2072
2154
  id: z4.string(),
2073
2155
  manage_token: z4.nullable(z4.string()),
2074
2156
  meet_url: z4.nullable(z4.string()),
2157
+ organizer_email: z4.nullable(z4.string()),
2075
2158
  start_at: z4.iso.datetime({ offset: true }),
2076
- status: z4.string(),
2159
+ status: z4.enum(["pending", "confirmed", "cancelled", "no_show"]),
2077
2160
  time_zone: z4.string(),
2078
2161
  title: z4.string()
2079
2162
  });
2080
2163
  var zBookingSource = z4.enum(["website", "phone", "walk_in", "import", "operator"]);
2081
- var zBookingMetadata = z4.strictObject({
2164
+ var zBookingMetadataInput = z4.strictObject({
2082
2165
  custom: z4.nullish(
2083
2166
  z4.record(z4.string(), z4.nullable(z4.union([z4.string(), z4.int(), z4.number(), z4.boolean()])))
2084
2167
  ),
@@ -2098,6 +2181,42 @@ var zBookingMetadata = z4.strictObject({
2098
2181
  utm_term: z4.nullish(z4.string().check(z4.maxLength(128))),
2099
2182
  visitor_id: z4.nullish(z4.string().check(z4.maxLength(64)))
2100
2183
  });
2184
+ var zBusySource = z4.enum(["google", "booking"]);
2185
+ var zBusyInterval = z4.strictObject({
2186
+ end_at: z4.iso.datetime({ offset: true }),
2187
+ source: zBusySource,
2188
+ start_at: z4.iso.datetime({ offset: true })
2189
+ });
2190
+ var zBusyWindow = z4.strictObject({
2191
+ since: z4.iso.datetime({ offset: true }),
2192
+ until: z4.iso.datetime({ offset: true })
2193
+ });
2194
+ var zBusyResponse = z4.strictObject({
2195
+ busy: z4.array(zBusyInterval),
2196
+ calendar_key: z4.string(),
2197
+ generated_at: z4.iso.datetime({ offset: true }),
2198
+ time_zone: z4.string(),
2199
+ window: zBusyWindow
2200
+ });
2201
+ var zCalendarSummary = z4.strictObject({
2202
+ allow_overlaps: z4.boolean(),
2203
+ calendar_key: z4.string(),
2204
+ connected_at: z4.nullable(z4.iso.datetime({ offset: true })),
2205
+ google_account_email: z4.nullable(z4.string()),
2206
+ granted_scopes: z4.nullable(z4.array(z4.string())),
2207
+ is_sandbox: z4.boolean(),
2208
+ label: z4.string(),
2209
+ sandbox_key: z4.nullable(z4.string()),
2210
+ status: z4.enum([
2211
+ "pending_invite",
2212
+ "awaiting_calendar_selection",
2213
+ "connected",
2214
+ "needs_reconnect",
2215
+ "revoked",
2216
+ "disabled"
2217
+ ]),
2218
+ time_zone: z4.string()
2219
+ });
2101
2220
  var zCustomLocation = z4.strictObject({
2102
2221
  kind: z4.literal("custom"),
2103
2222
  text: z4.string().check(z4.maxLength(1024))
@@ -2117,9 +2236,23 @@ var zErrorCode2 = z4.enum([
2117
2236
  "bad_request",
2118
2237
  "not_found",
2119
2238
  "conflict",
2239
+ "gone",
2120
2240
  "incompatible_payload",
2121
2241
  "repeat_confirmation_required",
2122
2242
  "idempotency_conflict",
2243
+ "slot_unavailable",
2244
+ "calendar_not_connected",
2245
+ "calendar_disconnected",
2246
+ "booking_not_found",
2247
+ "booking_not_cancellable",
2248
+ "booking_not_reschedulable",
2249
+ "manage_token_invalid",
2250
+ "google_error",
2251
+ "calendar_not_owned",
2252
+ "calendar_is_sandbox",
2253
+ "sandbox_exists",
2254
+ "sandbox_key_too_long",
2255
+ "sandbox_not_found",
2123
2256
  "validation_error",
2124
2257
  "unknown_service",
2125
2258
  "invalid_sale_properties",
@@ -2154,15 +2287,16 @@ var zBookingCreateSchema = z4.strictObject({
2154
2287
  buffer_before_minutes: z4._default(z4.optional(z4.int().check(z4.gte(0), z4.lte(1440))), 0),
2155
2288
  calendar_key: z4.string().check(z4.minLength(1), z4.maxLength(64)),
2156
2289
  customer: zBookingCustomerInput,
2290
+ date: z4.nullish(z4.iso.date()),
2157
2291
  description: z4.nullish(z4.string().check(z4.maxLength(8e3))),
2158
2292
  duration_minutes: z4.nullish(z4.int().check(z4.gt(0), z4.lte(1440))),
2159
2293
  end_at: z4.nullish(z4.iso.datetime({ offset: true })),
2160
2294
  idempotency_key: z4.nullish(z4.string().check(z4.maxLength(128))),
2161
2295
  location: z4.nullish(z4.union([zMeetLocation, zPhysicalLocation, zPhoneLocation, zCustomLocation])),
2162
- metadata: z4.nullish(zBookingMetadata),
2296
+ metadata: z4.nullish(zBookingMetadataInput),
2163
2297
  reminders: z4.nullish(zBookingReminders),
2164
2298
  send_invites: z4._default(z4.optional(z4.boolean()), true),
2165
- start_at: z4.iso.datetime({ offset: true }),
2299
+ start_at: z4.nullish(z4.iso.datetime({ offset: true })),
2166
2300
  time_zone: z4.string().check(z4.minLength(1), z4.maxLength(64), z4.regex(/^[A-Za-z0-9_+\-\/]+$/)),
2167
2301
  title: z4.nullish(z4.string().check(z4.maxLength(300)))
2168
2302
  });
@@ -2196,22 +2330,17 @@ var MAX_REMINDER_OVERRIDES = 5;
2196
2330
  var MAX_REMINDER_MINUTES = 40320;
2197
2331
  var MAX_BOOKING_MINUTES = 1440;
2198
2332
  var BOOKING_SOURCES = ["website", "phone", "walk_in", "import", "operator"];
2199
- var BOOKING_STATUSES = ["pending", "confirmed", "cancelled", "no_show"];
2200
- var GOOGLE_SYNC_STATES = ["queued", "synced", "uncertain", "failed", "drifted"];
2201
- var CALENDAR_SYNC_STATUSES = [
2202
- "pending_invite",
2203
- "awaiting_calendar_selection",
2204
- "connected",
2205
- "needs_reconnect",
2206
- "revoked",
2207
- "disabled"
2208
- ];
2333
+ var BOOKING_STATUSES = zBookingResponse.shape.status.options;
2334
+ var GOOGLE_SYNC_STATES = zBookingResponse.shape.google_sync_state.options;
2335
+ var CALENDAR_SYNC_STATUSES = zCalendarSummary.shape.status.options;
2209
2336
  var CALENDAR_ERROR_CODES = [
2210
2337
  "slot_unavailable",
2211
2338
  "calendar_not_connected",
2212
2339
  "calendar_disconnected",
2213
2340
  "booking_not_found",
2214
- "outside_booking_window",
2341
+ "booking_not_cancellable",
2342
+ "booking_not_reschedulable",
2343
+ "manage_token_invalid",
2215
2344
  "rate_limited",
2216
2345
  "google_error"
2217
2346
  ];
@@ -2232,7 +2361,7 @@ var ianaTz = z5.string().check(
2232
2361
  var bookingAttendeeSchema = zBookingAttendee;
2233
2362
  var bookingReminderSchema = zBookingReminder;
2234
2363
  var bookingCustomerSchema = zBookingCustomerInput;
2235
- var bookingMetadataSchema = z5.extend(zBookingMetadata, {
2364
+ var bookingMetadataSchema = z5.extend(zBookingMetadataInput, {
2236
2365
  custom: z5.nullish(
2237
2366
  z5.record(z5.string(), z5.union([z5.string(), z5.int(), z5.number(), z5.boolean(), z5.null()]))
2238
2367
  )
@@ -2261,6 +2390,24 @@ function refineEndXor(value, ctx) {
2261
2390
  addIssue2(ctx, ["end_at"], "end_at must be after start_at");
2262
2391
  }
2263
2392
  }
2393
+ function refineStartXor(value, ctx) {
2394
+ const hasStart = value.start_at !== void 0 && value.start_at !== null;
2395
+ const hasDate = value.date !== void 0 && value.date !== null;
2396
+ if (hasStart === hasDate) {
2397
+ addIssue2(ctx, ["start_at"], "provide exactly one of start_at or date");
2398
+ return;
2399
+ }
2400
+ if (hasStart) {
2401
+ refineEndXor(value, ctx);
2402
+ return;
2403
+ }
2404
+ if (value.end_at != null || value.duration_minutes != null) {
2405
+ addIssue2(ctx, ["date"], "an all-day booking (date) takes no end_at or duration_minutes");
2406
+ }
2407
+ if (value.buffer_before_minutes || value.buffer_after_minutes) {
2408
+ addIssue2(ctx, ["date"], "an all-day booking (date) takes no buffers");
2409
+ }
2410
+ }
2264
2411
  var bookingRemindersSchema = z5.extend(zBookingReminders, {
2265
2412
  overrides: z5._default(
2266
2413
  z5.array(bookingReminderSchema).check(z5.maxLength(MAX_REMINDER_OVERRIDES)),
@@ -2279,7 +2426,7 @@ var bookingCreateSchema = z5.extend(zBookingCreateSchema, {
2279
2426
  // our compositions into its own output.
2280
2427
  reminders: z5.nullish(bookingRemindersSchema),
2281
2428
  metadata: z5.nullish(bookingMetadataSchema)
2282
- }).check((ctx) => refineEndXor(ctx.value, ctx));
2429
+ }).check((ctx) => refineStartXor(ctx.value, ctx));
2283
2430
  var bookingRescheduleSchema = z5.extend(zBookingRescheduleSchema, { time_zone: ianaTz }).check((ctx) => refineEndXor(ctx.value, ctx));
2284
2431
  var bookingCancelSchema = zBookingCancelSchema;
2285
2432
 
@@ -2438,7 +2585,10 @@ function useBookingForm(options = {}) {
2438
2585
  const response = await fetch(endpoint, {
2439
2586
  method: "POST",
2440
2587
  headers: { "Content-Type": "application/json" },
2441
- body: JSON.stringify(input)
2588
+ body: JSON.stringify({
2589
+ ...input,
2590
+ metadata: { ...getBookingAttribution(), ...input.metadata }
2591
+ })
2442
2592
  });
2443
2593
  const body = await response.json().catch(() => null);
2444
2594
  if (!response.ok) {
@@ -2522,6 +2672,7 @@ export {
2522
2672
  formatPhoneAsTyped,
2523
2673
  formatSlotRange,
2524
2674
  fromMinor,
2675
+ getBookingAttribution,
2525
2676
  getConsentChoice,
2526
2677
  getConsentState,
2527
2678
  getEventSemantics,