@aranova/tracking-react 1.14.0 → 1.14.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.js CHANGED
@@ -555,10 +555,10 @@ function readStoredRecord() {
555
555
  return null;
556
556
  }
557
557
  }
558
- function writeRecord(record3) {
559
- memoryRecord = record3;
558
+ function writeRecord(record4) {
559
+ memoryRecord = record4;
560
560
  try {
561
- window.localStorage.setItem(LANDING_STORAGE_KEY, JSON.stringify(record3));
561
+ window.localStorage.setItem(LANDING_STORAGE_KEY, JSON.stringify(record4));
562
562
  } catch {
563
563
  }
564
564
  }
@@ -580,9 +580,9 @@ function getOrCaptureLandingParams(sessionId, url) {
580
580
  if (memoryRecord && memoryRecord.session_id === sessionId) {
581
581
  return memoryRecord.params;
582
582
  }
583
- const record3 = { session_id: sessionId, params: captureFromUrl(url) };
584
- writeRecord(record3);
585
- return record3.params;
583
+ const record4 = { session_id: sessionId, params: captureFromUrl(url) };
584
+ writeRecord(record4);
585
+ return record4.params;
586
586
  }
587
587
  function buildLandingPayloadFields(sessionId, override) {
588
588
  const params = override ?? (typeof window === "undefined" ? null : getOrCaptureLandingParams(sessionId));
@@ -1809,8 +1809,81 @@ var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
1809
1809
  var SDK_SURFACE_HEADER = "X-Aranova-Sdk-Surface";
1810
1810
  var SDK_ENVIRONMENT_HEADER = "X-Aranova-Sdk-Environment";
1811
1811
 
1812
- // ../tracking-core/src/lead-forms/lead-forms.gen.ts
1812
+ // ../tracking-core/src/ingest-typed.ts
1813
+ var import_mini = require("zod/mini");
1814
+
1815
+ // ../tracking-core/src/events/form-submit.ts
1813
1816
  var z2 = __toESM(require("zod/mini"));
1817
+ var jsonValueSchema = z2.lazy(
1818
+ () => z2.union([
1819
+ z2.string(),
1820
+ z2.number(),
1821
+ z2.boolean(),
1822
+ z2.null(),
1823
+ z2.array(jsonValueSchema),
1824
+ z2.record(z2.string(), jsonValueSchema)
1825
+ ])
1826
+ ).register(z2.globalRegistry, { id: "JsonSerializableValue" });
1827
+ var contractNameSchema = z2.string().check(z2.regex(/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/));
1828
+ var contractName = contractNameSchema;
1829
+ var violationRole = z2.string().check(
1830
+ z2.maxLength(200),
1831
+ z2.regex(
1832
+ /^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?(\|[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?)*$/
1833
+ )
1834
+ );
1835
+ var MAX_CONTRACT_VIOLATIONS = 50;
1836
+ var contractViolationSchema = z2.strictObject({
1837
+ role: z2.nullable(violationRole),
1838
+ rule: z2.string().check(z2.regex(/^[a-z][a-z_]{0,47}$/))
1839
+ });
1840
+ var formSubmitMetadataSchema = z2.strictObject({
1841
+ form: z2.strictObject({
1842
+ id: z2.string(),
1843
+ action: z2.nullable(z2.string()),
1844
+ fields: z2.optional(
1845
+ z2.array(
1846
+ z2.strictObject({
1847
+ name: z2.string(),
1848
+ type: z2.string(),
1849
+ label: z2.nullable(z2.string()),
1850
+ value: jsonValueSchema,
1851
+ role: z2.optional(z2.nullable(contractName))
1852
+ })
1853
+ )
1854
+ ),
1855
+ kind: z2.optional(z2.nullable(contractName)),
1856
+ contract_version: z2.optional(z2.nullable(z2.int().check(z2.gte(1)))),
1857
+ contract_hash: z2.optional(z2.nullable(z2.string().check(z2.maxLength(64)))),
1858
+ extra: z2.optional(
1859
+ z2.nullable(
1860
+ z2.array(
1861
+ z2.strictObject({
1862
+ key: z2.string().check(z2.maxLength(64)),
1863
+ label: z2.string().check(z2.maxLength(200)),
1864
+ value: jsonValueSchema
1865
+ })
1866
+ ).check(z2.maxLength(20))
1867
+ )
1868
+ ),
1869
+ contract_violations: z2.optional(
1870
+ z2.nullable(z2.array(contractViolationSchema).check(z2.maxLength(MAX_CONTRACT_VIOLATIONS)))
1871
+ )
1872
+ }),
1873
+ page: z2.strictObject({
1874
+ path: z2.string()
1875
+ })
1876
+ });
1877
+ var formSubmitConfigSchema = z2.strictObject({});
1878
+
1879
+ // ../tracking-core/src/ingest-typed.ts
1880
+ var clientSettings = /* @__PURE__ */ new WeakMap();
1881
+ function typedClientSettings(client) {
1882
+ return clientSettings.get(client) ?? {};
1883
+ }
1884
+
1885
+ // ../tracking-core/src/lead-forms/lead-forms.gen.ts
1886
+ var z3 = __toESM(require("zod/mini"));
1814
1887
  var LEAD_FORM_REGISTRY_VERSION = 2;
1815
1888
  var LEAD_FORM_KINDS = ["booking", "quote", "contact", "consult", "callback"];
1816
1889
  var LEAD_FORM_ROLES = [
@@ -1850,28 +1923,28 @@ var LEAD_FORM_PRIMITIVES = [
1850
1923
  "number"
1851
1924
  ];
1852
1925
  var leadFormPrimitiveSchemas = /* @__PURE__ */ (() => ({
1853
- string: z2.string().check(z2.maxLength(120)),
1854
- text: z2.string().check(z2.maxLength(2e3)),
1855
- enum: z2.string().check(z2.regex(/^[a-z0-9-]{1,48}$/)),
1856
- multi_enum: z2.array(z2.string().check(z2.regex(/^[a-z0-9-]{1,48}$/))).check(z2.maxLength(10)),
1857
- bool: z2.boolean(),
1858
- date: z2.string().check(z2.regex(/^\d{4}-\d{2}-\d{2}$/)),
1859
- time_window: z2.strictObject({
1860
- start: z2.string().check(z2.regex(/^([01]\d|2[0-3]):[0-5]\d$/)),
1861
- end: z2.nullable(z2.string().check(z2.regex(/^([01]\d|2[0-3]):[0-5]\d$/))),
1862
- label: z2.optional(z2.string().check(z2.maxLength(60)))
1926
+ string: z3.string().check(z3.maxLength(120)),
1927
+ text: z3.string().check(z3.maxLength(2e3)),
1928
+ enum: z3.string().check(z3.regex(/^[a-z0-9-]{1,48}$/)),
1929
+ multi_enum: z3.array(z3.string().check(z3.regex(/^[a-z0-9-]{1,48}$/))).check(z3.maxLength(10)),
1930
+ bool: z3.boolean(),
1931
+ date: z3.string().check(z3.regex(/^\d{4}-\d{2}-\d{2}$/)),
1932
+ time_window: z3.strictObject({
1933
+ start: z3.string().check(z3.regex(/^([01]\d|2[0-3]):[0-5]\d$/)),
1934
+ end: z3.nullable(z3.string().check(z3.regex(/^([01]\d|2[0-3]):[0-5]\d$/))),
1935
+ label: z3.optional(z3.string().check(z3.maxLength(60)))
1863
1936
  }),
1864
- phone: z2.string().check(z2.regex(/^\+[1-9]\d{6,14}$/)),
1865
- email: z2.string().check(z2.maxLength(320), z2.regex(/^[^\s@]+@[^\s@]+$/)),
1866
- address: z2.strictObject({
1867
- line1: z2.string().check(z2.maxLength(120)),
1868
- line2: z2.optional(z2.string().check(z2.maxLength(120))),
1869
- city: z2.optional(z2.string().check(z2.maxLength(120))),
1870
- region: z2.optional(z2.string().check(z2.maxLength(120))),
1871
- postal_code: z2.optional(z2.string().check(z2.maxLength(120))),
1872
- country: z2.optional(z2.string().check(z2.maxLength(120)))
1937
+ phone: z3.string().check(z3.regex(/^\+[1-9]\d{6,14}$/)),
1938
+ email: z3.string().check(z3.maxLength(320), z3.regex(/^[^\s@]+@[^\s@]+$/)),
1939
+ address: z3.strictObject({
1940
+ line1: z3.string().check(z3.maxLength(120)),
1941
+ line2: z3.optional(z3.string().check(z3.maxLength(120))),
1942
+ city: z3.optional(z3.string().check(z3.maxLength(120))),
1943
+ region: z3.optional(z3.string().check(z3.maxLength(120))),
1944
+ postal_code: z3.optional(z3.string().check(z3.maxLength(120))),
1945
+ country: z3.optional(z3.string().check(z3.maxLength(120)))
1873
1946
  }),
1874
- number: z2.number()
1947
+ number: z3.number()
1875
1948
  }))();
1876
1949
  var LEAD_FORM_ROLE_SPECS = {
1877
1950
  given_name: { primitive: "string", smsLabel: "", contactIdentity: true },
@@ -1921,6 +1994,101 @@ var LEAD_FORM_ROLE_SPECS = {
1921
1994
  attribution: { primitive: "enum", smsLabel: "", uninteresting: true }
1922
1995
  };
1923
1996
 
1997
+ // ../tracking-core/src/lead-forms/submit.ts
1998
+ var import_mini2 = require("zod/mini");
1999
+ var KNOWN_ROLES = new Set(LEAD_FORM_ROLES);
2000
+ var ROLE_ORDER = new Map(LEAD_FORM_ROLES.map((role, index) => [role, index]));
2001
+ var ADD_ON = /^add_on:[a-z0-9_-]{1,48}$/;
2002
+ var CONTRACT_NAME = /^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/;
2003
+ function judgeLeadForm(kind, formId, fields, contracts, settings) {
2004
+ const generated = contracts?.contracts[kind];
2005
+ const live = liveContract(settings.trackingConfig, kind);
2006
+ const violations = check(live === void 0 ? generated : fromLive(live), fields);
2007
+ const liveHash = live === void 0 ? void 0 : live?.contract_hash ?? null;
2008
+ if (contracts && (liveHash !== void 0 && (generated?.hash ?? null) !== liveHash || contracts.registryVersion !== LEAD_FORM_REGISTRY_VERSION)) {
2009
+ violations.push({ role: null, rule: "contract_behind" });
2010
+ }
2011
+ if (violations.length > 0 && (settings.debug || settings.environment === "development")) {
2012
+ const message = `[AranovaTracking] lead form "${formId}" (${kind}) breaks its contract: ${violations.map((v) => `${v.rule}${v.role ? ` (${v.role})` : ""}`).join(", ")}`;
2013
+ console.error(message);
2014
+ if (settings.debug) throw new Error(message);
2015
+ }
2016
+ return {
2017
+ violations,
2018
+ hash: liveHash === void 0 ? generated?.hash ?? null : liveHash
2019
+ };
2020
+ }
2021
+ function liveContract(ref, kind) {
2022
+ const leadForms = ref ? getTrackingConfigRuntime(ref).leadForms() : null;
2023
+ if (!leadForms) return void 0;
2024
+ return leadForms.contracts.find((c) => c.form_kind === kind) ?? null;
2025
+ }
2026
+ function fromLive(live) {
2027
+ if (!live) return void 0;
2028
+ return {
2029
+ requires: live.requires.map((r) => ({
2030
+ role: r.role,
2031
+ requiredWhen: r.required_when ? { role: r.required_when.role, anyOf: r.required_when.any_of } : null
2032
+ })),
2033
+ requiresAny: live.requires_any.map((g) => g.roles),
2034
+ // Deprecated keys still resolve: a cached form may send them (ADR-0024 §7).
2035
+ options: Object.fromEntries(live.options.map((o) => [o.role, o.options.map((x) => x.key)]))
2036
+ };
2037
+ }
2038
+ function check(contract, fields) {
2039
+ const answered = new Map(fields);
2040
+ const violations = [];
2041
+ for (const [role, value] of fields) {
2042
+ const primitive = primitiveOf(role);
2043
+ if (!primitive) {
2044
+ violations.push({ role: CONTRACT_NAME.test(role) ? role : null, rule: "unknown_role" });
2045
+ continue;
2046
+ }
2047
+ if (!(0, import_mini2.safeParse)(leadFormPrimitiveSchemas[primitive], value).success) {
2048
+ violations.push({ role, rule: "invalid_value" });
2049
+ continue;
2050
+ }
2051
+ const allowed = contract?.options[role] ?? registryOptions(role);
2052
+ if (allowed?.length && optionKeys(value).some((key) => !allowed.includes(key))) {
2053
+ violations.push({ role, rule: "unknown_option" });
2054
+ }
2055
+ }
2056
+ for (const { role, requiredWhen } of contract?.requires ?? []) {
2057
+ const owing = requiredWhen === null || optionKeys(answered.get(requiredWhen.role)).some((key) => requiredWhen.anyOf.includes(key));
2058
+ if (owing && !answered.has(role)) violations.push({ role, rule: "missing_required" });
2059
+ }
2060
+ for (const group of contract?.requiresAny ?? []) {
2061
+ if (!group.some((role) => answered.has(role))) {
2062
+ violations.push({ role: group.join("|"), rule: "missing_any_of" });
2063
+ }
2064
+ }
2065
+ return violations;
2066
+ }
2067
+ function primitiveOf(role) {
2068
+ if (ADD_ON.test(role)) return "bool";
2069
+ return KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role].primitive : null;
2070
+ }
2071
+ function registryOptions(role) {
2072
+ const spec = KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role] : void 0;
2073
+ return spec && "options" in spec ? spec.options.map((o) => o.key) : void 0;
2074
+ }
2075
+ function optionKeys(value) {
2076
+ if (typeof value === "string") return [value];
2077
+ return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
2078
+ }
2079
+ function slotFields(dateTime) {
2080
+ const written = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(dateTime);
2081
+ if (!written) {
2082
+ throw new TypeError(
2083
+ `slotFields needs the slot's wall time without an offset ("2026-10-13T09:30"), got "${dateTime}"`
2084
+ );
2085
+ }
2086
+ return { preferred_date: written[1], preferred_time: { start: written[2], end: null } };
2087
+ }
2088
+ function timeWindow(start, end, label) {
2089
+ return { start, end: end ?? null, ...label ? { label } : {} };
2090
+ }
2091
+
1924
2092
  // ../tracking-core/src/resources/http/errors.ts
1925
2093
  var AranovaApiError = class extends Error {
1926
2094
  constructor(message, options) {
@@ -1960,11 +2128,11 @@ async function apiRequest(config, method, path, body, extraHeaders) {
1960
2128
  try {
1961
2129
  const parsed = await response.json();
1962
2130
  if (parsed && typeof parsed === "object") {
1963
- const record3 = parsed;
1964
- if (typeof record3.detail === "string") detail = record3.detail;
1965
- if (typeof record3.code === "string") code = record3.code;
1966
- if (record3.context && typeof record3.context === "object") {
1967
- context = record3.context;
2131
+ const record4 = parsed;
2132
+ if (typeof record4.detail === "string") detail = record4.detail;
2133
+ if (typeof record4.code === "string") code = record4.code;
2134
+ if (record4.context && typeof record4.context === "object") {
2135
+ context = record4.context;
1968
2136
  }
1969
2137
  }
1970
2138
  } catch {
@@ -2018,7 +2186,7 @@ var DROP_OFF_KEYS = {
2018
2186
  waitForIt: "wait-for-it",
2019
2187
  dropOff: "drop-off"
2020
2188
  };
2021
- function formSubmitPayload(input, formSubmit, contractHash) {
2189
+ function formSubmitPayload(input, formSubmit, runtime) {
2022
2190
  const field = (role, name, type, label, value) => ({ name, type, label, value, role });
2023
2191
  const text = (value) => value?.trim() || void 0;
2024
2192
  const { vehicle, dropOff } = input;
@@ -2028,7 +2196,7 @@ function formSubmitPayload(input, formSubmit, contractHash) {
2028
2196
  // E.164 on the wire: it keys the customer and enhanced-conversion matching.
2029
2197
  field("phone", "phone", "tel", "Phone", toE164(input.phone) ?? input.phone),
2030
2198
  field("email", "email", "email", "Email", text(input.email)),
2031
- field("service", "service", "select", "Service", input.services),
2199
+ field("service", "service", "select", "Service", [...input.services]),
2032
2200
  field(
2033
2201
  "vehicle",
2034
2202
  "vehicle",
@@ -2053,6 +2221,14 @@ function formSubmitPayload(input, formSubmit, contractHash) {
2053
2221
  const reported = new Set(entries.map((item) => item.name));
2054
2222
  const fields = entries.filter((item) => item.value !== void 0);
2055
2223
  const extra = (formSubmit.extraFields ?? []).filter((item) => !reported.has(item.name));
2224
+ const settings = typedClientSettings(formSubmit.tracking);
2225
+ const { violations, hash } = judgeLeadForm(
2226
+ "booking",
2227
+ formSubmit.formId,
2228
+ fields.map((item) => [item.role, item.value]),
2229
+ formSubmit.contracts,
2230
+ { ...settings, trackingConfig: settings.trackingConfig ?? runtime?.ref }
2231
+ );
2056
2232
  return {
2057
2233
  form: {
2058
2234
  id: formSubmit.formId,
@@ -2060,7 +2236,8 @@ function formSubmitPayload(input, formSubmit, contractHash) {
2060
2236
  fields: [...fields, ...extra],
2061
2237
  kind: "booking",
2062
2238
  contract_version: LEAD_FORM_REGISTRY_VERSION,
2063
- ...contractHash ? { contract_hash: contractHash } : {}
2239
+ ...hash ? { contract_hash: hash } : {},
2240
+ ...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {}
2064
2241
  },
2065
2242
  page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
2066
2243
  };
@@ -2159,10 +2336,9 @@ function createSalesBookingsClient(config, firing) {
2159
2336
  }
2160
2337
  if (formSubmit && !submittedForms.has(attemptKey)) {
2161
2338
  submittedForms.add(attemptKey);
2162
- const contract = runtime?.leadForms()?.contracts.find((c) => c.form_kind === "booking");
2163
2339
  formSubmit.tracking.trackEvent(
2164
2340
  "form_submit",
2165
- formSubmitPayload(input, formSubmit, contract?.contract_hash ?? null)
2341
+ formSubmitPayload(input, formSubmit, runtime)
2166
2342
  );
2167
2343
  }
2168
2344
  const body = {
@@ -2178,7 +2354,7 @@ function createSalesBookingsClient(config, firing) {
2178
2354
  email: input.email?.trim() || null,
2179
2355
  vehicle: input.vehicle ?? null,
2180
2356
  drop_off: input.dropOff ?? null,
2181
- services: input.services,
2357
+ services: [...input.services],
2182
2358
  notes: input.notes?.trim() || null,
2183
2359
  marketing_sms_consent: input.marketingSmsConsent === true,
2184
2360
  page_path: typeof window === "undefined" ? null : window.location.pathname
@@ -2265,7 +2441,7 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
2265
2441
  }
2266
2442
  function createSalesClient(config) {
2267
2443
  if (config.firing) registerCapability("conversion_goals_manual");
2268
- async function record3(input) {
2444
+ async function record4(input) {
2269
2445
  const currency = input.currency ?? config.defaultCurrency;
2270
2446
  if (!currency) {
2271
2447
  throw new Error(
@@ -2291,9 +2467,9 @@ function createSalesClient(config) {
2291
2467
  return sale;
2292
2468
  }
2293
2469
  return {
2294
- record: record3,
2470
+ record: record4,
2295
2471
  // recordSale is the intent-revealing alias — same behavior, clearer call site.
2296
- recordSale: record3,
2472
+ recordSale: record4,
2297
2473
  trackConversion(key, options) {
2298
2474
  if (config.firing && "fireConversion" in config.firing) {
2299
2475
  if (options?.userData && getConsentState() !== "denied") stashUserData(options.userData);
@@ -2413,17 +2589,17 @@ function createSalesClient(config) {
2413
2589
  }
2414
2590
 
2415
2591
  // ../tracking-core/src/resources/sales/schema.ts
2416
- var z4 = __toESM(require("zod/mini"));
2592
+ var z5 = __toESM(require("zod/mini"));
2417
2593
 
2418
2594
  // ../tracking-core/src/resources/sales/generated/zod.gen.ts
2419
- var z3 = __toESM(require("zod/mini"));
2420
- var zAutoLeapSaleFacts = z3.object({
2421
- first_order: z3.boolean(),
2422
- fleet_customer: z3.boolean(),
2423
- invoice_code: z3.string(),
2424
- invoice_id: z3.string()
2595
+ var z4 = __toESM(require("zod/mini"));
2596
+ var zAutoLeapSaleFacts = z4.object({
2597
+ first_order: z4.boolean(),
2598
+ fleet_customer: z4.boolean(),
2599
+ invoice_code: z4.string(),
2600
+ invoice_id: z4.string()
2425
2601
  });
2426
- var zErrorCode = z3.enum([
2602
+ var zErrorCode = z4.enum([
2427
2603
  "missing_credentials",
2428
2604
  "invalid_api_key",
2429
2605
  "not_authenticated",
@@ -2467,37 +2643,37 @@ var zErrorCode = z3.enum([
2467
2643
  "rate_limited",
2468
2644
  "internal_error"
2469
2645
  ]);
2470
- var zSaleItemEntitySchema = z3.object({
2471
- category: z3.nullable(z3.string()),
2472
- external_item_id: z3.nullable(z3.string()),
2473
- id: z3.uuid(),
2474
- name: z3.nullable(z3.string()),
2475
- quantity: z3.string().check(z3.regex(/^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$/)),
2476
- unit_cost_cents: z3.nullable(z3.int()),
2477
- unit_price_cents: z3.int()
2646
+ var zSaleItemEntitySchema = z4.object({
2647
+ category: z4.nullable(z4.string()),
2648
+ external_item_id: z4.nullable(z4.string()),
2649
+ id: z4.uuid(),
2650
+ name: z4.nullable(z4.string()),
2651
+ quantity: z4.string().check(z4.regex(/^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$/)),
2652
+ unit_cost_cents: z4.nullable(z4.int()),
2653
+ unit_price_cents: z4.int()
2478
2654
  });
2479
- var zSaleItemInputSchema = z3.strictObject({
2480
- category: z3.nullish(z3.string()),
2481
- external_item_id: z3.nullish(z3.string()),
2482
- name: z3.nullish(z3.string()),
2483
- quantity: z3.string().check(z3.regex(/^\d+(\.\d{1,3})?$/)),
2484
- unit_cost_cents: z3.nullish(z3.int().check(z3.gte(0))),
2485
- unit_price_cents: z3.int().check(z3.gte(0))
2655
+ var zSaleItemInputSchema = z4.strictObject({
2656
+ category: z4.nullish(z4.string()),
2657
+ external_item_id: z4.nullish(z4.string()),
2658
+ name: z4.nullish(z4.string()),
2659
+ quantity: z4.string().check(z4.regex(/^\d+(\.\d{1,3})?$/)),
2660
+ unit_cost_cents: z4.nullish(z4.int().check(z4.gte(0))),
2661
+ unit_price_cents: z4.int().check(z4.gte(0))
2486
2662
  });
2487
- var zSaleServiceEntitySchema = z3.object({
2488
- amount_cents: z3.int(),
2489
- id: z3.uuid(),
2490
- mapped: z3.nullable(z3.boolean()),
2491
- service_id: z3.uuid(),
2492
- service_key: z3.string(),
2493
- service_label: z3.string()
2663
+ var zSaleServiceEntitySchema = z4.object({
2664
+ amount_cents: z4.int(),
2665
+ id: z4.uuid(),
2666
+ mapped: z4.nullable(z4.boolean()),
2667
+ service_id: z4.uuid(),
2668
+ service_key: z4.string(),
2669
+ service_label: z4.string()
2494
2670
  });
2495
- var zSaleServiceInputSchema = z3.strictObject({
2496
- amount_cents: z3.int().check(z3.gte(0)),
2497
- service: z3.string()
2671
+ var zSaleServiceInputSchema = z4.strictObject({
2672
+ amount_cents: z4.int().check(z4.gte(0)),
2673
+ service: z4.string()
2498
2674
  });
2499
- var zSaleSource = z3.enum(["api", "admin", "autoleap"]);
2500
- var zSmsAutomationState = z3.enum([
2675
+ var zSaleSource = z4.enum(["api", "admin", "autoleap"]);
2676
+ var zSmsAutomationState = z4.enum([
2501
2677
  "needs_check",
2502
2678
  "failed",
2503
2679
  "undelivered",
@@ -2509,7 +2685,7 @@ var zSmsAutomationState = z3.enum([
2509
2685
  "eligible",
2510
2686
  "not_applicable"
2511
2687
  ]);
2512
- var zSmsWithheldReason = z3.enum([
2688
+ var zSmsWithheldReason = z4.enum([
2513
2689
  "automation_disabled",
2514
2690
  "sms_disabled",
2515
2691
  "no_phone",
@@ -2535,77 +2711,79 @@ var zSmsWithheldReason = z3.enum([
2535
2711
  "confirmed_by_integration",
2536
2712
  "test_or_bot_session",
2537
2713
  "invalid_phone",
2538
- "recently_texted"
2714
+ "recently_texted",
2715
+ "do_not_contact",
2716
+ "do_not_text_tag"
2539
2717
  ]);
2540
- var zSaleSmsStatusSchema = z3.object({
2541
- can_send_now: z3._default(z3.boolean(), false),
2542
- last_message_at: z3.nullable(z3.iso.datetime({ offset: true })),
2543
- reason_detail: z3.nullable(z3.string()),
2718
+ var zSaleSmsStatusSchema = z4.object({
2719
+ can_send_now: z4._default(z4.boolean(), false),
2720
+ last_message_at: z4.nullable(z4.iso.datetime({ offset: true })),
2721
+ reason_detail: z4.nullable(z4.string()),
2544
2722
  state: zSmsAutomationState,
2545
- suppressed_by_other_sale: z3._default(z3.boolean(), false),
2546
- withheld_reason: z3.nullable(zSmsWithheldReason)
2723
+ suppressed_by_other_sale: z4._default(z4.boolean(), false),
2724
+ withheld_reason: z4.nullable(zSmsWithheldReason)
2547
2725
  });
2548
- var zSupportedCurrency = z3.enum(["USD", "CAD"]);
2549
- var zTrackingEnvironment = z3.enum(["production", "development"]);
2550
- var zSaleCreateSchema = z3.strictObject({
2551
- amount_total_cents: z3.nullish(z3.int().check(z3.gte(0))),
2726
+ var zSupportedCurrency = z4.enum(["USD", "CAD"]);
2727
+ var zTrackingEnvironment = z4.enum(["production", "development"]);
2728
+ var zSaleCreateSchema = z4.strictObject({
2729
+ amount_total_cents: z4.nullish(z4.int().check(z4.gte(0))),
2552
2730
  currency: zSupportedCurrency,
2553
- customer_email: z3.nullish(z3.email().check(z3.maxLength(320))),
2554
- customer_name: z3.nullish(z3.string().check(z3.maxLength(200))),
2555
- customer_phone: z3.nullish(z3.string().check(z3.maxLength(64))),
2556
- description: z3.nullish(z3.string()),
2557
- environment: z3._default(z3.optional(zTrackingEnvironment), "production"),
2558
- external_id: z3.nullish(z3.string()),
2559
- items: z3.optional(z3.array(zSaleItemInputSchema)),
2560
- metadata: z3.nullish(z3.record(z3.string(), z3.unknown())),
2561
- occurred_at: z3.iso.datetime({ offset: true }),
2562
- service: z3.nullish(z3.string()),
2563
- services: z3.nullish(z3.array(zSaleServiceInputSchema)),
2564
- sms_consent: z3.nullish(z3.boolean())
2731
+ customer_email: z4.nullish(z4.email().check(z4.maxLength(320))),
2732
+ customer_name: z4.nullish(z4.string().check(z4.maxLength(200))),
2733
+ customer_phone: z4.nullish(z4.string().check(z4.maxLength(64))),
2734
+ description: z4.nullish(z4.string()),
2735
+ environment: z4._default(z4.optional(zTrackingEnvironment), "production"),
2736
+ external_id: z4.nullish(z4.string()),
2737
+ items: z4.optional(z4.array(zSaleItemInputSchema)),
2738
+ metadata: z4.nullish(z4.record(z4.string(), z4.unknown())),
2739
+ occurred_at: z4.iso.datetime({ offset: true }),
2740
+ service: z4.nullish(z4.string()),
2741
+ services: z4.nullish(z4.array(zSaleServiceInputSchema)),
2742
+ sms_consent: z4.nullish(z4.boolean())
2565
2743
  });
2566
- var zValidationError = z3.object({
2567
- ctx: z3.optional(z3.record(z3.string(), z3.unknown())),
2568
- input: z3.optional(z3.unknown()),
2569
- loc: z3.array(z3.union([z3.string(), z3.int()])),
2570
- msg: z3.string(),
2571
- type: z3.string()
2744
+ var zValidationError = z4.object({
2745
+ ctx: z4.optional(z4.record(z4.string(), z4.unknown())),
2746
+ input: z4.optional(z4.unknown()),
2747
+ loc: z4.array(z4.union([z4.string(), z4.int()])),
2748
+ msg: z4.string(),
2749
+ type: z4.string()
2572
2750
  });
2573
- var zHttpValidationError = z3.object({
2574
- detail: z3.optional(z3.array(zValidationError))
2751
+ var zHttpValidationError = z4.object({
2752
+ detail: z4.optional(z4.array(zValidationError))
2575
2753
  });
2576
- var zValidationErrorItem = z3.object({
2577
- loc: z3.array(z3.union([z3.string(), z3.int()])),
2578
- msg: z3.string(),
2579
- type: z3.string()
2754
+ var zValidationErrorItem = z4.object({
2755
+ loc: z4.array(z4.union([z4.string(), z4.int()])),
2756
+ msg: z4.string(),
2757
+ type: z4.string()
2580
2758
  });
2581
- var zApiErrorSchema = z3.object({
2759
+ var zApiErrorSchema = z4.object({
2582
2760
  code: zErrorCode,
2583
- context: z3._default(z3.nullish(z3.record(z3.string(), z3.unknown())), null),
2584
- detail: z3.string(),
2585
- errors: z3._default(z3.nullish(z3.array(zValidationErrorItem)), null),
2586
- request_id: z3._default(z3.nullish(z3.string()), null)
2761
+ context: z4._default(z4.nullish(z4.record(z4.string(), z4.unknown())), null),
2762
+ detail: z4.string(),
2763
+ errors: z4._default(z4.nullish(z4.array(zValidationErrorItem)), null),
2764
+ request_id: z4._default(z4.nullish(z4.string()), null)
2587
2765
  });
2588
- var zWritebackEmailSource = z3.enum(["NONE", "SALE", "CUSTOMER", "HARVESTED"]);
2589
- var zWritebackEnrichmentStatus = z3.enum(["NONE", "MATCHED", "AMBIGUOUS"]);
2590
- var zWritebackSaleUploadCounts = z3.object({
2591
- failed: z3._default(z3.int(), 0),
2592
- pending: z3._default(z3.int(), 0),
2593
- skipped: z3._default(z3.int(), 0),
2594
- submitted: z3._default(z3.int(), 0),
2595
- total: z3._default(z3.int(), 0),
2596
- uploaded: z3._default(z3.int(), 0)
2766
+ var zWritebackEmailSource = z4.enum(["NONE", "SALE", "CUSTOMER", "HARVESTED"]);
2767
+ var zWritebackEnrichmentStatus = z4.enum(["NONE", "MATCHED", "AMBIGUOUS"]);
2768
+ var zWritebackSaleUploadCounts = z4.object({
2769
+ failed: z4._default(z4.int(), 0),
2770
+ pending: z4._default(z4.int(), 0),
2771
+ skipped: z4._default(z4.int(), 0),
2772
+ submitted: z4._default(z4.int(), 0),
2773
+ total: z4._default(z4.int(), 0),
2774
+ uploaded: z4._default(z4.int(), 0)
2597
2775
  });
2598
- var zSaleWritebackStatusSchema = z3.object({
2599
- blocked_reason: z3.nullable(z3.string()),
2600
- can_dispatch: z3._default(z3.boolean(), false),
2601
- email_source: z3.nullable(zWritebackEmailSource),
2602
- enrichment_status: z3.nullable(zWritebackEnrichmentStatus),
2603
- gclid_attached: z3._default(z3.boolean(), false),
2604
- identifiers_sent: z3.nullable(z3.string()),
2605
- mapped_service_ids: z3.array(z3.uuid()),
2606
- matched_submit_count: z3.nullable(z3.int()),
2607
- needs_force: z3._default(z3.boolean(), false),
2608
- rollup: z3.enum([
2776
+ var zSaleWritebackStatusSchema = z4.object({
2777
+ blocked_reason: z4.nullable(z4.string()),
2778
+ can_dispatch: z4._default(z4.boolean(), false),
2779
+ email_source: z4.nullable(zWritebackEmailSource),
2780
+ enrichment_status: z4.nullable(zWritebackEnrichmentStatus),
2781
+ gclid_attached: z4._default(z4.boolean(), false),
2782
+ identifiers_sent: z4.nullable(z4.string()),
2783
+ mapped_service_ids: z4.array(z4.uuid()),
2784
+ matched_submit_count: z4.nullable(z4.int()),
2785
+ needs_force: z4._default(z4.boolean(), false),
2786
+ rollup: z4.enum([
2609
2787
  "failed",
2610
2788
  "skipped",
2611
2789
  "pending",
@@ -2615,39 +2793,39 @@ var zSaleWritebackStatusSchema = z3.object({
2615
2793
  "out_of_window",
2616
2794
  "blocked"
2617
2795
  ]),
2618
- stale: z3._default(z3.boolean(), false),
2619
- uncovered_service_ids: z3.array(z3.uuid()),
2796
+ stale: z4._default(z4.boolean(), false),
2797
+ uncovered_service_ids: z4.array(z4.uuid()),
2620
2798
  uploads: zWritebackSaleUploadCounts
2621
2799
  });
2622
- var zSaleEntitySchema = z3.object({
2623
- amount_total_cents: z3.int(),
2624
- business_id: z3.uuid(),
2625
- business_name: z3.nullable(z3.string()),
2626
- created_at: z3.iso.datetime({ offset: true }),
2627
- currency: z3.string(),
2628
- customer_email: z3.nullable(z3.string()),
2629
- customer_name: z3.nullable(z3.string()),
2630
- customer_name_placeholder_confirmed: z3._default(z3.boolean(), false),
2631
- customer_name_placeholder_confirmed_at: z3.nullable(z3.iso.datetime({ offset: true })),
2632
- customer_phone: z3.nullable(z3.string()),
2633
- description: z3.nullable(z3.string()),
2800
+ var zSaleEntitySchema = z4.object({
2801
+ amount_total_cents: z4.int(),
2802
+ business_id: z4.uuid(),
2803
+ business_name: z4.nullable(z4.string()),
2804
+ created_at: z4.iso.datetime({ offset: true }),
2805
+ currency: z4.string(),
2806
+ customer_email: z4.nullable(z4.string()),
2807
+ customer_name: z4.nullable(z4.string()),
2808
+ customer_name_placeholder_confirmed: z4._default(z4.boolean(), false),
2809
+ customer_name_placeholder_confirmed_at: z4.nullable(z4.iso.datetime({ offset: true })),
2810
+ customer_phone: z4.nullable(z4.string()),
2811
+ description: z4.nullable(z4.string()),
2634
2812
  environment: zTrackingEnvironment,
2635
- external_id: z3.nullable(z3.string()),
2636
- id: z3.uuid(),
2637
- items: z3.array(zSaleItemEntitySchema),
2638
- metadata: z3.nullable(z3.record(z3.string(), z3.unknown())),
2639
- occurred_at: z3.iso.datetime({ offset: true }),
2640
- service_id: z3.nullable(z3.uuid()),
2641
- service_key: z3.nullable(z3.string()),
2642
- service_label: z3.nullable(z3.string()),
2643
- services: z3.array(zSaleServiceEntitySchema),
2644
- sms_automation: z3.nullable(zSaleSmsStatusSchema),
2645
- sms_consent: z3._default(z3.boolean(), false),
2646
- sms_consent_granted_at: z3.nullable(z3.iso.datetime({ offset: true })),
2813
+ external_id: z4.nullable(z4.string()),
2814
+ id: z4.uuid(),
2815
+ items: z4.array(zSaleItemEntitySchema),
2816
+ metadata: z4.nullable(z4.record(z4.string(), z4.unknown())),
2817
+ occurred_at: z4.iso.datetime({ offset: true }),
2818
+ service_id: z4.nullable(z4.uuid()),
2819
+ service_key: z4.nullable(z4.string()),
2820
+ service_label: z4.nullable(z4.string()),
2821
+ services: z4.array(zSaleServiceEntitySchema),
2822
+ sms_automation: z4.nullable(zSaleSmsStatusSchema),
2823
+ sms_consent: z4._default(z4.boolean(), false),
2824
+ sms_consent_granted_at: z4.nullable(z4.iso.datetime({ offset: true })),
2647
2825
  source: zSaleSource,
2648
- source_facts: z3.nullable(zAutoLeapSaleFacts),
2649
- updated_at: z3.iso.datetime({ offset: true }),
2650
- writeback: z3.nullable(zSaleWritebackStatusSchema)
2826
+ source_facts: z4.nullable(zAutoLeapSaleFacts),
2827
+ updated_at: z4.iso.datetime({ offset: true }),
2828
+ writeback: z4.nullable(zSaleWritebackStatusSchema)
2651
2829
  });
2652
2830
 
2653
2831
  // ../tracking-core/src/resources/sales/schema.ts
@@ -2656,11 +2834,11 @@ var saleServiceSchema = zSaleServiceInputSchema;
2656
2834
  var currencySchema = zSupportedCurrency;
2657
2835
  var SUPPORTED_CURRENCIES = currencySchema.options;
2658
2836
  var SALE_SOURCES = zSaleSource.options;
2659
- var centsSchema = z4.int().check(z4.gte(0));
2660
- var metadataSchema = z4.record(z4.string(), z4.unknown());
2661
- var customerNameSchema = z4.string().check(z4.maxLength(200));
2662
- var customerPhoneSchema = z4.string().check(z4.maxLength(64));
2663
- var customerEmailSchema = z4.email().check(z4.maxLength(320));
2837
+ var centsSchema = z5.int().check(z5.gte(0));
2838
+ var metadataSchema = z5.record(z5.string(), z5.unknown());
2839
+ var customerNameSchema = z5.string().check(z5.maxLength(200));
2840
+ var customerPhoneSchema = z5.string().check(z5.maxLength(64));
2841
+ var customerEmailSchema = z5.email().check(z5.maxLength(320));
2664
2842
  function addIssue(ctx, path, message) {
2665
2843
  ctx.issues.push({ code: "custom", input: ctx.value, path, message });
2666
2844
  }
@@ -2694,24 +2872,24 @@ function refineServiceXor(val, ctx, { requireAmount }) {
2694
2872
  );
2695
2873
  }
2696
2874
  }
2697
- var saleCreateSchema = z4.extend(zSaleCreateSchema, { items: z4._default(z4.array(saleItemSchema), []) }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: true }));
2698
- var saleUpdateSchema = z4.strictObject({
2699
- description: z4.nullish(z4.string()),
2700
- service: z4.nullish(z4.string()),
2701
- services: z4.nullish(z4.array(saleServiceSchema)),
2702
- currency: z4.optional(currencySchema),
2703
- amount_total_cents: z4.optional(centsSchema),
2704
- occurred_at: z4.optional(z4.iso.datetime()),
2705
- items: z4.optional(z4.array(saleItemSchema)),
2706
- metadata: z4.nullish(metadataSchema),
2707
- customer_name: z4.nullish(customerNameSchema),
2875
+ var saleCreateSchema = z5.extend(zSaleCreateSchema, { items: z5._default(z5.array(saleItemSchema), []) }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: true }));
2876
+ var saleUpdateSchema = z5.strictObject({
2877
+ description: z5.nullish(z5.string()),
2878
+ service: z5.nullish(z5.string()),
2879
+ services: z5.nullish(z5.array(saleServiceSchema)),
2880
+ currency: z5.optional(currencySchema),
2881
+ amount_total_cents: z5.optional(centsSchema),
2882
+ occurred_at: z5.optional(z5.iso.datetime()),
2883
+ items: z5.optional(z5.array(saleItemSchema)),
2884
+ metadata: z5.nullish(metadataSchema),
2885
+ customer_name: z5.nullish(customerNameSchema),
2708
2886
  // Re-attest when changing a filler-looking name; the server clears the
2709
2887
  // prior attestation whenever `customer_name` changes.
2710
- customer_name_placeholder_confirmed: z4.optional(z4.boolean()),
2711
- customer_phone: z4.nullish(customerPhoneSchema),
2712
- customer_email: z4.nullish(customerEmailSchema),
2888
+ customer_name_placeholder_confirmed: z5.optional(z5.boolean()),
2889
+ customer_phone: z5.nullish(customerPhoneSchema),
2890
+ customer_email: z5.nullish(customerEmailSchema),
2713
2891
  // NOT NULL server-side: omit to leave unchanged (explicit null is rejected).
2714
- sms_consent: z4.optional(z4.boolean())
2892
+ sms_consent: z5.optional(z5.boolean())
2715
2893
  }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: false }));
2716
2894
  var TRACKING_RANGES = ["24h", "7d", "30d"];
2717
2895
  var NAMED_RANGES = [
@@ -2738,23 +2916,6 @@ function phoneField(name, raw, country, label = null) {
2738
2916
  return { name, type: "phone", label, value: toE164(raw, country) };
2739
2917
  }
2740
2918
 
2741
- // ../tracking-core/src/lead-forms/submit.ts
2742
- var import_mini = require("zod/mini");
2743
- var KNOWN_ROLES = new Set(LEAD_FORM_ROLES);
2744
- var ROLE_ORDER = new Map(LEAD_FORM_ROLES.map((role, index) => [role, index]));
2745
- function slotFields(dateTime) {
2746
- const written = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(dateTime);
2747
- if (!written) {
2748
- throw new TypeError(
2749
- `slotFields needs the slot's wall time without an offset ("2026-10-13T09:30"), got "${dateTime}"`
2750
- );
2751
- }
2752
- return { preferred_date: written[1], preferred_time: { start: written[2], end: null } };
2753
- }
2754
- function timeWindow(start, end, label) {
2755
- return { start, end: end ?? null, ...label ? { label } : {} };
2756
- }
2757
-
2758
2919
  // src/index.ts
2759
2920
  var import_client2 = require("@aranova/tracking-react/client");
2760
2921
  var import_client3 = require("@aranova/tracking-react/client");