@aranova/tracking-react 1.3.0 → 1.4.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/README.md +7 -0
- package/dist/{bookings-VsQdopTt.d.mts → bookings-CqCuuyP6.d.mts} +26 -5
- package/dist/{bookings-CqdjLMkv.d.ts → bookings-DIu1ho6v.d.ts} +26 -5
- package/dist/client.d.mts +4 -2
- package/dist/client.d.ts +4 -2
- package/dist/client.js +12 -6
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +12 -6
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +58 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +58 -16
- package/dist/index.mjs.map +1 -1
- package/dist/{ingest-typed-DGqzbteM.d.ts → ingest-typed-D2S3Kb8m.d.ts} +6 -1
- package/dist/{ingest-typed-BCUv93ax.d.mts → ingest-typed-D7UZr0EM.d.mts} +6 -1
- package/dist/{sales-DSL6vMuY.d.mts → sales-CxJVthx_.d.mts} +1 -1
- package/dist/{sales-_F3nnI2r.d.ts → sales-hlcVTJSS.d.ts} +1 -1
- package/dist/sales.d.mts +2 -2
- package/dist/sales.d.ts +2 -2
- package/dist/sales.js +101 -50
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +101 -50
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -666,6 +666,10 @@ function fireConversionWithConsent(input, options) {
|
|
|
666
666
|
}
|
|
667
667
|
|
|
668
668
|
// ../tracking-core/src/resources/conversion-config.ts
|
|
669
|
+
var BOOKING_MODES = ["live", "test", "simulated"];
|
|
670
|
+
function isBookingMode(value) {
|
|
671
|
+
return BOOKING_MODES.includes(value);
|
|
672
|
+
}
|
|
669
673
|
function isStringMap(value) {
|
|
670
674
|
return typeof value === "object" && value !== null && Object.values(value).every((v) => typeof v === "string");
|
|
671
675
|
}
|
|
@@ -737,7 +741,8 @@ function parseIntegrations(value) {
|
|
|
737
741
|
config_version: typeof b.config_version === "number" ? b.config_version : null,
|
|
738
742
|
accepts_bookings: b.accepts_bookings === true,
|
|
739
743
|
rules: parseBookingRules(b.rules),
|
|
740
|
-
options: Array.isArray(b.options) ? b.options.flatMap(parseBookingOption) : []
|
|
744
|
+
options: Array.isArray(b.options) ? b.options.flatMap(parseBookingOption) : [],
|
|
745
|
+
...isBookingMode(b.mode) ? { mode: b.mode } : {}
|
|
741
746
|
}
|
|
742
747
|
}
|
|
743
748
|
};
|
|
@@ -1444,7 +1449,8 @@ function getBookingIntegration(integrations) {
|
|
|
1444
1449
|
timezone: booking.timezone,
|
|
1445
1450
|
configVersion: booking.config_version,
|
|
1446
1451
|
rules,
|
|
1447
|
-
options: booking.options.map((option) => ({ key: option.key, label: option.label }))
|
|
1452
|
+
options: booking.options.map((option) => ({ key: option.key, label: option.label })),
|
|
1453
|
+
mode: booking.mode ?? "live"
|
|
1448
1454
|
};
|
|
1449
1455
|
}
|
|
1450
1456
|
function camelRules(rules) {
|
|
@@ -1685,6 +1691,7 @@ async function apiRequest(config, method, path, body, extraHeaders) {
|
|
|
1685
1691
|
var salesRequest = apiRequest;
|
|
1686
1692
|
|
|
1687
1693
|
// ../tracking-core/src/resources/sales/bookings.ts
|
|
1694
|
+
var BOOKING_SIMULATE_HEADER = "X-Aranova-Simulate";
|
|
1688
1695
|
var BOOKING_ERROR_CODES = {
|
|
1689
1696
|
unavailable: "booking_unavailable",
|
|
1690
1697
|
stale: "booking_config_stale",
|
|
@@ -1699,10 +1706,11 @@ function sleep(ms) {
|
|
|
1699
1706
|
});
|
|
1700
1707
|
}
|
|
1701
1708
|
function outcomeOf(body) {
|
|
1709
|
+
const mode = body.mode ?? "live";
|
|
1702
1710
|
if (body.status === "created")
|
|
1703
|
-
return { status: "created", id: body.id, requestCode: body.request_code };
|
|
1704
|
-
if (body.status === "pending") return { status: "pending", id: body.id };
|
|
1705
|
-
return { status: "failed", id: body.id, fallbackUrl: body.fallback_url };
|
|
1711
|
+
return { status: "created", id: body.id, requestCode: body.request_code, mode };
|
|
1712
|
+
if (body.status === "pending") return { status: "pending", id: body.id, mode };
|
|
1713
|
+
return { status: "failed", id: body.id, fallbackUrl: body.fallback_url, mode };
|
|
1706
1714
|
}
|
|
1707
1715
|
function formSubmitPayload(input, formId, labels) {
|
|
1708
1716
|
const vehicle = input.vehicle ? `${input.vehicle.year} ${input.vehicle.make} ${input.vehicle.model}` : "";
|
|
@@ -1744,9 +1752,29 @@ function formSubmitPayload(input, formId, labels) {
|
|
|
1744
1752
|
function runtimeOf(firing) {
|
|
1745
1753
|
return firing && "integrations" in firing ? firing : null;
|
|
1746
1754
|
}
|
|
1755
|
+
function isLocalUrl(url) {
|
|
1756
|
+
try {
|
|
1757
|
+
return ["localhost", "127.0.0.1", "[::1]"].includes(new URL(url).hostname);
|
|
1758
|
+
} catch {
|
|
1759
|
+
return false;
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
function bookingSetupMismatch(endpoint, runtime) {
|
|
1763
|
+
if (!runtime || !isLocalUrl(endpoint)) return null;
|
|
1764
|
+
const configUrl = resolveTrackingConfigUrl(runtime.ref);
|
|
1765
|
+
if (isLocalUrl(configUrl)) return null;
|
|
1766
|
+
return `[aranova] Bookings go to the local API (${endpoint}) but the runtime config comes from ${configUrl}. Set NEXT_PUBLIC_ARANOVA_CDN_BASE_URL to the local bucket (http://localhost:9100/aranova-demos) so both come from one backend.`;
|
|
1767
|
+
}
|
|
1747
1768
|
function createSalesBookingsClient(config, firing) {
|
|
1748
1769
|
const submittedForms = /* @__PURE__ */ new Set();
|
|
1749
1770
|
const staleAttempts = /* @__PURE__ */ new Set();
|
|
1771
|
+
let isSetupChecked = false;
|
|
1772
|
+
function warnOnSetupMismatch(runtime) {
|
|
1773
|
+
if (isSetupChecked) return;
|
|
1774
|
+
isSetupChecked = true;
|
|
1775
|
+
const warning = bookingSetupMismatch(config.endpoint, runtime);
|
|
1776
|
+
if (warning) console.warn(warning);
|
|
1777
|
+
}
|
|
1750
1778
|
function handoff(input) {
|
|
1751
1779
|
const booking = getBookingIntegration(runtimeOf(firing)?.integrations());
|
|
1752
1780
|
if (!booking) return null;
|
|
@@ -1757,14 +1785,18 @@ function createSalesBookingsClient(config, firing) {
|
|
|
1757
1785
|
email: input.email
|
|
1758
1786
|
});
|
|
1759
1787
|
}
|
|
1788
|
+
function failedBeforeSend(input) {
|
|
1789
|
+
const mode = getBookingIntegration(runtimeOf(firing)?.integrations())?.mode ?? "live";
|
|
1790
|
+
return { status: "failed", id: null, fallbackUrl: handoff(input), mode };
|
|
1791
|
+
}
|
|
1760
1792
|
function withHandoff(outcome, input) {
|
|
1761
1793
|
if (outcome.status === "failed" && !outcome.fallbackUrl) {
|
|
1762
1794
|
return { ...outcome, fallbackUrl: handoff(input) };
|
|
1763
1795
|
}
|
|
1764
1796
|
return outcome;
|
|
1765
1797
|
}
|
|
1766
|
-
async function poll(id) {
|
|
1767
|
-
let outcome = { status: "pending", id };
|
|
1798
|
+
async function poll(id, mode) {
|
|
1799
|
+
let outcome = { status: "pending", id, mode };
|
|
1768
1800
|
for (const delay of POLL_DELAYS_MS) {
|
|
1769
1801
|
await sleep(delay);
|
|
1770
1802
|
try {
|
|
@@ -1779,12 +1811,10 @@ function createSalesBookingsClient(config, firing) {
|
|
|
1779
1811
|
}
|
|
1780
1812
|
async function rejected(error, input, attemptKey, runtime) {
|
|
1781
1813
|
if (!(error instanceof AranovaApiError)) {
|
|
1782
|
-
return
|
|
1814
|
+
return failedBeforeSend(input);
|
|
1783
1815
|
}
|
|
1784
1816
|
if (error.code === BOOKING_ERROR_CODES.stale) {
|
|
1785
|
-
if (staleAttempts.has(attemptKey))
|
|
1786
|
-
return { status: "failed", id: null, fallbackUrl: handoff(input) };
|
|
1787
|
-
}
|
|
1817
|
+
if (staleAttempts.has(attemptKey)) return failedBeforeSend(input);
|
|
1788
1818
|
staleAttempts.add(attemptKey);
|
|
1789
1819
|
await runtime?.revalidate();
|
|
1790
1820
|
return { status: "stale", message: error.message };
|
|
@@ -1800,15 +1830,16 @@ function createSalesBookingsClient(config, firing) {
|
|
|
1800
1830
|
if (error.code === "validation_error") {
|
|
1801
1831
|
return { status: "invalid", message: INVALID_DETAILS, reasons: [] };
|
|
1802
1832
|
}
|
|
1803
|
-
return
|
|
1833
|
+
return failedBeforeSend(input);
|
|
1804
1834
|
}
|
|
1805
1835
|
return {
|
|
1806
|
-
async submit(input, { attemptKey, formSubmit }) {
|
|
1836
|
+
async submit(input, { attemptKey, formSubmit, simulate }) {
|
|
1807
1837
|
registerCapability("booking_integration");
|
|
1808
1838
|
const runtime = runtimeOf(firing);
|
|
1839
|
+
warnOnSetupMismatch(runtime);
|
|
1809
1840
|
const booking = getBookingIntegration(runtime?.integrations());
|
|
1810
1841
|
if (!booking?.acceptsBookings || booking.configVersion === null) {
|
|
1811
|
-
return
|
|
1842
|
+
return failedBeforeSend(input);
|
|
1812
1843
|
}
|
|
1813
1844
|
if (formSubmit && !submittedForms.has(attemptKey)) {
|
|
1814
1845
|
submittedForms.add(attemptKey);
|
|
@@ -1838,12 +1869,22 @@ function createSalesBookingsClient(config, firing) {
|
|
|
1838
1869
|
};
|
|
1839
1870
|
let response;
|
|
1840
1871
|
try {
|
|
1841
|
-
|
|
1872
|
+
const headers = simulate ? { [BOOKING_SIMULATE_HEADER]: simulate } : void 0;
|
|
1873
|
+
response = await salesRequest(
|
|
1874
|
+
config,
|
|
1875
|
+
"POST",
|
|
1876
|
+
"/bookings",
|
|
1877
|
+
body,
|
|
1878
|
+
headers
|
|
1879
|
+
);
|
|
1842
1880
|
} catch (error) {
|
|
1843
1881
|
return rejected(error, input, attemptKey, runtime);
|
|
1844
1882
|
}
|
|
1845
1883
|
const outcome = outcomeOf(response);
|
|
1846
|
-
return withHandoff(
|
|
1884
|
+
return withHandoff(
|
|
1885
|
+
outcome.status === "pending" ? await poll(outcome.id, outcome.mode) : outcome,
|
|
1886
|
+
input
|
|
1887
|
+
);
|
|
1847
1888
|
},
|
|
1848
1889
|
async status(id) {
|
|
1849
1890
|
return outcomeOf(
|
|
@@ -2072,6 +2113,7 @@ var zErrorCode = z2.enum([
|
|
|
2072
2113
|
"booking_not_found",
|
|
2073
2114
|
"booking_not_cancellable",
|
|
2074
2115
|
"booking_not_reschedulable",
|
|
2116
|
+
"booking_not_synced",
|
|
2075
2117
|
"manage_token_invalid",
|
|
2076
2118
|
"google_error",
|
|
2077
2119
|
"booking_unavailable",
|