@aranova/tracking-react 0.27.0 → 1.1.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 (35) hide show
  1. package/dist/client.d.mts +11 -4
  2. package/dist/client.d.ts +11 -4
  3. package/dist/client.js +620 -350
  4. package/dist/client.js.map +1 -1
  5. package/dist/client.mjs +610 -350
  6. package/dist/client.mjs.map +1 -1
  7. package/dist/index.d.mts +7 -6
  8. package/dist/index.d.ts +7 -6
  9. package/dist/index.js +339 -393
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +328 -393
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/ingest-typed-MBuMe9Pn.d.ts +883 -0
  14. package/dist/ingest-typed-UA13xTfI.d.mts +883 -0
  15. package/dist/{phone-utils-BVzSNBf1.d.mts → phone-utils-C0ds6cqZ.d.mts} +24 -78
  16. package/dist/{phone-utils-BVzSNBf1.d.ts → phone-utils-C0ds6cqZ.d.ts} +24 -78
  17. package/dist/phone.d.mts +2 -2
  18. package/dist/phone.d.ts +2 -2
  19. package/dist/phone.js +0 -464
  20. package/dist/phone.js.map +1 -1
  21. package/dist/phone.mjs +0 -464
  22. package/dist/phone.mjs.map +1 -1
  23. package/dist/{sales-D4TB9gRS.d.ts → sales-BuKD_bdo.d.mts} +90 -329
  24. package/dist/{sales-cYjB07y8.d.mts → sales-C3O_xxZ_.d.ts} +90 -329
  25. package/dist/sales.d.mts +3 -3
  26. package/dist/sales.d.ts +3 -3
  27. package/dist/sales.js +270 -127
  28. package/dist/sales.js.map +1 -1
  29. package/dist/sales.mjs +259 -127
  30. package/dist/sales.mjs.map +1 -1
  31. package/dist/{tracking-config-runtime-D7prdTE1.d.mts → tracking-config-runtime-C6H7ofmo.d.mts} +6 -0
  32. package/dist/{tracking-config-runtime-D7prdTE1.d.ts → tracking-config-runtime-C6H7ofmo.d.ts} +6 -0
  33. package/package.json +2 -2
  34. package/dist/ingest-typed-BxLFlZ7N.d.mts +0 -1371
  35. package/dist/ingest-typed-ByQVRMvP.d.ts +0 -1371
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -39,6 +49,7 @@ __export(src_exports, {
39
49
  createTrackingClientContext: () => createTrackingClientContext,
40
50
  createTrackingEventCreatePayload: () => createTrackingEventCreatePayload,
41
51
  createTrackingSessionUpsertPayload: () => createTrackingSessionUpsertPayload,
52
+ currencySchema: () => currencySchema,
42
53
  fetchServices: () => fetchServices,
43
54
  formatDateInTz: () => formatDateInTz,
44
55
  formatMoney: () => formatMoney,
@@ -126,7 +137,7 @@ function normalizeEmail(raw) {
126
137
  return EMAIL_SHAPE.test(cleaned) ? cleaned : null;
127
138
  }
128
139
  function stashUserData(data, country) {
129
- const email = normalizeEmail(data.email);
140
+ const email3 = normalizeEmail(data.email);
130
141
  let phoneNumber = null;
131
142
  if (typeof data.phone === "string" && data.phone.length > 0) {
132
143
  try {
@@ -136,7 +147,7 @@ function stashUserData(data, country) {
136
147
  }
137
148
  }
138
149
  stash = {
139
- email: email ?? stash.email,
150
+ email: email3 ?? stash.email,
140
151
  phoneNumber: phoneNumber ?? stash.phoneNumber
141
152
  };
142
153
  }
@@ -145,11 +156,11 @@ function clearStashedUserData() {
145
156
  }
146
157
  function applyUserDataForConversion(explicit, country) {
147
158
  if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
148
- let email = stash.email;
159
+ let email3 = stash.email;
149
160
  let phoneNumber = stash.phoneNumber;
150
161
  if (explicit) {
151
162
  const normalizedEmail = normalizeEmail(explicit.email);
152
- if (normalizedEmail) email = normalizedEmail;
163
+ if (normalizedEmail) email3 = normalizedEmail;
153
164
  if (typeof explicit.phone === "string" && explicit.phone.length > 0) {
154
165
  try {
155
166
  phoneNumber = toE164(explicit.phone, country) ?? phoneNumber;
@@ -157,10 +168,10 @@ function applyUserDataForConversion(explicit, country) {
157
168
  }
158
169
  }
159
170
  }
160
- if (email === null && phoneNumber === null) return false;
171
+ if (email3 === null && phoneNumber === null) return false;
161
172
  try {
162
173
  window.gtag("set", "user_data", {
163
- ...email !== null ? { email } : {},
174
+ ...email3 !== null ? { email: email3 } : {},
164
175
  ...phoneNumber !== null ? { phone_number: phoneNumber } : {}
165
176
  });
166
177
  return true;
@@ -292,6 +303,7 @@ var TRACKING_CAPABILITIES = [
292
303
  "consent_controls",
293
304
  "conversion_goals_auto",
294
305
  "conversion_goals_manual",
306
+ "cross_site_linker",
295
307
  "cta_click_capture",
296
308
  "form_capture",
297
309
  "phone_click_capture",
@@ -318,6 +330,9 @@ function readDomMarkers() {
318
330
  return found;
319
331
  }
320
332
 
333
+ // ../tracking-core/src/cross-site-link.ts
334
+ var z = __toESM(require("zod/mini"));
335
+
321
336
  // ../tracking-core/src/tracking.ts
322
337
  var TRACKING_COOKIE_MAX_AGE_SECONDS = 7776e3;
323
338
  var TRACKING_PARAM_KEYS = [
@@ -516,10 +531,10 @@ function readStoredRecord() {
516
531
  return null;
517
532
  }
518
533
  }
519
- function writeRecord(record) {
520
- memoryRecord = record;
534
+ function writeRecord(record3) {
535
+ memoryRecord = record3;
521
536
  try {
522
- window.localStorage.setItem(LANDING_STORAGE_KEY, JSON.stringify(record));
537
+ window.localStorage.setItem(LANDING_STORAGE_KEY, JSON.stringify(record3));
523
538
  } catch {
524
539
  }
525
540
  }
@@ -541,9 +556,9 @@ function getOrCaptureLandingParams(sessionId, url) {
541
556
  if (memoryRecord && memoryRecord.session_id === sessionId) {
542
557
  return memoryRecord.params;
543
558
  }
544
- const record = { session_id: sessionId, params: captureFromUrl(url) };
545
- writeRecord(record);
546
- return record.params;
559
+ const record3 = { session_id: sessionId, params: captureFromUrl(url) };
560
+ writeRecord(record3);
561
+ return record3.params;
547
562
  }
548
563
  function buildLandingPayloadFields(sessionId, override) {
549
564
  const params = override ?? (typeof window === "undefined" ? null : getOrCaptureLandingParams(sessionId));
@@ -562,6 +577,43 @@ function buildLandingPayloadFields(sessionId, override) {
562
577
  };
563
578
  }
564
579
 
580
+ // ../tracking-core/src/cross-site-link.ts
581
+ var LINK_PARAM = "_arv";
582
+ var LINK_TOKEN_TTL_MS = 5 * 60 * 1e3;
583
+ var FUTURE_SKEW_MS = 60 * 1e3;
584
+ var CARRIED_KEYS = {
585
+ g: "gclid",
586
+ w: "wbraid",
587
+ gb: "gbraid",
588
+ f: "fbclid",
589
+ y: "ylpcid"
590
+ };
591
+ var CARRIED_ENTRIES = Object.entries(CARRIED_KEYS);
592
+ var identifier = z.string().check(z.minLength(1), z.maxLength(128));
593
+ var optionalIdentifier = z.optional(identifier);
594
+ var linkTokenSchema = z.object({
595
+ v: identifier,
596
+ s: identifier,
597
+ // Epoch ms in base36.
598
+ t: z.string().check(z.regex(/^[0-9a-z]{1,12}$/)),
599
+ g: optionalIdentifier,
600
+ w: optionalIdentifier,
601
+ gb: optionalIdentifier,
602
+ f: optionalIdentifier,
603
+ fc: optionalIdentifier,
604
+ y: optionalIdentifier
605
+ });
606
+ function stripLinkParam(url) {
607
+ try {
608
+ const parsed = new URL(url, typeof window === "undefined" ? void 0 : window.location.href);
609
+ if (!parsed.searchParams.has(LINK_PARAM)) return url;
610
+ parsed.searchParams.delete(LINK_PARAM);
611
+ return parsed.href;
612
+ } catch {
613
+ return url;
614
+ }
615
+ }
616
+
565
617
  // ../tracking-core/src/payloads.ts
566
618
  function createTrackingClientContext(surface, input = {}) {
567
619
  return {
@@ -601,6 +653,7 @@ function createTrackingSessionUpsertPayload(trackingParams, input, context) {
601
653
  };
602
654
  }
603
655
  function createTrackingEventCreatePayload(trackingParams, input, context) {
656
+ const pageUrl = input.pageUrl ?? (typeof window === "undefined" ? null : window.location.href);
604
657
  return {
605
658
  session_id: input.sessionId,
606
659
  event_type: input.eventType,
@@ -611,7 +664,7 @@ function createTrackingEventCreatePayload(trackingParams, input, context) {
611
664
  fbclid: trackingParams.fbclid,
612
665
  fbc: getFbcCookie(),
613
666
  fbp: getFbpCookie(),
614
- page_url: input.pageUrl ?? (typeof window === "undefined" ? null : window.location.href),
667
+ page_url: pageUrl === null ? null : stripLinkParam(pageUrl),
615
668
  metadata: input.metadata ?? null,
616
669
  context
617
670
  };
@@ -723,7 +776,8 @@ function parseConversionConfig(raw) {
723
776
  gtag_ids: isStringMap(obj.gtag_ids) ? obj.gtag_ids : {},
724
777
  meta_pixel_ids: isStringMap(obj.meta_pixel_ids) ? obj.meta_pixel_ids : {},
725
778
  services,
726
- goals
779
+ goals,
780
+ linked_hostnames: Array.isArray(obj.linked_hostnames) ? obj.linked_hostnames.filter((h) => typeof h === "string" && h.length > 0) : []
727
781
  };
728
782
  }
729
783
  var CACHE_PREFIX = "_aranova_cfg_";
@@ -807,6 +861,7 @@ function resolveConversionConfig(options) {
807
861
  getFiring: (key) => goalsByKey.get(key)?.firing ?? null,
808
862
  getGoal: (key) => goalsByKey.get(key) ?? null,
809
863
  listGoals: () => [...goalsByKey.values()],
864
+ linkedHostnames: () => current?.linked_hostnames ?? [],
810
865
  current: () => current,
811
866
  isReady: () => current !== null,
812
867
  onResolve: (listener) => {
@@ -920,9 +975,9 @@ function automaticThresholdMet(goal, eventType, metadata) {
920
975
  }
921
976
 
922
977
  // ../tracking-core/src/resources/intl/date.ts
923
- function formatDateInTz(iso, timeZone, opts, locale) {
924
- const date = new Date(iso);
925
- if (Number.isNaN(date.getTime())) return iso;
978
+ function formatDateInTz(iso3, timeZone, opts, locale) {
979
+ const date = new Date(iso3);
980
+ if (Number.isNaN(date.getTime())) return iso3;
926
981
  return new Intl.DateTimeFormat(locale, {
927
982
  year: "numeric",
928
983
  month: "short",
@@ -1014,7 +1069,7 @@ function validateConfig(config, ref) {
1014
1069
  function pageViewSnapshot() {
1015
1070
  if (typeof window === "undefined" || typeof document === "undefined") return null;
1016
1071
  return {
1017
- href: window.location.href,
1072
+ href: stripLinkParam(window.location.href),
1018
1073
  title: document.title || null,
1019
1074
  referrer: document.referrer || null
1020
1075
  };
@@ -1165,6 +1220,10 @@ var TrackingConfigRuntime = class {
1165
1220
  listGoals() {
1166
1221
  return this.current?.goals ?? [];
1167
1222
  }
1223
+ /** Sibling hostnames for the linker — read from the cached object even while unconfirmed. */
1224
+ linkedHostnames() {
1225
+ return this.current?.linked_hostnames ?? [];
1226
+ }
1168
1227
  async revalidateNow() {
1169
1228
  try {
1170
1229
  const headers = {};
@@ -1334,29 +1393,6 @@ function getTrackingConfigRuntime(ref, fetchImpl) {
1334
1393
  return runtime;
1335
1394
  }
1336
1395
 
1337
- // ../tracking-core/src/session.ts
1338
- var SESSION_IDLE_MS = 30 * 60 * 1e3;
1339
-
1340
- // ../tracking-core/src/events/page-view.ts
1341
- var import_zod = require("zod");
1342
- var pageViewMetadataSchema = import_zod.z.object({
1343
- page: import_zod.z.object({
1344
- title: import_zod.z.string().nullable(),
1345
- path: import_zod.z.string(),
1346
- search: import_zod.z.string(),
1347
- hash: import_zod.z.string()
1348
- }).strict(),
1349
- referrer: import_zod.z.string().nullable(),
1350
- // `.nullable().optional()` — absent (undefined) OR explicit null OR a
1351
- // real viewport object. Mirrors Pydantic's `_Viewport | None = None`
1352
- // on the backend side so the drift test stays clean.
1353
- viewport: import_zod.z.object({
1354
- w: import_zod.z.number(),
1355
- h: import_zod.z.number()
1356
- }).strict().nullable().optional()
1357
- }).strict();
1358
- var pageViewConfigSchema = import_zod.z.object({}).strict();
1359
-
1360
1396
  // ../tracking-core/src/ingest.ts
1361
1397
  var API_KEY_HEADER = "X-Aranova-Api-Key";
1362
1398
  var SDK_VERSION_HEADER = "X-Aranova-Sdk-Version";
@@ -1364,187 +1400,6 @@ var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
1364
1400
  var SDK_SURFACE_HEADER = "X-Aranova-Sdk-Surface";
1365
1401
  var SDK_ENVIRONMENT_HEADER = "X-Aranova-Sdk-Environment";
1366
1402
 
1367
- // ../tracking-core/src/events/cta-click.ts
1368
- var import_zod2 = require("zod");
1369
- var ctaClickMetadataSchema = import_zod2.z.object({
1370
- cta_name: import_zod2.z.string(),
1371
- page: import_zod2.z.object({
1372
- path: import_zod2.z.string()
1373
- }).strict(),
1374
- section: import_zod2.z.string().nullable().optional(),
1375
- destination_url: import_zod2.z.string().nullable().optional(),
1376
- // Set by auto-capture (and available to manual callers): the link target
1377
- // and a short element descriptor (tag#id) for tying clicks to specific UI.
1378
- href: import_zod2.z.string().nullable().optional(),
1379
- element: import_zod2.z.string().nullable().optional()
1380
- }).strict();
1381
- var ctaClickConfigSchema = import_zod2.z.object({
1382
- autoCapture: import_zod2.z.object({
1383
- selector: import_zod2.z.string().optional()
1384
- }).strict().optional()
1385
- }).strict();
1386
-
1387
- // ../tracking-core/src/events/sdk-heartbeat.ts
1388
- var import_zod3 = require("zod");
1389
- var sdkHeartbeatTriggersSchema = import_zod3.z.object({
1390
- automatic: import_zod3.z.array(import_zod3.z.string()),
1391
- manual: import_zod3.z.array(import_zod3.z.string())
1392
- }).strict();
1393
- var sdkHeartbeatMetadataSchema = import_zod3.z.object({
1394
- sdk_version: import_zod3.z.string(),
1395
- package_name: import_zod3.z.string().nullable(),
1396
- surface: import_zod3.z.enum(["next", "react", "script"]),
1397
- triggers: sdkHeartbeatTriggersSchema,
1398
- trigger_config: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown())).nullable().optional(),
1399
- configured_gtag_ids: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.string()).nullable().optional(),
1400
- // Site whose config object the SDK resolves; null on a legacy business ref.
1401
- config_site_id: import_zod3.z.string().uuid().nullable().optional()
1402
- }).strict();
1403
- var sdkHeartbeatConfigSchema = import_zod3.z.object({}).strict();
1404
-
1405
- // ../tracking-core/src/events/form-start.ts
1406
- var import_zod4 = require("zod");
1407
- var formStartMetadataSchema = import_zod4.z.object({
1408
- form: import_zod4.z.object({
1409
- id: import_zod4.z.string(),
1410
- action: import_zod4.z.string().nullable()
1411
- }).strict(),
1412
- page: import_zod4.z.object({
1413
- path: import_zod4.z.string()
1414
- }).strict()
1415
- }).strict();
1416
- var formStartConfigSchema = import_zod4.z.object({
1417
- selector: import_zod4.z.string().optional()
1418
- }).strict();
1419
-
1420
- // ../tracking-core/src/events/form-submit.ts
1421
- var import_zod5 = require("zod");
1422
- var jsonValueSchema = import_zod5.z.lazy(
1423
- () => import_zod5.z.union([
1424
- import_zod5.z.string(),
1425
- import_zod5.z.number().finite(),
1426
- import_zod5.z.boolean(),
1427
- import_zod5.z.null(),
1428
- import_zod5.z.array(jsonValueSchema),
1429
- import_zod5.z.record(jsonValueSchema)
1430
- ])
1431
- );
1432
- var formSubmitMetadataSchema = import_zod5.z.object({
1433
- form: import_zod5.z.object({
1434
- id: import_zod5.z.string(),
1435
- action: import_zod5.z.string().nullable(),
1436
- fields: import_zod5.z.array(
1437
- import_zod5.z.object({
1438
- name: import_zod5.z.string(),
1439
- type: import_zod5.z.string(),
1440
- label: import_zod5.z.string().nullable(),
1441
- value: jsonValueSchema
1442
- }).strict()
1443
- ).optional()
1444
- }).strict(),
1445
- page: import_zod5.z.object({
1446
- path: import_zod5.z.string()
1447
- }).strict()
1448
- }).strict();
1449
- var formSubmitConfigSchema = import_zod5.z.object({}).strict();
1450
-
1451
- // ../tracking-core/src/events/multi-page-session.ts
1452
- var import_zod6 = require("zod");
1453
- var multiPageSessionMetadataSchema = import_zod6.z.object({
1454
- page_count: import_zod6.z.number().int().min(2),
1455
- page: import_zod6.z.object({
1456
- path: import_zod6.z.string()
1457
- }).strict()
1458
- }).strict();
1459
- var multiPageSessionConfigSchema = import_zod6.z.object({
1460
- pageThreshold: import_zod6.z.number().int().min(2)
1461
- }).strict();
1462
-
1463
- // ../tracking-core/src/events/page-exit.ts
1464
- var import_zod7 = require("zod");
1465
- var pageExitMetadataSchema = import_zod7.z.object({
1466
- dwell_ms: import_zod7.z.number().int().min(0),
1467
- // null = left without any scroll signal; floor is 0 so a valid 0% is never
1468
- // rejected (a single bad field 422s the whole keepalive beacon batch).
1469
- max_scroll_percent: import_zod7.z.number().int().min(0).max(100).nullable(),
1470
- // The gating baseline: the fraction of the page visible at load with
1471
- // zero scrolling — or, for pages that grew after the post-paint snapshot
1472
- // (skeleton/streaming renders), the first-scroll position that
1473
- // established it. null = page had no scrollable range, or the segment
1474
- // ended before the snapshot. `.optional()` is load-bearing: SDK builds
1475
- // predating this field keep POSTing page_exit without the key —
1476
- // requiring it would 422 whole keepalive beacon batches.
1477
- scroll_baseline_percent: import_zod7.z.number().int().min(0).max(100).nullable().optional(),
1478
- page: import_zod7.z.object({
1479
- path: import_zod7.z.string()
1480
- }).strict()
1481
- }).strict();
1482
- var pageExitConfigSchema = import_zod7.z.object({}).strict();
1483
-
1484
- // ../tracking-core/src/events/phone-click.ts
1485
- var import_zod8 = require("zod");
1486
- var phoneClickMetadataSchema = import_zod8.z.object({
1487
- phone_number: import_zod8.z.string(),
1488
- page: import_zod8.z.object({
1489
- path: import_zod8.z.string()
1490
- }).strict(),
1491
- section: import_zod8.z.string().nullable().optional()
1492
- }).strict();
1493
- var phoneClickConfigSchema = import_zod8.z.object({
1494
- autoCapture: import_zod8.z.object({
1495
- selector: import_zod8.z.string().optional()
1496
- }).strict().optional()
1497
- }).strict();
1498
-
1499
- // ../tracking-core/src/events/scroll-depth.ts
1500
- var import_zod9 = require("zod");
1501
- var scrollDepthMetadataSchema = import_zod9.z.object({
1502
- depth_percent: import_zod9.z.number().int().min(1).max(100),
1503
- page: import_zod9.z.object({
1504
- path: import_zod9.z.string()
1505
- }).strict()
1506
- }).strict();
1507
- var scrollDepthConfigSchema = import_zod9.z.object({
1508
- thresholds: import_zod9.z.array(import_zod9.z.number().int().min(1).max(100)).min(1)
1509
- }).strict();
1510
-
1511
- // ../tracking-core/src/events/specific-page-visit.ts
1512
- var import_zod10 = require("zod");
1513
- var PAGE_IDENTITY_MAX_LENGTH = 64;
1514
- var PAGE_IDENTITY_PATTERN = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;
1515
- var pageIdentitySchema = import_zod10.z.string().max(PAGE_IDENTITY_MAX_LENGTH).regex(PAGE_IDENTITY_PATTERN, {
1516
- message: "page identity must be lowercase snake_case, start with a letter, and contain at most 64 characters"
1517
- });
1518
- var specificPageNameSchema = pageIdentitySchema;
1519
- var specificPageVisitMetadataSchema = import_zod10.z.object({
1520
- page_name: specificPageNameSchema,
1521
- page: import_zod10.z.object({
1522
- path: import_zod10.z.string()
1523
- }).strict()
1524
- }).strict();
1525
- var specificPageVisitConfigSchema = import_zod10.z.object({
1526
- pages: import_zod10.z.array(
1527
- import_zod10.z.object({
1528
- name: specificPageNameSchema,
1529
- pathPattern: import_zod10.z.custom((value) => value instanceof RegExp, {
1530
- message: "pathPattern must be a RegExp"
1531
- })
1532
- }).strict()
1533
- ).min(1)
1534
- }).strict();
1535
-
1536
- // ../tracking-core/src/events/time-on-site.ts
1537
- var import_zod11 = require("zod");
1538
- var timeOnSiteMetadataSchema = import_zod11.z.object({
1539
- duration_ms: import_zod11.z.number().int().nonnegative(),
1540
- page: import_zod11.z.object({
1541
- path: import_zod11.z.string()
1542
- }).strict()
1543
- }).strict();
1544
- var timeOnSiteConfigSchema = import_zod11.z.object({
1545
- thresholdSeconds: import_zod11.z.number().int().positive()
1546
- }).strict();
1547
-
1548
1403
  // ../tracking-core/src/events/semantics.ts
1549
1404
  var EVENT_SEMANTICS = {
1550
1405
  page_view: {
@@ -1612,88 +1467,24 @@ var EVENT_SEMANTICS = {
1612
1467
  category: "engagement",
1613
1468
  outcomeRole: "engagement",
1614
1469
  clientVisibility: "simple"
1470
+ },
1471
+ site_link_click: {
1472
+ label: "Left for sibling site",
1473
+ category: "page",
1474
+ outcomeRole: "navigation",
1475
+ clientVisibility: "detailed"
1476
+ },
1477
+ site_link_arrival: {
1478
+ label: "Arrived from sibling site",
1479
+ category: "page",
1480
+ outcomeRole: "navigation",
1481
+ clientVisibility: "simple"
1615
1482
  }
1616
1483
  };
1617
1484
  function getEventSemantics(eventName) {
1618
1485
  return eventName in EVENT_SEMANTICS ? EVENT_SEMANTICS[eventName] : null;
1619
1486
  }
1620
1487
 
1621
- // ../tracking-core/src/events/registry.ts
1622
- var EVENT_REGISTRY = {
1623
- // --- automatic triggers ---
1624
- page_view: {
1625
- kind: "automatic",
1626
- semantics: EVENT_SEMANTICS.page_view,
1627
- metadataSchema: pageViewMetadataSchema,
1628
- configSchema: pageViewConfigSchema
1629
- },
1630
- time_on_site: {
1631
- kind: "automatic",
1632
- semantics: EVENT_SEMANTICS.time_on_site,
1633
- metadataSchema: timeOnSiteMetadataSchema,
1634
- configSchema: timeOnSiteConfigSchema
1635
- },
1636
- specific_page_visit: {
1637
- kind: "automatic",
1638
- semantics: EVENT_SEMANTICS.specific_page_visit,
1639
- metadataSchema: specificPageVisitMetadataSchema,
1640
- configSchema: specificPageVisitConfigSchema
1641
- },
1642
- scroll_depth: {
1643
- kind: "automatic",
1644
- semantics: EVENT_SEMANTICS.scroll_depth,
1645
- metadataSchema: scrollDepthMetadataSchema,
1646
- configSchema: scrollDepthConfigSchema
1647
- },
1648
- multi_page_session: {
1649
- kind: "automatic",
1650
- semantics: EVENT_SEMANTICS.multi_page_session,
1651
- metadataSchema: multiPageSessionMetadataSchema,
1652
- configSchema: multiPageSessionConfigSchema
1653
- },
1654
- form_start: {
1655
- kind: "automatic",
1656
- semantics: EVENT_SEMANTICS.form_start,
1657
- metadataSchema: formStartMetadataSchema,
1658
- configSchema: formStartConfigSchema
1659
- },
1660
- // --- SDK-internal automatic (not consumer-configurable) ---
1661
- sdk_heartbeat: {
1662
- kind: "automatic",
1663
- semantics: EVENT_SEMANTICS.sdk_heartbeat,
1664
- metadataSchema: sdkHeartbeatMetadataSchema,
1665
- configSchema: sdkHeartbeatConfigSchema
1666
- },
1667
- page_exit: {
1668
- kind: "automatic",
1669
- semantics: EVENT_SEMANTICS.page_exit,
1670
- metadataSchema: pageExitMetadataSchema,
1671
- configSchema: pageExitConfigSchema
1672
- },
1673
- // --- manual triggers ---
1674
- form_submit: {
1675
- kind: "manual",
1676
- semantics: EVENT_SEMANTICS.form_submit,
1677
- metadataSchema: formSubmitMetadataSchema,
1678
- configSchema: formSubmitConfigSchema
1679
- },
1680
- phone_click: {
1681
- kind: "manual",
1682
- semantics: EVENT_SEMANTICS.phone_click,
1683
- metadataSchema: phoneClickMetadataSchema,
1684
- configSchema: phoneClickConfigSchema
1685
- },
1686
- cta_click: {
1687
- kind: "manual",
1688
- semantics: EVENT_SEMANTICS.cta_click,
1689
- metadataSchema: ctaClickMetadataSchema,
1690
- configSchema: ctaClickConfigSchema
1691
- }
1692
- };
1693
- var ALL_AUTOMATIC_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "automatic").map(([name]) => name);
1694
- var ALL_MANUAL_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "manual").map(([name]) => name);
1695
- var ALL_LEAD_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.semantics.outcomeRole === "lead").map(([name]) => name);
1696
-
1697
1488
  // ../tracking-core/src/resources/http/errors.ts
1698
1489
  var AranovaApiError = class extends Error {
1699
1490
  constructor(message, options) {
@@ -1731,9 +1522,9 @@ async function apiRequest(config, method, path, body, extraHeaders) {
1731
1522
  try {
1732
1523
  const parsed = await response.json();
1733
1524
  if (parsed && typeof parsed === "object") {
1734
- const record = parsed;
1735
- if (typeof record.detail === "string") detail = record.detail;
1736
- if (typeof record.code === "string") code = record.code;
1525
+ const record3 = parsed;
1526
+ if (typeof record3.detail === "string") detail = record3.detail;
1527
+ if (typeof record3.code === "string") code = record3.code;
1737
1528
  }
1738
1529
  } catch {
1739
1530
  }
@@ -1782,7 +1573,7 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
1782
1573
  }
1783
1574
  function createSalesClient(config) {
1784
1575
  if (config.firing) registerCapability("conversion_goals_manual");
1785
- async function record(input) {
1576
+ async function record3(input) {
1786
1577
  const currency = input.currency ?? config.defaultCurrency;
1787
1578
  if (!currency) {
1788
1579
  throw new Error(
@@ -1808,9 +1599,9 @@ function createSalesClient(config) {
1808
1599
  return sale;
1809
1600
  }
1810
1601
  return {
1811
- record,
1602
+ record: record3,
1812
1603
  // recordSale is the intent-revealing alias — same behavior, clearer call site.
1813
- recordSale: record,
1604
+ recordSale: record3,
1814
1605
  trackConversion(key, options) {
1815
1606
  if (config.firing && "fireConversion" in config.firing) {
1816
1607
  if (options?.userData && getConsentState() !== "denied") stashUserData(options.userData);
@@ -1929,115 +1720,269 @@ function createSalesClient(config) {
1929
1720
  }
1930
1721
 
1931
1722
  // ../tracking-core/src/resources/sales/schema.ts
1932
- var import_zod12 = require("zod");
1933
- var SUPPORTED_CURRENCIES = ["USD", "CAD"];
1934
- var TRACKING_ENVIRONMENTS = ["production", "development"];
1935
- var currencySchema = import_zod12.z.enum(SUPPORTED_CURRENCIES);
1936
- var centsSchema = import_zod12.z.number().int().nonnegative();
1937
- var quantitySchema = import_zod12.z.string().regex(/^\d+(\.\d{1,3})?$/);
1938
- var metadataSchema = import_zod12.z.record(import_zod12.z.unknown());
1939
- var saleItemSchema = import_zod12.z.object({
1940
- external_item_id: import_zod12.z.string().nullable().optional(),
1941
- name: import_zod12.z.string().nullable().optional(),
1942
- category: import_zod12.z.string().nullable().optional(),
1943
- quantity: quantitySchema,
1944
- unit_price_cents: centsSchema,
1945
- // Non-negativity validated on the wire — same contract as the other cents
1946
- // fields — and backstopped by the DB CHECK.
1947
- unit_cost_cents: centsSchema.nullable().optional()
1948
- }).strict();
1949
- var saleServiceSchema = import_zod12.z.object({
1950
- service: import_zod12.z.string(),
1951
- amount_cents: centsSchema
1952
- }).strict();
1953
- var customerNameSchema = import_zod12.z.string().max(200);
1954
- var customerPhoneSchema = import_zod12.z.string().max(64);
1955
- var customerEmailSchema = import_zod12.z.string().max(320).email();
1723
+ var z3 = __toESM(require("zod/mini"));
1724
+
1725
+ // ../tracking-core/src/resources/sales/generated/zod.gen.ts
1726
+ var z2 = __toESM(require("zod/mini"));
1727
+ var zErrorCode = z2.enum([
1728
+ "missing_credentials",
1729
+ "invalid_api_key",
1730
+ "not_authenticated",
1731
+ "wrong_key_type",
1732
+ "origin_missing",
1733
+ "origin_not_allowed",
1734
+ "capability_denied",
1735
+ "session_required",
1736
+ "operator_only",
1737
+ "cross_tenant",
1738
+ "business_id_required",
1739
+ "bad_request",
1740
+ "not_found",
1741
+ "conflict",
1742
+ "incompatible_payload",
1743
+ "repeat_confirmation_required",
1744
+ "idempotency_conflict",
1745
+ "validation_error",
1746
+ "unknown_service",
1747
+ "invalid_sale_properties",
1748
+ "invalid_cursor",
1749
+ "rate_limited",
1750
+ "internal_error"
1751
+ ]);
1752
+ var zSaleItemEntitySchema = z2.object({
1753
+ category: z2.nullable(z2.string()),
1754
+ external_item_id: z2.nullable(z2.string()),
1755
+ id: z2.uuid(),
1756
+ name: z2.nullable(z2.string()),
1757
+ quantity: z2.string().check(z2.regex(/^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$/)),
1758
+ unit_cost_cents: z2.nullable(z2.int()),
1759
+ unit_price_cents: z2.int()
1760
+ });
1761
+ var zSaleItemInputSchema = z2.strictObject({
1762
+ category: z2.nullish(z2.string()),
1763
+ external_item_id: z2.nullish(z2.string()),
1764
+ name: z2.nullish(z2.string()),
1765
+ quantity: z2.string().check(z2.regex(/^\d+(\.\d{1,3})?$/)),
1766
+ unit_cost_cents: z2.nullish(z2.int().check(z2.gte(0))),
1767
+ unit_price_cents: z2.int().check(z2.gte(0))
1768
+ });
1769
+ var zSaleServiceEntitySchema = z2.object({
1770
+ amount_cents: z2.int(),
1771
+ id: z2.uuid(),
1772
+ mapped: z2.nullable(z2.boolean()),
1773
+ service_id: z2.uuid(),
1774
+ service_key: z2.string(),
1775
+ service_label: z2.string()
1776
+ });
1777
+ var zSaleServiceInputSchema = z2.strictObject({
1778
+ amount_cents: z2.int().check(z2.gte(0)),
1779
+ service: z2.string()
1780
+ });
1781
+ var zSmsAutomationState = z2.enum([
1782
+ "needs_check",
1783
+ "failed",
1784
+ "undelivered",
1785
+ "blocked_opted_out",
1786
+ "withheld",
1787
+ "queued",
1788
+ "sent",
1789
+ "delivered",
1790
+ "eligible",
1791
+ "not_applicable"
1792
+ ]);
1793
+ var zSmsWithheldReason = z2.enum([
1794
+ "automation_disabled",
1795
+ "sms_disabled",
1796
+ "no_phone",
1797
+ "no_consent",
1798
+ "no_customer_identity",
1799
+ "missing_customer_name",
1800
+ "placeholder_customer_name",
1801
+ "opted_out",
1802
+ "already_messaged",
1803
+ "sender_not_ready",
1804
+ "missing_review_url",
1805
+ "no_handler",
1806
+ "dispatch_already_recorded",
1807
+ "text_back_disabled",
1808
+ "number_not_active",
1809
+ "a2p_registration_required",
1810
+ "alert_recipient_cannot_receive_sms",
1811
+ "line_type_unresolved"
1812
+ ]);
1813
+ var zSaleSmsStatusSchema = z2.object({
1814
+ can_send_now: z2._default(z2.boolean(), false),
1815
+ last_message_at: z2.nullable(z2.iso.datetime({ offset: true })),
1816
+ reason_detail: z2.nullable(z2.string()),
1817
+ state: zSmsAutomationState,
1818
+ suppressed_by_other_sale: z2._default(z2.boolean(), false),
1819
+ withheld_reason: z2.nullable(zSmsWithheldReason)
1820
+ });
1821
+ var zSupportedCurrency = z2.enum(["USD", "CAD"]);
1822
+ var zTrackingEnvironment = z2.enum(["production", "development"]);
1823
+ var zSaleCreateSchema = z2.strictObject({
1824
+ amount_total_cents: z2.nullish(z2.int().check(z2.gte(0))),
1825
+ currency: zSupportedCurrency,
1826
+ customer_email: z2.nullish(z2.email().check(z2.maxLength(320))),
1827
+ customer_name: z2.nullish(z2.string().check(z2.maxLength(200))),
1828
+ customer_phone: z2.nullish(z2.string().check(z2.maxLength(64))),
1829
+ description: z2.nullish(z2.string()),
1830
+ environment: z2._default(z2.optional(zTrackingEnvironment), "production"),
1831
+ external_id: z2.nullish(z2.string()),
1832
+ items: z2.optional(z2.array(zSaleItemInputSchema)),
1833
+ metadata: z2.nullish(z2.record(z2.string(), z2.unknown())),
1834
+ occurred_at: z2.iso.datetime({ offset: true }),
1835
+ service: z2.nullish(z2.string()),
1836
+ services: z2.nullish(z2.array(zSaleServiceInputSchema)),
1837
+ sms_consent: z2.nullish(z2.boolean())
1838
+ });
1839
+ var zValidationError = z2.object({
1840
+ ctx: z2.optional(z2.record(z2.string(), z2.unknown())),
1841
+ input: z2.optional(z2.unknown()),
1842
+ loc: z2.array(z2.union([z2.string(), z2.int()])),
1843
+ msg: z2.string(),
1844
+ type: z2.string()
1845
+ });
1846
+ var zHttpValidationError = z2.object({
1847
+ detail: z2.optional(z2.array(zValidationError))
1848
+ });
1849
+ var zValidationErrorItem = z2.object({
1850
+ loc: z2.array(z2.union([z2.string(), z2.int()])),
1851
+ msg: z2.string(),
1852
+ type: z2.string()
1853
+ });
1854
+ var zApiErrorSchema = z2.object({
1855
+ code: zErrorCode,
1856
+ context: z2._default(z2.nullish(z2.record(z2.string(), z2.unknown())), null),
1857
+ detail: z2.string(),
1858
+ errors: z2._default(z2.nullish(z2.array(zValidationErrorItem)), null),
1859
+ request_id: z2._default(z2.nullish(z2.string()), null)
1860
+ });
1861
+ var zWritebackEmailSource = z2.enum(["NONE", "SALE", "CUSTOMER", "HARVESTED"]);
1862
+ var zWritebackEnrichmentStatus = z2.enum(["NONE", "MATCHED", "AMBIGUOUS"]);
1863
+ var zWritebackSaleUploadCounts = z2.object({
1864
+ failed: z2._default(z2.int(), 0),
1865
+ pending: z2._default(z2.int(), 0),
1866
+ skipped: z2._default(z2.int(), 0),
1867
+ submitted: z2._default(z2.int(), 0),
1868
+ total: z2._default(z2.int(), 0),
1869
+ uploaded: z2._default(z2.int(), 0)
1870
+ });
1871
+ var zSaleWritebackStatusSchema = z2.object({
1872
+ blocked_reason: z2.nullable(z2.string()),
1873
+ can_dispatch: z2._default(z2.boolean(), false),
1874
+ email_source: z2.nullable(zWritebackEmailSource),
1875
+ enrichment_status: z2.nullable(zWritebackEnrichmentStatus),
1876
+ gclid_attached: z2._default(z2.boolean(), false),
1877
+ identifiers_sent: z2.nullable(z2.string()),
1878
+ mapped_service_ids: z2.array(z2.uuid()),
1879
+ matched_submit_count: z2.nullable(z2.int()),
1880
+ needs_force: z2._default(z2.boolean(), false),
1881
+ rollup: z2.enum([
1882
+ "failed",
1883
+ "skipped",
1884
+ "pending",
1885
+ "submitted",
1886
+ "uploaded",
1887
+ "not_uploaded",
1888
+ "out_of_window",
1889
+ "blocked"
1890
+ ]),
1891
+ stale: z2._default(z2.boolean(), false),
1892
+ uncovered_service_ids: z2.array(z2.uuid()),
1893
+ uploads: zWritebackSaleUploadCounts
1894
+ });
1895
+ var zSaleEntitySchema = z2.object({
1896
+ amount_total_cents: z2.int(),
1897
+ business_id: z2.uuid(),
1898
+ business_name: z2.nullable(z2.string()),
1899
+ created_at: z2.iso.datetime({ offset: true }),
1900
+ currency: z2.string(),
1901
+ customer_email: z2.nullable(z2.string()),
1902
+ customer_name: z2.nullable(z2.string()),
1903
+ customer_name_placeholder_confirmed: z2._default(z2.boolean(), false),
1904
+ customer_name_placeholder_confirmed_at: z2.nullable(z2.iso.datetime({ offset: true })),
1905
+ customer_phone: z2.nullable(z2.string()),
1906
+ description: z2.nullable(z2.string()),
1907
+ environment: zTrackingEnvironment,
1908
+ external_id: z2.nullable(z2.string()),
1909
+ id: z2.uuid(),
1910
+ items: z2.array(zSaleItemEntitySchema),
1911
+ metadata: z2.nullable(z2.record(z2.string(), z2.unknown())),
1912
+ occurred_at: z2.iso.datetime({ offset: true }),
1913
+ service_id: z2.nullable(z2.uuid()),
1914
+ service_key: z2.nullable(z2.string()),
1915
+ service_label: z2.nullable(z2.string()),
1916
+ services: z2.array(zSaleServiceEntitySchema),
1917
+ sms_automation: z2.nullable(zSaleSmsStatusSchema),
1918
+ sms_consent: z2._default(z2.boolean(), false),
1919
+ sms_consent_granted_at: z2.nullable(z2.iso.datetime({ offset: true })),
1920
+ updated_at: z2.iso.datetime({ offset: true }),
1921
+ writeback: z2.nullable(zSaleWritebackStatusSchema)
1922
+ });
1923
+
1924
+ // ../tracking-core/src/resources/sales/schema.ts
1925
+ var saleItemSchema = zSaleItemInputSchema;
1926
+ var saleServiceSchema = zSaleServiceInputSchema;
1927
+ var currencySchema = zSupportedCurrency;
1928
+ var SUPPORTED_CURRENCIES = currencySchema.options;
1929
+ var centsSchema = z3.int().check(z3.gte(0));
1930
+ var metadataSchema = z3.record(z3.string(), z3.unknown());
1931
+ var customerNameSchema = z3.string().check(z3.maxLength(200));
1932
+ var customerPhoneSchema = z3.string().check(z3.maxLength(64));
1933
+ var customerEmailSchema = z3.email().check(z3.maxLength(320));
1934
+ function addIssue(ctx, path, message) {
1935
+ ctx.issues.push({ code: "custom", input: ctx.value, path, message });
1936
+ }
1956
1937
  function refineServiceXor(val, ctx, { requireAmount }) {
1957
1938
  if (val.services != null) {
1958
1939
  if (val.service != null) {
1959
- ctx.addIssue({
1960
- code: import_zod12.z.ZodIssueCode.custom,
1961
- message: "pass either `service` or `services`, not both",
1962
- path: ["services"]
1963
- });
1940
+ addIssue(ctx, ["services"], "pass either `service` or `services`, not both");
1964
1941
  }
1965
1942
  if (val.services.length === 0) {
1966
- ctx.addIssue({
1967
- code: import_zod12.z.ZodIssueCode.custom,
1968
- message: "`services` must not be empty",
1969
- path: ["services"]
1970
- });
1943
+ addIssue(ctx, ["services"], "`services` must not be empty");
1971
1944
  }
1972
1945
  const keys = val.services.map((s) => s.service);
1973
1946
  if (new Set(keys).size !== keys.length) {
1974
- ctx.addIssue({
1975
- code: import_zod12.z.ZodIssueCode.custom,
1976
- message: "`services` must not list the same service more than once",
1977
- path: ["services"]
1978
- });
1947
+ addIssue(ctx, ["services"], "`services` must not list the same service more than once");
1979
1948
  }
1980
1949
  if (val.amount_total_cents != null) {
1981
1950
  const sum = val.services.reduce((acc, s) => acc + s.amount_cents, 0);
1982
1951
  if (val.amount_total_cents !== sum) {
1983
- ctx.addIssue({
1984
- code: import_zod12.z.ZodIssueCode.custom,
1985
- message: "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)",
1986
- path: ["amount_total_cents"]
1987
- });
1952
+ addIssue(
1953
+ ctx,
1954
+ ["amount_total_cents"],
1955
+ "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)"
1956
+ );
1988
1957
  }
1989
1958
  }
1990
1959
  } else if (requireAmount && val.amount_total_cents == null) {
1991
- ctx.addIssue({
1992
- code: import_zod12.z.ZodIssueCode.custom,
1993
- message: "amount_total_cents is required unless `services` is provided",
1994
- path: ["amount_total_cents"]
1995
- });
1960
+ addIssue(
1961
+ ctx,
1962
+ ["amount_total_cents"],
1963
+ "amount_total_cents is required unless `services` is provided"
1964
+ );
1996
1965
  }
1997
1966
  }
1998
- var saleCreateSchema = import_zod12.z.object({
1999
- external_id: import_zod12.z.string().nullable().optional(),
2000
- description: import_zod12.z.string().nullable().optional(),
2001
- service: import_zod12.z.string().nullable().optional(),
2002
- services: import_zod12.z.array(saleServiceSchema).nullable().optional(),
2003
- currency: currencySchema,
2004
- // Optional only because the plural `services` form derives it from the sum
2005
- // (see refineServiceXor); the singular/serviceless path still requires it.
2006
- amount_total_cents: centsSchema.nullable().optional(),
2007
- occurred_at: import_zod12.z.string().datetime(),
2008
- environment: import_zod12.z.enum(TRACKING_ENVIRONMENTS).default("production"),
2009
- items: import_zod12.z.array(saleItemSchema).default([]),
2010
- metadata: metadataSchema.nullable().optional(),
2011
- customer_name: customerNameSchema.nullable().optional(),
2012
- customer_phone: customerPhoneSchema.nullable().optional(),
2013
- customer_email: customerEmailSchema.nullable().optional(),
2014
- // CASL consent attestation: the customer agreed to receive SMS. Recorded
2015
- // with a timestamp server-side; every SMS send path gates on it.
2016
- //
2017
- // Tri-state: omit it (or send null) to let the server apply the business's
2018
- // configured default-opt-in policy, honouring a returning customer's
2019
- // remembered preference. Send an explicit boolean to assert consent state
2020
- // yourself — `false` records a deliberate opt-out.
2021
- sms_consent: import_zod12.z.boolean().nullable().optional()
2022
- }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: true }));
2023
- var saleUpdateSchema = import_zod12.z.object({
2024
- description: import_zod12.z.string().nullable().optional(),
2025
- service: import_zod12.z.string().nullable().optional(),
2026
- services: import_zod12.z.array(saleServiceSchema).nullable().optional(),
2027
- currency: currencySchema.optional(),
2028
- amount_total_cents: centsSchema.optional(),
2029
- occurred_at: import_zod12.z.string().datetime().optional(),
2030
- items: import_zod12.z.array(saleItemSchema).optional(),
2031
- metadata: metadataSchema.nullable().optional(),
2032
- customer_name: customerNameSchema.nullable().optional(),
1967
+ var saleCreateSchema = z3.extend(zSaleCreateSchema, { items: z3._default(z3.array(saleItemSchema), []) }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: true }));
1968
+ var saleUpdateSchema = z3.strictObject({
1969
+ description: z3.nullish(z3.string()),
1970
+ service: z3.nullish(z3.string()),
1971
+ services: z3.nullish(z3.array(saleServiceSchema)),
1972
+ currency: z3.optional(currencySchema),
1973
+ amount_total_cents: z3.optional(centsSchema),
1974
+ occurred_at: z3.optional(z3.iso.datetime()),
1975
+ items: z3.optional(z3.array(saleItemSchema)),
1976
+ metadata: z3.nullish(metadataSchema),
1977
+ customer_name: z3.nullish(customerNameSchema),
2033
1978
  // Re-attest when changing a filler-looking name; the server clears the
2034
1979
  // prior attestation whenever `customer_name` changes.
2035
- customer_name_placeholder_confirmed: import_zod12.z.boolean().optional(),
2036
- customer_phone: customerPhoneSchema.nullable().optional(),
2037
- customer_email: customerEmailSchema.nullable().optional(),
1980
+ customer_name_placeholder_confirmed: z3.optional(z3.boolean()),
1981
+ customer_phone: z3.nullish(customerPhoneSchema),
1982
+ customer_email: z3.nullish(customerEmailSchema),
2038
1983
  // NOT NULL server-side: omit to leave unchanged (explicit null is rejected).
2039
- sms_consent: import_zod12.z.boolean().optional()
2040
- }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: false }));
1984
+ sms_consent: z3.optional(z3.boolean())
1985
+ }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: false }));
2041
1986
  var TRACKING_RANGES = ["24h", "7d", "30d"];
2042
1987
  var NAMED_RANGES = [
2043
1988
  "today",
@@ -2086,6 +2031,7 @@ var import_client2 = require("@aranova/tracking-react/client");
2086
2031
  createTrackingClientContext,
2087
2032
  createTrackingEventCreatePayload,
2088
2033
  createTrackingSessionUpsertPayload,
2034
+ currencySchema,
2089
2035
  fetchServices,
2090
2036
  formatDateInTz,
2091
2037
  formatMoney,