@aranova/tracking-react 1.14.0 → 1.15.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.
- package/dist/{bookings-Bw2ImtPd.d.ts → bookings-CkfA5XOM.d.ts} +283 -8
- package/dist/{bookings-CDGNZUaH.d.mts → bookings-DFz3BUiP.d.mts} +283 -8
- package/dist/client.d.mts +10 -9
- package/dist/client.d.ts +10 -9
- package/dist/client.js +157 -141
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +157 -141
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +5 -6
- package/dist/index.d.ts +5 -6
- package/dist/index.js +365 -203
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +365 -203
- package/dist/index.mjs.map +1 -1
- package/dist/{submit-DuvP5AGN.d.ts → ingest-typed-BO6Arbw-.d.mts} +2 -252
- package/dist/{submit-rqgXl-Wg.d.mts → ingest-typed-D7I4aQ7p.d.ts} +2 -252
- package/dist/{phone-utils-Cfdx474X.d.mts → phone-utils-CYr6AmEP.d.mts} +55 -2
- package/dist/{phone-utils-D2TGPCQW.d.ts → phone-utils-CYr6AmEP.d.ts} +55 -2
- package/dist/phone.d.mts +1 -2
- package/dist/phone.d.ts +1 -2
- package/dist/{sales-DkdrGIUS.d.ts → sales-C0FMkN4m.d.ts} +1 -1
- package/dist/{sales-D4aU73mR.d.mts → sales-KbTcowYa.d.mts} +1 -1
- package/dist/sales.d.mts +3 -3
- package/dist/sales.d.ts +3 -3
- package/dist/sales.js +1205 -170
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +1205 -170
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/form-submit-C_vJXCxh.d.mts +0 -57
- package/dist/form-submit-C_vJXCxh.d.ts +0 -57
package/dist/index.mjs
CHANGED
|
@@ -457,10 +457,10 @@ function readStoredRecord() {
|
|
|
457
457
|
return null;
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
|
-
function writeRecord(
|
|
461
|
-
memoryRecord =
|
|
460
|
+
function writeRecord(record4) {
|
|
461
|
+
memoryRecord = record4;
|
|
462
462
|
try {
|
|
463
|
-
window.localStorage.setItem(LANDING_STORAGE_KEY, JSON.stringify(
|
|
463
|
+
window.localStorage.setItem(LANDING_STORAGE_KEY, JSON.stringify(record4));
|
|
464
464
|
} catch {
|
|
465
465
|
}
|
|
466
466
|
}
|
|
@@ -482,9 +482,9 @@ function getOrCaptureLandingParams(sessionId, url) {
|
|
|
482
482
|
if (memoryRecord && memoryRecord.session_id === sessionId) {
|
|
483
483
|
return memoryRecord.params;
|
|
484
484
|
}
|
|
485
|
-
const
|
|
486
|
-
writeRecord(
|
|
487
|
-
return
|
|
485
|
+
const record4 = { session_id: sessionId, params: captureFromUrl(url) };
|
|
486
|
+
writeRecord(record4);
|
|
487
|
+
return record4.params;
|
|
488
488
|
}
|
|
489
489
|
function buildLandingPayloadFields(sessionId, override) {
|
|
490
490
|
const params = override ?? (typeof window === "undefined" ? null : getOrCaptureLandingParams(sessionId));
|
|
@@ -1711,8 +1711,81 @@ var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
|
|
|
1711
1711
|
var SDK_SURFACE_HEADER = "X-Aranova-Sdk-Surface";
|
|
1712
1712
|
var SDK_ENVIRONMENT_HEADER = "X-Aranova-Sdk-Environment";
|
|
1713
1713
|
|
|
1714
|
-
// ../tracking-core/src/
|
|
1714
|
+
// ../tracking-core/src/ingest-typed.ts
|
|
1715
|
+
import { parse, safeParse } from "zod/mini";
|
|
1716
|
+
|
|
1717
|
+
// ../tracking-core/src/events/form-submit.ts
|
|
1715
1718
|
import * as z2 from "zod/mini";
|
|
1719
|
+
var jsonValueSchema = z2.lazy(
|
|
1720
|
+
() => z2.union([
|
|
1721
|
+
z2.string(),
|
|
1722
|
+
z2.number(),
|
|
1723
|
+
z2.boolean(),
|
|
1724
|
+
z2.null(),
|
|
1725
|
+
z2.array(jsonValueSchema),
|
|
1726
|
+
z2.record(z2.string(), jsonValueSchema)
|
|
1727
|
+
])
|
|
1728
|
+
).register(z2.globalRegistry, { id: "JsonSerializableValue" });
|
|
1729
|
+
var contractNameSchema = z2.string().check(z2.regex(/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/));
|
|
1730
|
+
var contractName = contractNameSchema;
|
|
1731
|
+
var violationRole = z2.string().check(
|
|
1732
|
+
z2.maxLength(200),
|
|
1733
|
+
z2.regex(
|
|
1734
|
+
/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?(\|[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?)*$/
|
|
1735
|
+
)
|
|
1736
|
+
);
|
|
1737
|
+
var MAX_CONTRACT_VIOLATIONS = 50;
|
|
1738
|
+
var contractViolationSchema = z2.strictObject({
|
|
1739
|
+
role: z2.nullable(violationRole),
|
|
1740
|
+
rule: z2.string().check(z2.regex(/^[a-z][a-z_]{0,47}$/))
|
|
1741
|
+
});
|
|
1742
|
+
var formSubmitMetadataSchema = z2.strictObject({
|
|
1743
|
+
form: z2.strictObject({
|
|
1744
|
+
id: z2.string(),
|
|
1745
|
+
action: z2.nullable(z2.string()),
|
|
1746
|
+
fields: z2.optional(
|
|
1747
|
+
z2.array(
|
|
1748
|
+
z2.strictObject({
|
|
1749
|
+
name: z2.string(),
|
|
1750
|
+
type: z2.string(),
|
|
1751
|
+
label: z2.nullable(z2.string()),
|
|
1752
|
+
value: jsonValueSchema,
|
|
1753
|
+
role: z2.optional(z2.nullable(contractName))
|
|
1754
|
+
})
|
|
1755
|
+
)
|
|
1756
|
+
),
|
|
1757
|
+
kind: z2.optional(z2.nullable(contractName)),
|
|
1758
|
+
contract_version: z2.optional(z2.nullable(z2.int().check(z2.gte(1)))),
|
|
1759
|
+
contract_hash: z2.optional(z2.nullable(z2.string().check(z2.maxLength(64)))),
|
|
1760
|
+
extra: z2.optional(
|
|
1761
|
+
z2.nullable(
|
|
1762
|
+
z2.array(
|
|
1763
|
+
z2.strictObject({
|
|
1764
|
+
key: z2.string().check(z2.maxLength(64)),
|
|
1765
|
+
label: z2.string().check(z2.maxLength(200)),
|
|
1766
|
+
value: jsonValueSchema
|
|
1767
|
+
})
|
|
1768
|
+
).check(z2.maxLength(20))
|
|
1769
|
+
)
|
|
1770
|
+
),
|
|
1771
|
+
contract_violations: z2.optional(
|
|
1772
|
+
z2.nullable(z2.array(contractViolationSchema).check(z2.maxLength(MAX_CONTRACT_VIOLATIONS)))
|
|
1773
|
+
)
|
|
1774
|
+
}),
|
|
1775
|
+
page: z2.strictObject({
|
|
1776
|
+
path: z2.string()
|
|
1777
|
+
})
|
|
1778
|
+
});
|
|
1779
|
+
var formSubmitConfigSchema = z2.strictObject({});
|
|
1780
|
+
|
|
1781
|
+
// ../tracking-core/src/ingest-typed.ts
|
|
1782
|
+
var clientSettings = /* @__PURE__ */ new WeakMap();
|
|
1783
|
+
function typedClientSettings(client) {
|
|
1784
|
+
return clientSettings.get(client) ?? {};
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
// ../tracking-core/src/lead-forms/lead-forms.gen.ts
|
|
1788
|
+
import * as z3 from "zod/mini";
|
|
1716
1789
|
var LEAD_FORM_REGISTRY_VERSION = 2;
|
|
1717
1790
|
var LEAD_FORM_KINDS = ["booking", "quote", "contact", "consult", "callback"];
|
|
1718
1791
|
var LEAD_FORM_ROLES = [
|
|
@@ -1752,28 +1825,28 @@ var LEAD_FORM_PRIMITIVES = [
|
|
|
1752
1825
|
"number"
|
|
1753
1826
|
];
|
|
1754
1827
|
var leadFormPrimitiveSchemas = /* @__PURE__ */ (() => ({
|
|
1755
|
-
string:
|
|
1756
|
-
text:
|
|
1757
|
-
enum:
|
|
1758
|
-
multi_enum:
|
|
1759
|
-
bool:
|
|
1760
|
-
date:
|
|
1761
|
-
time_window:
|
|
1762
|
-
start:
|
|
1763
|
-
end:
|
|
1764
|
-
label:
|
|
1828
|
+
string: z3.string().check(z3.maxLength(120)),
|
|
1829
|
+
text: z3.string().check(z3.maxLength(2e3)),
|
|
1830
|
+
enum: z3.string().check(z3.regex(/^[a-z0-9-]{1,48}$/)),
|
|
1831
|
+
multi_enum: z3.array(z3.string().check(z3.regex(/^[a-z0-9-]{1,48}$/))).check(z3.maxLength(10)),
|
|
1832
|
+
bool: z3.boolean(),
|
|
1833
|
+
date: z3.string().check(z3.regex(/^\d{4}-\d{2}-\d{2}$/)),
|
|
1834
|
+
time_window: z3.strictObject({
|
|
1835
|
+
start: z3.string().check(z3.regex(/^([01]\d|2[0-3]):[0-5]\d$/)),
|
|
1836
|
+
end: z3.nullable(z3.string().check(z3.regex(/^([01]\d|2[0-3]):[0-5]\d$/))),
|
|
1837
|
+
label: z3.optional(z3.string().check(z3.maxLength(60)))
|
|
1765
1838
|
}),
|
|
1766
|
-
phone:
|
|
1767
|
-
email:
|
|
1768
|
-
address:
|
|
1769
|
-
line1:
|
|
1770
|
-
line2:
|
|
1771
|
-
city:
|
|
1772
|
-
region:
|
|
1773
|
-
postal_code:
|
|
1774
|
-
country:
|
|
1839
|
+
phone: z3.string().check(z3.regex(/^\+[1-9]\d{6,14}$/)),
|
|
1840
|
+
email: z3.string().check(z3.maxLength(320), z3.regex(/^[^\s@]+@[^\s@]+$/)),
|
|
1841
|
+
address: z3.strictObject({
|
|
1842
|
+
line1: z3.string().check(z3.maxLength(120)),
|
|
1843
|
+
line2: z3.optional(z3.string().check(z3.maxLength(120))),
|
|
1844
|
+
city: z3.optional(z3.string().check(z3.maxLength(120))),
|
|
1845
|
+
region: z3.optional(z3.string().check(z3.maxLength(120))),
|
|
1846
|
+
postal_code: z3.optional(z3.string().check(z3.maxLength(120))),
|
|
1847
|
+
country: z3.optional(z3.string().check(z3.maxLength(120)))
|
|
1775
1848
|
}),
|
|
1776
|
-
number:
|
|
1849
|
+
number: z3.number()
|
|
1777
1850
|
}))();
|
|
1778
1851
|
var LEAD_FORM_ROLE_SPECS = {
|
|
1779
1852
|
given_name: { primitive: "string", smsLabel: "", contactIdentity: true },
|
|
@@ -1823,6 +1896,101 @@ var LEAD_FORM_ROLE_SPECS = {
|
|
|
1823
1896
|
attribution: { primitive: "enum", smsLabel: "", uninteresting: true }
|
|
1824
1897
|
};
|
|
1825
1898
|
|
|
1899
|
+
// ../tracking-core/src/lead-forms/submit.ts
|
|
1900
|
+
import { safeParse as safeParse2 } from "zod/mini";
|
|
1901
|
+
var KNOWN_ROLES = new Set(LEAD_FORM_ROLES);
|
|
1902
|
+
var ROLE_ORDER = new Map(LEAD_FORM_ROLES.map((role, index) => [role, index]));
|
|
1903
|
+
var ADD_ON = /^add_on:[a-z0-9_-]{1,48}$/;
|
|
1904
|
+
var CONTRACT_NAME = /^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/;
|
|
1905
|
+
function judgeLeadForm(kind, formId, fields, contracts, settings) {
|
|
1906
|
+
const generated = contracts?.contracts[kind];
|
|
1907
|
+
const live = liveContract(settings.trackingConfig, kind);
|
|
1908
|
+
const violations = check(live === void 0 ? generated : fromLive(live), fields);
|
|
1909
|
+
const liveHash = live === void 0 ? void 0 : live?.contract_hash ?? null;
|
|
1910
|
+
if (contracts && (liveHash !== void 0 && (generated?.hash ?? null) !== liveHash || contracts.registryVersion !== LEAD_FORM_REGISTRY_VERSION)) {
|
|
1911
|
+
violations.push({ role: null, rule: "contract_behind" });
|
|
1912
|
+
}
|
|
1913
|
+
if (violations.length > 0 && (settings.debug || settings.environment === "development")) {
|
|
1914
|
+
const message = `[AranovaTracking] lead form "${formId}" (${kind}) breaks its contract: ${violations.map((v) => `${v.rule}${v.role ? ` (${v.role})` : ""}`).join(", ")}`;
|
|
1915
|
+
console.error(message);
|
|
1916
|
+
if (settings.debug) throw new Error(message);
|
|
1917
|
+
}
|
|
1918
|
+
return {
|
|
1919
|
+
violations,
|
|
1920
|
+
hash: liveHash === void 0 ? generated?.hash ?? null : liveHash
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
function liveContract(ref, kind) {
|
|
1924
|
+
const leadForms = ref ? getTrackingConfigRuntime(ref).leadForms() : null;
|
|
1925
|
+
if (!leadForms) return void 0;
|
|
1926
|
+
return leadForms.contracts.find((c) => c.form_kind === kind) ?? null;
|
|
1927
|
+
}
|
|
1928
|
+
function fromLive(live) {
|
|
1929
|
+
if (!live) return void 0;
|
|
1930
|
+
return {
|
|
1931
|
+
requires: live.requires.map((r) => ({
|
|
1932
|
+
role: r.role,
|
|
1933
|
+
requiredWhen: r.required_when ? { role: r.required_when.role, anyOf: r.required_when.any_of } : null
|
|
1934
|
+
})),
|
|
1935
|
+
requiresAny: live.requires_any.map((g) => g.roles),
|
|
1936
|
+
// Deprecated keys still resolve: a cached form may send them (ADR-0024 §7).
|
|
1937
|
+
options: Object.fromEntries(live.options.map((o) => [o.role, o.options.map((x) => x.key)]))
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
function check(contract, fields) {
|
|
1941
|
+
const answered = new Map(fields);
|
|
1942
|
+
const violations = [];
|
|
1943
|
+
for (const [role, value] of fields) {
|
|
1944
|
+
const primitive = primitiveOf(role);
|
|
1945
|
+
if (!primitive) {
|
|
1946
|
+
violations.push({ role: CONTRACT_NAME.test(role) ? role : null, rule: "unknown_role" });
|
|
1947
|
+
continue;
|
|
1948
|
+
}
|
|
1949
|
+
if (!safeParse2(leadFormPrimitiveSchemas[primitive], value).success) {
|
|
1950
|
+
violations.push({ role, rule: "invalid_value" });
|
|
1951
|
+
continue;
|
|
1952
|
+
}
|
|
1953
|
+
const allowed = contract?.options[role] ?? registryOptions(role);
|
|
1954
|
+
if (allowed?.length && optionKeys(value).some((key) => !allowed.includes(key))) {
|
|
1955
|
+
violations.push({ role, rule: "unknown_option" });
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
for (const { role, requiredWhen } of contract?.requires ?? []) {
|
|
1959
|
+
const owing = requiredWhen === null || optionKeys(answered.get(requiredWhen.role)).some((key) => requiredWhen.anyOf.includes(key));
|
|
1960
|
+
if (owing && !answered.has(role)) violations.push({ role, rule: "missing_required" });
|
|
1961
|
+
}
|
|
1962
|
+
for (const group of contract?.requiresAny ?? []) {
|
|
1963
|
+
if (!group.some((role) => answered.has(role))) {
|
|
1964
|
+
violations.push({ role: group.join("|"), rule: "missing_any_of" });
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
return violations;
|
|
1968
|
+
}
|
|
1969
|
+
function primitiveOf(role) {
|
|
1970
|
+
if (ADD_ON.test(role)) return "bool";
|
|
1971
|
+
return KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role].primitive : null;
|
|
1972
|
+
}
|
|
1973
|
+
function registryOptions(role) {
|
|
1974
|
+
const spec = KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role] : void 0;
|
|
1975
|
+
return spec && "options" in spec ? spec.options.map((o) => o.key) : void 0;
|
|
1976
|
+
}
|
|
1977
|
+
function optionKeys(value) {
|
|
1978
|
+
if (typeof value === "string") return [value];
|
|
1979
|
+
return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
|
|
1980
|
+
}
|
|
1981
|
+
function slotFields(dateTime) {
|
|
1982
|
+
const written = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(dateTime);
|
|
1983
|
+
if (!written) {
|
|
1984
|
+
throw new TypeError(
|
|
1985
|
+
`slotFields needs the slot's wall time without an offset ("2026-10-13T09:30"), got "${dateTime}"`
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
return { preferred_date: written[1], preferred_time: { start: written[2], end: null } };
|
|
1989
|
+
}
|
|
1990
|
+
function timeWindow(start, end, label) {
|
|
1991
|
+
return { start, end: end ?? null, ...label ? { label } : {} };
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1826
1994
|
// ../tracking-core/src/resources/http/errors.ts
|
|
1827
1995
|
var AranovaApiError = class extends Error {
|
|
1828
1996
|
constructor(message, options) {
|
|
@@ -1862,11 +2030,11 @@ async function apiRequest(config, method, path, body, extraHeaders) {
|
|
|
1862
2030
|
try {
|
|
1863
2031
|
const parsed = await response.json();
|
|
1864
2032
|
if (parsed && typeof parsed === "object") {
|
|
1865
|
-
const
|
|
1866
|
-
if (typeof
|
|
1867
|
-
if (typeof
|
|
1868
|
-
if (
|
|
1869
|
-
context =
|
|
2033
|
+
const record4 = parsed;
|
|
2034
|
+
if (typeof record4.detail === "string") detail = record4.detail;
|
|
2035
|
+
if (typeof record4.code === "string") code = record4.code;
|
|
2036
|
+
if (record4.context && typeof record4.context === "object") {
|
|
2037
|
+
context = record4.context;
|
|
1870
2038
|
}
|
|
1871
2039
|
}
|
|
1872
2040
|
} catch {
|
|
@@ -1920,7 +2088,7 @@ var DROP_OFF_KEYS = {
|
|
|
1920
2088
|
waitForIt: "wait-for-it",
|
|
1921
2089
|
dropOff: "drop-off"
|
|
1922
2090
|
};
|
|
1923
|
-
function formSubmitPayload(input, formSubmit,
|
|
2091
|
+
function formSubmitPayload(input, formSubmit, runtime) {
|
|
1924
2092
|
const field = (role, name, type, label, value) => ({ name, type, label, value, role });
|
|
1925
2093
|
const text = (value) => value?.trim() || void 0;
|
|
1926
2094
|
const { vehicle, dropOff } = input;
|
|
@@ -1930,7 +2098,7 @@ function formSubmitPayload(input, formSubmit, contractHash) {
|
|
|
1930
2098
|
// E.164 on the wire: it keys the customer and enhanced-conversion matching.
|
|
1931
2099
|
field("phone", "phone", "tel", "Phone", toE164(input.phone) ?? input.phone),
|
|
1932
2100
|
field("email", "email", "email", "Email", text(input.email)),
|
|
1933
|
-
field("service", "service", "select", "Service", input.services),
|
|
2101
|
+
field("service", "service", "select", "Service", [...input.services]),
|
|
1934
2102
|
field(
|
|
1935
2103
|
"vehicle",
|
|
1936
2104
|
"vehicle",
|
|
@@ -1955,6 +2123,14 @@ function formSubmitPayload(input, formSubmit, contractHash) {
|
|
|
1955
2123
|
const reported = new Set(entries.map((item) => item.name));
|
|
1956
2124
|
const fields = entries.filter((item) => item.value !== void 0);
|
|
1957
2125
|
const extra = (formSubmit.extraFields ?? []).filter((item) => !reported.has(item.name));
|
|
2126
|
+
const settings = typedClientSettings(formSubmit.tracking);
|
|
2127
|
+
const { violations, hash } = judgeLeadForm(
|
|
2128
|
+
"booking",
|
|
2129
|
+
formSubmit.formId,
|
|
2130
|
+
fields.map((item) => [item.role, item.value]),
|
|
2131
|
+
formSubmit.contracts,
|
|
2132
|
+
{ ...settings, trackingConfig: settings.trackingConfig ?? runtime?.ref }
|
|
2133
|
+
);
|
|
1958
2134
|
return {
|
|
1959
2135
|
form: {
|
|
1960
2136
|
id: formSubmit.formId,
|
|
@@ -1962,7 +2138,8 @@ function formSubmitPayload(input, formSubmit, contractHash) {
|
|
|
1962
2138
|
fields: [...fields, ...extra],
|
|
1963
2139
|
kind: "booking",
|
|
1964
2140
|
contract_version: LEAD_FORM_REGISTRY_VERSION,
|
|
1965
|
-
...
|
|
2141
|
+
...hash ? { contract_hash: hash } : {},
|
|
2142
|
+
...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {}
|
|
1966
2143
|
},
|
|
1967
2144
|
page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
|
|
1968
2145
|
};
|
|
@@ -2061,10 +2238,9 @@ function createSalesBookingsClient(config, firing) {
|
|
|
2061
2238
|
}
|
|
2062
2239
|
if (formSubmit && !submittedForms.has(attemptKey)) {
|
|
2063
2240
|
submittedForms.add(attemptKey);
|
|
2064
|
-
const contract = runtime?.leadForms()?.contracts.find((c) => c.form_kind === "booking");
|
|
2065
2241
|
formSubmit.tracking.trackEvent(
|
|
2066
2242
|
"form_submit",
|
|
2067
|
-
formSubmitPayload(input, formSubmit,
|
|
2243
|
+
formSubmitPayload(input, formSubmit, runtime)
|
|
2068
2244
|
);
|
|
2069
2245
|
}
|
|
2070
2246
|
const body = {
|
|
@@ -2080,7 +2256,7 @@ function createSalesBookingsClient(config, firing) {
|
|
|
2080
2256
|
email: input.email?.trim() || null,
|
|
2081
2257
|
vehicle: input.vehicle ?? null,
|
|
2082
2258
|
drop_off: input.dropOff ?? null,
|
|
2083
|
-
services: input.services,
|
|
2259
|
+
services: [...input.services],
|
|
2084
2260
|
notes: input.notes?.trim() || null,
|
|
2085
2261
|
marketing_sms_consent: input.marketingSmsConsent === true,
|
|
2086
2262
|
page_path: typeof window === "undefined" ? null : window.location.pathname
|
|
@@ -2167,7 +2343,7 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
|
|
|
2167
2343
|
}
|
|
2168
2344
|
function createSalesClient(config) {
|
|
2169
2345
|
if (config.firing) registerCapability("conversion_goals_manual");
|
|
2170
|
-
async function
|
|
2346
|
+
async function record4(input) {
|
|
2171
2347
|
const currency = input.currency ?? config.defaultCurrency;
|
|
2172
2348
|
if (!currency) {
|
|
2173
2349
|
throw new Error(
|
|
@@ -2193,9 +2369,9 @@ function createSalesClient(config) {
|
|
|
2193
2369
|
return sale;
|
|
2194
2370
|
}
|
|
2195
2371
|
return {
|
|
2196
|
-
record:
|
|
2372
|
+
record: record4,
|
|
2197
2373
|
// recordSale is the intent-revealing alias — same behavior, clearer call site.
|
|
2198
|
-
recordSale:
|
|
2374
|
+
recordSale: record4,
|
|
2199
2375
|
trackConversion(key, options) {
|
|
2200
2376
|
if (config.firing && "fireConversion" in config.firing) {
|
|
2201
2377
|
if (options?.userData && getConsentState() !== "denied") stashUserData(options.userData);
|
|
@@ -2315,17 +2491,17 @@ function createSalesClient(config) {
|
|
|
2315
2491
|
}
|
|
2316
2492
|
|
|
2317
2493
|
// ../tracking-core/src/resources/sales/schema.ts
|
|
2318
|
-
import * as
|
|
2494
|
+
import * as z5 from "zod/mini";
|
|
2319
2495
|
|
|
2320
2496
|
// ../tracking-core/src/resources/sales/generated/zod.gen.ts
|
|
2321
|
-
import * as
|
|
2322
|
-
var zAutoLeapSaleFacts =
|
|
2323
|
-
first_order:
|
|
2324
|
-
fleet_customer:
|
|
2325
|
-
invoice_code:
|
|
2326
|
-
invoice_id:
|
|
2497
|
+
import * as z4 from "zod/mini";
|
|
2498
|
+
var zAutoLeapSaleFacts = z4.object({
|
|
2499
|
+
first_order: z4.boolean(),
|
|
2500
|
+
fleet_customer: z4.boolean(),
|
|
2501
|
+
invoice_code: z4.string(),
|
|
2502
|
+
invoice_id: z4.string()
|
|
2327
2503
|
});
|
|
2328
|
-
var zErrorCode =
|
|
2504
|
+
var zErrorCode = z4.enum([
|
|
2329
2505
|
"missing_credentials",
|
|
2330
2506
|
"invalid_api_key",
|
|
2331
2507
|
"not_authenticated",
|
|
@@ -2369,37 +2545,37 @@ var zErrorCode = z3.enum([
|
|
|
2369
2545
|
"rate_limited",
|
|
2370
2546
|
"internal_error"
|
|
2371
2547
|
]);
|
|
2372
|
-
var zSaleItemEntitySchema =
|
|
2373
|
-
category:
|
|
2374
|
-
external_item_id:
|
|
2375
|
-
id:
|
|
2376
|
-
name:
|
|
2377
|
-
quantity:
|
|
2378
|
-
unit_cost_cents:
|
|
2379
|
-
unit_price_cents:
|
|
2548
|
+
var zSaleItemEntitySchema = z4.object({
|
|
2549
|
+
category: z4.nullable(z4.string()),
|
|
2550
|
+
external_item_id: z4.nullable(z4.string()),
|
|
2551
|
+
id: z4.uuid(),
|
|
2552
|
+
name: z4.nullable(z4.string()),
|
|
2553
|
+
quantity: z4.string().check(z4.regex(/^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$/)),
|
|
2554
|
+
unit_cost_cents: z4.nullable(z4.int()),
|
|
2555
|
+
unit_price_cents: z4.int()
|
|
2380
2556
|
});
|
|
2381
|
-
var zSaleItemInputSchema =
|
|
2382
|
-
category:
|
|
2383
|
-
external_item_id:
|
|
2384
|
-
name:
|
|
2385
|
-
quantity:
|
|
2386
|
-
unit_cost_cents:
|
|
2387
|
-
unit_price_cents:
|
|
2557
|
+
var zSaleItemInputSchema = z4.strictObject({
|
|
2558
|
+
category: z4.nullish(z4.string()),
|
|
2559
|
+
external_item_id: z4.nullish(z4.string()),
|
|
2560
|
+
name: z4.nullish(z4.string()),
|
|
2561
|
+
quantity: z4.string().check(z4.regex(/^\d+(\.\d{1,3})?$/)),
|
|
2562
|
+
unit_cost_cents: z4.nullish(z4.int().check(z4.gte(0))),
|
|
2563
|
+
unit_price_cents: z4.int().check(z4.gte(0))
|
|
2388
2564
|
});
|
|
2389
|
-
var zSaleServiceEntitySchema =
|
|
2390
|
-
amount_cents:
|
|
2391
|
-
id:
|
|
2392
|
-
mapped:
|
|
2393
|
-
service_id:
|
|
2394
|
-
service_key:
|
|
2395
|
-
service_label:
|
|
2565
|
+
var zSaleServiceEntitySchema = z4.object({
|
|
2566
|
+
amount_cents: z4.int(),
|
|
2567
|
+
id: z4.uuid(),
|
|
2568
|
+
mapped: z4.nullable(z4.boolean()),
|
|
2569
|
+
service_id: z4.uuid(),
|
|
2570
|
+
service_key: z4.string(),
|
|
2571
|
+
service_label: z4.string()
|
|
2396
2572
|
});
|
|
2397
|
-
var zSaleServiceInputSchema =
|
|
2398
|
-
amount_cents:
|
|
2399
|
-
service:
|
|
2573
|
+
var zSaleServiceInputSchema = z4.strictObject({
|
|
2574
|
+
amount_cents: z4.int().check(z4.gte(0)),
|
|
2575
|
+
service: z4.string()
|
|
2400
2576
|
});
|
|
2401
|
-
var zSaleSource =
|
|
2402
|
-
var zSmsAutomationState =
|
|
2577
|
+
var zSaleSource = z4.enum(["api", "admin", "autoleap"]);
|
|
2578
|
+
var zSmsAutomationState = z4.enum([
|
|
2403
2579
|
"needs_check",
|
|
2404
2580
|
"failed",
|
|
2405
2581
|
"undelivered",
|
|
@@ -2411,7 +2587,7 @@ var zSmsAutomationState = z3.enum([
|
|
|
2411
2587
|
"eligible",
|
|
2412
2588
|
"not_applicable"
|
|
2413
2589
|
]);
|
|
2414
|
-
var zSmsWithheldReason =
|
|
2590
|
+
var zSmsWithheldReason = z4.enum([
|
|
2415
2591
|
"automation_disabled",
|
|
2416
2592
|
"sms_disabled",
|
|
2417
2593
|
"no_phone",
|
|
@@ -2437,77 +2613,80 @@ var zSmsWithheldReason = z3.enum([
|
|
|
2437
2613
|
"confirmed_by_integration",
|
|
2438
2614
|
"test_or_bot_session",
|
|
2439
2615
|
"invalid_phone",
|
|
2440
|
-
"recently_texted"
|
|
2616
|
+
"recently_texted",
|
|
2617
|
+
"do_not_contact",
|
|
2618
|
+
"do_not_text_tag",
|
|
2619
|
+
"missing_value"
|
|
2441
2620
|
]);
|
|
2442
|
-
var zSaleSmsStatusSchema =
|
|
2443
|
-
can_send_now:
|
|
2444
|
-
last_message_at:
|
|
2445
|
-
reason_detail:
|
|
2621
|
+
var zSaleSmsStatusSchema = z4.object({
|
|
2622
|
+
can_send_now: z4._default(z4.boolean(), false),
|
|
2623
|
+
last_message_at: z4.nullable(z4.iso.datetime({ offset: true })),
|
|
2624
|
+
reason_detail: z4.nullable(z4.string()),
|
|
2446
2625
|
state: zSmsAutomationState,
|
|
2447
|
-
suppressed_by_other_sale:
|
|
2448
|
-
withheld_reason:
|
|
2626
|
+
suppressed_by_other_sale: z4._default(z4.boolean(), false),
|
|
2627
|
+
withheld_reason: z4.nullable(zSmsWithheldReason)
|
|
2449
2628
|
});
|
|
2450
|
-
var zSupportedCurrency =
|
|
2451
|
-
var zTrackingEnvironment =
|
|
2452
|
-
var zSaleCreateSchema =
|
|
2453
|
-
amount_total_cents:
|
|
2629
|
+
var zSupportedCurrency = z4.enum(["USD", "CAD"]);
|
|
2630
|
+
var zTrackingEnvironment = z4.enum(["production", "development"]);
|
|
2631
|
+
var zSaleCreateSchema = z4.strictObject({
|
|
2632
|
+
amount_total_cents: z4.nullish(z4.int().check(z4.gte(0))),
|
|
2454
2633
|
currency: zSupportedCurrency,
|
|
2455
|
-
customer_email:
|
|
2456
|
-
customer_name:
|
|
2457
|
-
customer_phone:
|
|
2458
|
-
description:
|
|
2459
|
-
environment:
|
|
2460
|
-
external_id:
|
|
2461
|
-
items:
|
|
2462
|
-
metadata:
|
|
2463
|
-
occurred_at:
|
|
2464
|
-
service:
|
|
2465
|
-
services:
|
|
2466
|
-
sms_consent:
|
|
2634
|
+
customer_email: z4.nullish(z4.email().check(z4.maxLength(320))),
|
|
2635
|
+
customer_name: z4.nullish(z4.string().check(z4.maxLength(200))),
|
|
2636
|
+
customer_phone: z4.nullish(z4.string().check(z4.maxLength(64))),
|
|
2637
|
+
description: z4.nullish(z4.string()),
|
|
2638
|
+
environment: z4._default(z4.optional(zTrackingEnvironment), "production"),
|
|
2639
|
+
external_id: z4.nullish(z4.string()),
|
|
2640
|
+
items: z4.optional(z4.array(zSaleItemInputSchema)),
|
|
2641
|
+
metadata: z4.nullish(z4.record(z4.string(), z4.unknown())),
|
|
2642
|
+
occurred_at: z4.iso.datetime({ offset: true }),
|
|
2643
|
+
service: z4.nullish(z4.string()),
|
|
2644
|
+
services: z4.nullish(z4.array(zSaleServiceInputSchema)),
|
|
2645
|
+
sms_consent: z4.nullish(z4.boolean())
|
|
2467
2646
|
});
|
|
2468
|
-
var zValidationError =
|
|
2469
|
-
ctx:
|
|
2470
|
-
input:
|
|
2471
|
-
loc:
|
|
2472
|
-
msg:
|
|
2473
|
-
type:
|
|
2647
|
+
var zValidationError = z4.object({
|
|
2648
|
+
ctx: z4.optional(z4.record(z4.string(), z4.unknown())),
|
|
2649
|
+
input: z4.optional(z4.unknown()),
|
|
2650
|
+
loc: z4.array(z4.union([z4.string(), z4.int()])),
|
|
2651
|
+
msg: z4.string(),
|
|
2652
|
+
type: z4.string()
|
|
2474
2653
|
});
|
|
2475
|
-
var zHttpValidationError =
|
|
2476
|
-
detail:
|
|
2654
|
+
var zHttpValidationError = z4.object({
|
|
2655
|
+
detail: z4.optional(z4.array(zValidationError))
|
|
2477
2656
|
});
|
|
2478
|
-
var zValidationErrorItem =
|
|
2479
|
-
loc:
|
|
2480
|
-
msg:
|
|
2481
|
-
type:
|
|
2657
|
+
var zValidationErrorItem = z4.object({
|
|
2658
|
+
loc: z4.array(z4.union([z4.string(), z4.int()])),
|
|
2659
|
+
msg: z4.string(),
|
|
2660
|
+
type: z4.string()
|
|
2482
2661
|
});
|
|
2483
|
-
var zApiErrorSchema =
|
|
2662
|
+
var zApiErrorSchema = z4.object({
|
|
2484
2663
|
code: zErrorCode,
|
|
2485
|
-
context:
|
|
2486
|
-
detail:
|
|
2487
|
-
errors:
|
|
2488
|
-
request_id:
|
|
2664
|
+
context: z4._default(z4.nullish(z4.record(z4.string(), z4.unknown())), null),
|
|
2665
|
+
detail: z4.string(),
|
|
2666
|
+
errors: z4._default(z4.nullish(z4.array(zValidationErrorItem)), null),
|
|
2667
|
+
request_id: z4._default(z4.nullish(z4.string()), null)
|
|
2489
2668
|
});
|
|
2490
|
-
var zWritebackEmailSource =
|
|
2491
|
-
var zWritebackEnrichmentStatus =
|
|
2492
|
-
var zWritebackSaleUploadCounts =
|
|
2493
|
-
failed:
|
|
2494
|
-
pending:
|
|
2495
|
-
skipped:
|
|
2496
|
-
submitted:
|
|
2497
|
-
total:
|
|
2498
|
-
uploaded:
|
|
2669
|
+
var zWritebackEmailSource = z4.enum(["NONE", "SALE", "CUSTOMER", "HARVESTED"]);
|
|
2670
|
+
var zWritebackEnrichmentStatus = z4.enum(["NONE", "MATCHED", "AMBIGUOUS"]);
|
|
2671
|
+
var zWritebackSaleUploadCounts = z4.object({
|
|
2672
|
+
failed: z4._default(z4.int(), 0),
|
|
2673
|
+
pending: z4._default(z4.int(), 0),
|
|
2674
|
+
skipped: z4._default(z4.int(), 0),
|
|
2675
|
+
submitted: z4._default(z4.int(), 0),
|
|
2676
|
+
total: z4._default(z4.int(), 0),
|
|
2677
|
+
uploaded: z4._default(z4.int(), 0)
|
|
2499
2678
|
});
|
|
2500
|
-
var zSaleWritebackStatusSchema =
|
|
2501
|
-
blocked_reason:
|
|
2502
|
-
can_dispatch:
|
|
2503
|
-
email_source:
|
|
2504
|
-
enrichment_status:
|
|
2505
|
-
gclid_attached:
|
|
2506
|
-
identifiers_sent:
|
|
2507
|
-
mapped_service_ids:
|
|
2508
|
-
matched_submit_count:
|
|
2509
|
-
needs_force:
|
|
2510
|
-
rollup:
|
|
2679
|
+
var zSaleWritebackStatusSchema = z4.object({
|
|
2680
|
+
blocked_reason: z4.nullable(z4.string()),
|
|
2681
|
+
can_dispatch: z4._default(z4.boolean(), false),
|
|
2682
|
+
email_source: z4.nullable(zWritebackEmailSource),
|
|
2683
|
+
enrichment_status: z4.nullable(zWritebackEnrichmentStatus),
|
|
2684
|
+
gclid_attached: z4._default(z4.boolean(), false),
|
|
2685
|
+
identifiers_sent: z4.nullable(z4.string()),
|
|
2686
|
+
mapped_service_ids: z4.array(z4.uuid()),
|
|
2687
|
+
matched_submit_count: z4.nullable(z4.int()),
|
|
2688
|
+
needs_force: z4._default(z4.boolean(), false),
|
|
2689
|
+
rollup: z4.enum([
|
|
2511
2690
|
"failed",
|
|
2512
2691
|
"skipped",
|
|
2513
2692
|
"pending",
|
|
@@ -2517,39 +2696,39 @@ var zSaleWritebackStatusSchema = z3.object({
|
|
|
2517
2696
|
"out_of_window",
|
|
2518
2697
|
"blocked"
|
|
2519
2698
|
]),
|
|
2520
|
-
stale:
|
|
2521
|
-
uncovered_service_ids:
|
|
2699
|
+
stale: z4._default(z4.boolean(), false),
|
|
2700
|
+
uncovered_service_ids: z4.array(z4.uuid()),
|
|
2522
2701
|
uploads: zWritebackSaleUploadCounts
|
|
2523
2702
|
});
|
|
2524
|
-
var zSaleEntitySchema =
|
|
2525
|
-
amount_total_cents:
|
|
2526
|
-
business_id:
|
|
2527
|
-
business_name:
|
|
2528
|
-
created_at:
|
|
2529
|
-
currency:
|
|
2530
|
-
customer_email:
|
|
2531
|
-
customer_name:
|
|
2532
|
-
customer_name_placeholder_confirmed:
|
|
2533
|
-
customer_name_placeholder_confirmed_at:
|
|
2534
|
-
customer_phone:
|
|
2535
|
-
description:
|
|
2703
|
+
var zSaleEntitySchema = z4.object({
|
|
2704
|
+
amount_total_cents: z4.int(),
|
|
2705
|
+
business_id: z4.uuid(),
|
|
2706
|
+
business_name: z4.nullable(z4.string()),
|
|
2707
|
+
created_at: z4.iso.datetime({ offset: true }),
|
|
2708
|
+
currency: z4.string(),
|
|
2709
|
+
customer_email: z4.nullable(z4.string()),
|
|
2710
|
+
customer_name: z4.nullable(z4.string()),
|
|
2711
|
+
customer_name_placeholder_confirmed: z4._default(z4.boolean(), false),
|
|
2712
|
+
customer_name_placeholder_confirmed_at: z4.nullable(z4.iso.datetime({ offset: true })),
|
|
2713
|
+
customer_phone: z4.nullable(z4.string()),
|
|
2714
|
+
description: z4.nullable(z4.string()),
|
|
2536
2715
|
environment: zTrackingEnvironment,
|
|
2537
|
-
external_id:
|
|
2538
|
-
id:
|
|
2539
|
-
items:
|
|
2540
|
-
metadata:
|
|
2541
|
-
occurred_at:
|
|
2542
|
-
service_id:
|
|
2543
|
-
service_key:
|
|
2544
|
-
service_label:
|
|
2545
|
-
services:
|
|
2546
|
-
sms_automation:
|
|
2547
|
-
sms_consent:
|
|
2548
|
-
sms_consent_granted_at:
|
|
2716
|
+
external_id: z4.nullable(z4.string()),
|
|
2717
|
+
id: z4.uuid(),
|
|
2718
|
+
items: z4.array(zSaleItemEntitySchema),
|
|
2719
|
+
metadata: z4.nullable(z4.record(z4.string(), z4.unknown())),
|
|
2720
|
+
occurred_at: z4.iso.datetime({ offset: true }),
|
|
2721
|
+
service_id: z4.nullable(z4.uuid()),
|
|
2722
|
+
service_key: z4.nullable(z4.string()),
|
|
2723
|
+
service_label: z4.nullable(z4.string()),
|
|
2724
|
+
services: z4.array(zSaleServiceEntitySchema),
|
|
2725
|
+
sms_automation: z4.nullable(zSaleSmsStatusSchema),
|
|
2726
|
+
sms_consent: z4._default(z4.boolean(), false),
|
|
2727
|
+
sms_consent_granted_at: z4.nullable(z4.iso.datetime({ offset: true })),
|
|
2549
2728
|
source: zSaleSource,
|
|
2550
|
-
source_facts:
|
|
2551
|
-
updated_at:
|
|
2552
|
-
writeback:
|
|
2729
|
+
source_facts: z4.nullable(zAutoLeapSaleFacts),
|
|
2730
|
+
updated_at: z4.iso.datetime({ offset: true }),
|
|
2731
|
+
writeback: z4.nullable(zSaleWritebackStatusSchema)
|
|
2553
2732
|
});
|
|
2554
2733
|
|
|
2555
2734
|
// ../tracking-core/src/resources/sales/schema.ts
|
|
@@ -2558,11 +2737,11 @@ var saleServiceSchema = zSaleServiceInputSchema;
|
|
|
2558
2737
|
var currencySchema = zSupportedCurrency;
|
|
2559
2738
|
var SUPPORTED_CURRENCIES = currencySchema.options;
|
|
2560
2739
|
var SALE_SOURCES = zSaleSource.options;
|
|
2561
|
-
var centsSchema =
|
|
2562
|
-
var metadataSchema =
|
|
2563
|
-
var customerNameSchema =
|
|
2564
|
-
var customerPhoneSchema =
|
|
2565
|
-
var customerEmailSchema =
|
|
2740
|
+
var centsSchema = z5.int().check(z5.gte(0));
|
|
2741
|
+
var metadataSchema = z5.record(z5.string(), z5.unknown());
|
|
2742
|
+
var customerNameSchema = z5.string().check(z5.maxLength(200));
|
|
2743
|
+
var customerPhoneSchema = z5.string().check(z5.maxLength(64));
|
|
2744
|
+
var customerEmailSchema = z5.email().check(z5.maxLength(320));
|
|
2566
2745
|
function addIssue(ctx, path, message) {
|
|
2567
2746
|
ctx.issues.push({ code: "custom", input: ctx.value, path, message });
|
|
2568
2747
|
}
|
|
@@ -2596,24 +2775,24 @@ function refineServiceXor(val, ctx, { requireAmount }) {
|
|
|
2596
2775
|
);
|
|
2597
2776
|
}
|
|
2598
2777
|
}
|
|
2599
|
-
var saleCreateSchema =
|
|
2600
|
-
var saleUpdateSchema =
|
|
2601
|
-
description:
|
|
2602
|
-
service:
|
|
2603
|
-
services:
|
|
2604
|
-
currency:
|
|
2605
|
-
amount_total_cents:
|
|
2606
|
-
occurred_at:
|
|
2607
|
-
items:
|
|
2608
|
-
metadata:
|
|
2609
|
-
customer_name:
|
|
2778
|
+
var saleCreateSchema = z5.extend(zSaleCreateSchema, { items: z5._default(z5.array(saleItemSchema), []) }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: true }));
|
|
2779
|
+
var saleUpdateSchema = z5.strictObject({
|
|
2780
|
+
description: z5.nullish(z5.string()),
|
|
2781
|
+
service: z5.nullish(z5.string()),
|
|
2782
|
+
services: z5.nullish(z5.array(saleServiceSchema)),
|
|
2783
|
+
currency: z5.optional(currencySchema),
|
|
2784
|
+
amount_total_cents: z5.optional(centsSchema),
|
|
2785
|
+
occurred_at: z5.optional(z5.iso.datetime()),
|
|
2786
|
+
items: z5.optional(z5.array(saleItemSchema)),
|
|
2787
|
+
metadata: z5.nullish(metadataSchema),
|
|
2788
|
+
customer_name: z5.nullish(customerNameSchema),
|
|
2610
2789
|
// Re-attest when changing a filler-looking name; the server clears the
|
|
2611
2790
|
// prior attestation whenever `customer_name` changes.
|
|
2612
|
-
customer_name_placeholder_confirmed:
|
|
2613
|
-
customer_phone:
|
|
2614
|
-
customer_email:
|
|
2791
|
+
customer_name_placeholder_confirmed: z5.optional(z5.boolean()),
|
|
2792
|
+
customer_phone: z5.nullish(customerPhoneSchema),
|
|
2793
|
+
customer_email: z5.nullish(customerEmailSchema),
|
|
2615
2794
|
// NOT NULL server-side: omit to leave unchanged (explicit null is rejected).
|
|
2616
|
-
sms_consent:
|
|
2795
|
+
sms_consent: z5.optional(z5.boolean())
|
|
2617
2796
|
}).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: false }));
|
|
2618
2797
|
var TRACKING_RANGES = ["24h", "7d", "30d"];
|
|
2619
2798
|
var NAMED_RANGES = [
|
|
@@ -2640,23 +2819,6 @@ function phoneField(name, raw, country, label = null) {
|
|
|
2640
2819
|
return { name, type: "phone", label, value: toE164(raw, country) };
|
|
2641
2820
|
}
|
|
2642
2821
|
|
|
2643
|
-
// ../tracking-core/src/lead-forms/submit.ts
|
|
2644
|
-
import { safeParse } from "zod/mini";
|
|
2645
|
-
var KNOWN_ROLES = new Set(LEAD_FORM_ROLES);
|
|
2646
|
-
var ROLE_ORDER = new Map(LEAD_FORM_ROLES.map((role, index) => [role, index]));
|
|
2647
|
-
function slotFields(dateTime) {
|
|
2648
|
-
const written = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(dateTime);
|
|
2649
|
-
if (!written) {
|
|
2650
|
-
throw new TypeError(
|
|
2651
|
-
`slotFields needs the slot's wall time without an offset ("2026-10-13T09:30"), got "${dateTime}"`
|
|
2652
|
-
);
|
|
2653
|
-
}
|
|
2654
|
-
return { preferred_date: written[1], preferred_time: { start: written[2], end: null } };
|
|
2655
|
-
}
|
|
2656
|
-
function timeWindow(start, end, label) {
|
|
2657
|
-
return { start, end: end ?? null, ...label ? { label } : {} };
|
|
2658
|
-
}
|
|
2659
|
-
|
|
2660
2822
|
// src/index.ts
|
|
2661
2823
|
import {
|
|
2662
2824
|
PhoneField,
|