@aranova/tracking-react 1.2.4 → 1.3.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/README.md +70 -0
- package/dist/{tracking-config-runtime-C6H7ofmo.d.mts → bookings-CqdjLMkv.d.ts} +144 -1
- package/dist/{tracking-config-runtime-C6H7ofmo.d.ts → bookings-VsQdopTt.d.mts} +144 -1
- package/dist/client.d.mts +56 -6
- package/dist/client.d.ts +56 -6
- package/dist/client.js +281 -11
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +276 -11
- package/dist/client.mjs.map +1 -1
- package/dist/form-submit-BLb28aCk.d.mts +75 -0
- package/dist/form-submit-BLb28aCk.d.ts +75 -0
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +429 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +424 -4
- package/dist/index.mjs.map +1 -1
- package/dist/{ingest-typed-QKX9WGr3.d.ts → ingest-typed-BCUv93ax.d.mts} +80 -4
- package/dist/{ingest-typed-D1sYF0bA.d.mts → ingest-typed-DGqzbteM.d.ts} +80 -4
- package/dist/{phone-utils-qLfVpQI7.d.mts → phone-utils-CM8eUPz8.d.mts} +2 -74
- package/dist/{phone-utils-qLfVpQI7.d.ts → phone-utils-l8ey3Zdm.d.ts} +2 -74
- package/dist/phone.d.mts +2 -1
- package/dist/phone.d.ts +2 -1
- package/dist/{sales-C3O_xxZ_.d.ts → sales-DSL6vMuY.d.mts} +23 -2
- package/dist/{sales-BuKD_bdo.d.mts → sales-_F3nnI2r.d.ts} +23 -2
- package/dist/sales.d.mts +3 -2
- package/dist/sales.d.ts +3 -2
- package/dist/sales.js +307 -9
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +305 -9
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
package/dist/sales.js
CHANGED
|
@@ -32,6 +32,7 @@ var sales_exports = {};
|
|
|
32
32
|
__export(sales_exports, {
|
|
33
33
|
AranovaApiError: () => AranovaApiError,
|
|
34
34
|
NAMED_RANGES: () => NAMED_RANGES,
|
|
35
|
+
SALE_SOURCES: () => SALE_SOURCES,
|
|
35
36
|
SUPPORTED_CURRENCIES: () => SUPPORTED_CURRENCIES,
|
|
36
37
|
TRACKING_RANGES: () => TRACKING_RANGES,
|
|
37
38
|
createSalesClient: () => createSalesClient,
|
|
@@ -40,6 +41,7 @@ __export(sales_exports, {
|
|
|
40
41
|
formatDateInTz: () => formatDateInTz,
|
|
41
42
|
formatMoney: () => formatMoney,
|
|
42
43
|
fromMinor: () => fromMinor,
|
|
44
|
+
newBookingAttemptKey: () => newBookingAttemptKey,
|
|
43
45
|
saleCreateSchema: () => saleCreateSchema,
|
|
44
46
|
saleItemSchema: () => saleItemSchema,
|
|
45
47
|
saleServiceSchema: () => saleServiceSchema,
|
|
@@ -221,12 +223,105 @@ function fireConversionWithConsent(input, options) {
|
|
|
221
223
|
}
|
|
222
224
|
}
|
|
223
225
|
|
|
224
|
-
//
|
|
225
|
-
var
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
226
|
+
// ../../contracts/autoleap-booking-links.json
|
|
227
|
+
var autoleap_booking_links_default = {
|
|
228
|
+
hosts: ["myalp.io"]
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// ../tracking-core/src/integrations-public.ts
|
|
232
|
+
var HANDOFF_HOSTS = new Set(autoleap_booking_links_default.hosts);
|
|
233
|
+
function getBookingIntegration(integrations) {
|
|
234
|
+
const booking = integrations?.autoleap?.booking;
|
|
235
|
+
if (!booking) return null;
|
|
236
|
+
const rules = booking.rules ? camelRules(booking.rules) : null;
|
|
237
|
+
return {
|
|
238
|
+
provider: "autoleap",
|
|
239
|
+
enabled: booking.enabled,
|
|
240
|
+
fallbackUrl: booking.fallback_url,
|
|
241
|
+
acceptsBookings: booking.accepts_bookings && rules !== null && booking.config_version !== null,
|
|
242
|
+
timezone: booking.timezone,
|
|
243
|
+
configVersion: booking.config_version,
|
|
244
|
+
rules,
|
|
245
|
+
options: booking.options.map((option) => ({ key: option.key, label: option.label }))
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function camelRules(rules) {
|
|
249
|
+
return {
|
|
250
|
+
minDaysAhead: rules.min_days_ahead,
|
|
251
|
+
maxDaysAhead: rules.max_days_ahead,
|
|
252
|
+
hours: rules.hours,
|
|
253
|
+
closedDates: rules.closed_dates,
|
|
254
|
+
specialHours: rules.special_hours,
|
|
255
|
+
vehicleRequired: rules.vehicle_required,
|
|
256
|
+
dropOffOptions: rules.drop_off_options
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function buildBookingHandoffUrl(fallbackUrl, prefill = {}) {
|
|
260
|
+
let url;
|
|
261
|
+
try {
|
|
262
|
+
url = new URL(fallbackUrl);
|
|
263
|
+
} catch {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
if (url.protocol !== "https:" || !HANDOFF_HOSTS.has(url.hostname) || url.username || url.password || url.port) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
const [firstName, lastName] = prefill.firstName?.trim() ? [prefill.firstName, prefill.lastName] : splitFullName(prefill.name);
|
|
270
|
+
const values = [
|
|
271
|
+
["firstName", firstName?.trim()],
|
|
272
|
+
["lastName", lastName?.trim()],
|
|
273
|
+
["phone", prefill.phone ? nationalDigits(prefill.phone) : ""],
|
|
274
|
+
["email", prefill.email?.trim()]
|
|
275
|
+
];
|
|
276
|
+
for (const [key, value] of values) {
|
|
277
|
+
if (value) url.searchParams.set(key, value);
|
|
278
|
+
}
|
|
279
|
+
return url.toString();
|
|
280
|
+
}
|
|
281
|
+
function splitFullName(name) {
|
|
282
|
+
const [first = "", ...rest] = (name ?? "").trim().split(/\s+/);
|
|
283
|
+
return [first, rest.join(" ")];
|
|
284
|
+
}
|
|
285
|
+
function nationalDigits(phone) {
|
|
286
|
+
const parsed = parsePhone(phone);
|
|
287
|
+
return (parsed.isValid ? parsed.national : phone).replace(/\D/g, "");
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ../tracking-core/src/uuid.ts
|
|
291
|
+
function uuidV4() {
|
|
292
|
+
const cryptoApi = globalThis.crypto;
|
|
293
|
+
if (typeof cryptoApi?.randomUUID === "function") return cryptoApi.randomUUID();
|
|
294
|
+
const bytes = new Uint8Array(16);
|
|
295
|
+
if (typeof cryptoApi?.getRandomValues === "function") cryptoApi.getRandomValues(bytes);
|
|
296
|
+
else for (let i = 0; i < 16; i += 1) bytes[i] = Math.floor(Math.random() * 256);
|
|
297
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
298
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
299
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
300
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ../tracking-core/src/session.ts
|
|
304
|
+
var SESSION_STORAGE_KEY = "aranova_tracking_session";
|
|
305
|
+
var SESSION_IDLE_MS = 30 * 60 * 1e3;
|
|
306
|
+
function readLocalStorage(key) {
|
|
307
|
+
try {
|
|
308
|
+
return window.localStorage.getItem(key);
|
|
309
|
+
} catch {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function peekSessionId(now = Date.now()) {
|
|
314
|
+
if (typeof window === "undefined") return null;
|
|
315
|
+
const raw = readLocalStorage(SESSION_STORAGE_KEY);
|
|
316
|
+
if (!raw) return null;
|
|
317
|
+
try {
|
|
318
|
+
const parsed = JSON.parse(raw);
|
|
319
|
+
if (typeof parsed.id !== "string" || typeof parsed.last_event_at !== "number") return null;
|
|
320
|
+
return now - parsed.last_event_at <= SESSION_IDLE_MS ? parsed.id : null;
|
|
321
|
+
} catch {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
230
325
|
|
|
231
326
|
// ../tracking-core/src/resources/http/errors.ts
|
|
232
327
|
var AranovaApiError = class extends Error {
|
|
@@ -236,9 +331,17 @@ var AranovaApiError = class extends Error {
|
|
|
236
331
|
this.status = options.status;
|
|
237
332
|
this.code = options.code;
|
|
238
333
|
this.requestId = options.requestId;
|
|
334
|
+
this.context = options.context;
|
|
239
335
|
}
|
|
240
336
|
};
|
|
241
337
|
|
|
338
|
+
// ../tracking-core/src/ingest.ts
|
|
339
|
+
var API_KEY_HEADER = "X-Aranova-Api-Key";
|
|
340
|
+
var SDK_VERSION_HEADER = "X-Aranova-Sdk-Version";
|
|
341
|
+
var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
|
|
342
|
+
var SDK_SURFACE_HEADER = "X-Aranova-Sdk-Surface";
|
|
343
|
+
var SDK_ENVIRONMENT_HEADER = "X-Aranova-Sdk-Environment";
|
|
344
|
+
|
|
242
345
|
// ../tracking-core/src/resources/http/request.ts
|
|
243
346
|
function identityHeaders(config) {
|
|
244
347
|
const headers = { [API_KEY_HEADER]: config.apiKey };
|
|
@@ -262,19 +365,24 @@ async function apiRequest(config, method, path, body, extraHeaders) {
|
|
|
262
365
|
if (!response.ok) {
|
|
263
366
|
let detail;
|
|
264
367
|
let code;
|
|
368
|
+
let context;
|
|
265
369
|
try {
|
|
266
370
|
const parsed = await response.json();
|
|
267
371
|
if (parsed && typeof parsed === "object") {
|
|
268
372
|
const record3 = parsed;
|
|
269
373
|
if (typeof record3.detail === "string") detail = record3.detail;
|
|
270
374
|
if (typeof record3.code === "string") code = record3.code;
|
|
375
|
+
if (record3.context && typeof record3.context === "object") {
|
|
376
|
+
context = record3.context;
|
|
377
|
+
}
|
|
271
378
|
}
|
|
272
379
|
} catch {
|
|
273
380
|
}
|
|
274
381
|
throw new AranovaApiError(detail ?? response.statusText ?? "Request failed", {
|
|
275
382
|
status: response.status,
|
|
276
383
|
code,
|
|
277
|
-
requestId: response.headers.get("x-request-id") ?? void 0
|
|
384
|
+
requestId: response.headers.get("x-request-id") ?? void 0,
|
|
385
|
+
context
|
|
278
386
|
});
|
|
279
387
|
}
|
|
280
388
|
if (response.status === 204) return void 0;
|
|
@@ -284,6 +392,179 @@ async function apiRequest(config, method, path, body, extraHeaders) {
|
|
|
284
392
|
// ../tracking-core/src/resources/sales/transport.ts
|
|
285
393
|
var salesRequest = apiRequest;
|
|
286
394
|
|
|
395
|
+
// ../tracking-core/src/resources/sales/bookings.ts
|
|
396
|
+
var BOOKING_ERROR_CODES = {
|
|
397
|
+
unavailable: "booking_unavailable",
|
|
398
|
+
stale: "booking_config_stale",
|
|
399
|
+
rejected: "booking_rejected"
|
|
400
|
+
};
|
|
401
|
+
var POLL_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 15e3];
|
|
402
|
+
var INVALID_DETAILS = "Please check your details and try again.";
|
|
403
|
+
var newBookingAttemptKey = uuidV4;
|
|
404
|
+
function sleep(ms) {
|
|
405
|
+
return new Promise((resolve) => {
|
|
406
|
+
setTimeout(resolve, ms);
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
function outcomeOf(body) {
|
|
410
|
+
if (body.status === "created")
|
|
411
|
+
return { status: "created", id: body.id, requestCode: body.request_code };
|
|
412
|
+
if (body.status === "pending") return { status: "pending", id: body.id };
|
|
413
|
+
return { status: "failed", id: body.id, fallbackUrl: body.fallback_url };
|
|
414
|
+
}
|
|
415
|
+
function formSubmitPayload(input, formId, labels) {
|
|
416
|
+
const vehicle = input.vehicle ? `${input.vehicle.year} ${input.vehicle.make} ${input.vehicle.model}` : "";
|
|
417
|
+
const field = (name, type, label, value) => ({
|
|
418
|
+
name,
|
|
419
|
+
type,
|
|
420
|
+
label,
|
|
421
|
+
value
|
|
422
|
+
});
|
|
423
|
+
return {
|
|
424
|
+
form: {
|
|
425
|
+
id: formId,
|
|
426
|
+
action: "/tracking/bookings",
|
|
427
|
+
fields: [
|
|
428
|
+
field("first_name", "text", "First name", input.firstName),
|
|
429
|
+
field("last_name", "text", "Last name", input.lastName),
|
|
430
|
+
// E.164 on the wire: it keys the customer and enhanced-conversion matching.
|
|
431
|
+
field("phone", "tel", "Phone", toE164(input.phone) ?? input.phone),
|
|
432
|
+
field("email", "email", "Email", input.email ?? ""),
|
|
433
|
+
field(
|
|
434
|
+
"service",
|
|
435
|
+
"select",
|
|
436
|
+
"Service",
|
|
437
|
+
input.services.map((key) => labels.get(key) ?? key).join(", ")
|
|
438
|
+
),
|
|
439
|
+
field("vehicle", "text", "Vehicle", vehicle),
|
|
440
|
+
field(
|
|
441
|
+
"start",
|
|
442
|
+
"text",
|
|
443
|
+
"Requested time",
|
|
444
|
+
`${input.startDate} ${String(input.startHour).padStart(2, "0")}:00`
|
|
445
|
+
),
|
|
446
|
+
field("note", "textarea", "Notes", input.notes ?? "")
|
|
447
|
+
]
|
|
448
|
+
},
|
|
449
|
+
page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function runtimeOf(firing) {
|
|
453
|
+
return firing && "integrations" in firing ? firing : null;
|
|
454
|
+
}
|
|
455
|
+
function createSalesBookingsClient(config, firing) {
|
|
456
|
+
const submittedForms = /* @__PURE__ */ new Set();
|
|
457
|
+
const staleAttempts = /* @__PURE__ */ new Set();
|
|
458
|
+
function handoff(input) {
|
|
459
|
+
const booking = getBookingIntegration(runtimeOf(firing)?.integrations());
|
|
460
|
+
if (!booking) return null;
|
|
461
|
+
return buildBookingHandoffUrl(booking.fallbackUrl, {
|
|
462
|
+
firstName: input.firstName,
|
|
463
|
+
lastName: input.lastName,
|
|
464
|
+
phone: input.phone,
|
|
465
|
+
email: input.email
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
function withHandoff(outcome, input) {
|
|
469
|
+
if (outcome.status === "failed" && !outcome.fallbackUrl) {
|
|
470
|
+
return { ...outcome, fallbackUrl: handoff(input) };
|
|
471
|
+
}
|
|
472
|
+
return outcome;
|
|
473
|
+
}
|
|
474
|
+
async function poll(id) {
|
|
475
|
+
let outcome = { status: "pending", id };
|
|
476
|
+
for (const delay of POLL_DELAYS_MS) {
|
|
477
|
+
await sleep(delay);
|
|
478
|
+
try {
|
|
479
|
+
const path = `/bookings/${encodeURIComponent(id)}`;
|
|
480
|
+
outcome = outcomeOf(await salesRequest(config, "GET", path));
|
|
481
|
+
} catch {
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
if (outcome.status !== "pending") return outcome;
|
|
485
|
+
}
|
|
486
|
+
return outcome;
|
|
487
|
+
}
|
|
488
|
+
async function rejected(error, input, attemptKey, runtime) {
|
|
489
|
+
if (!(error instanceof AranovaApiError)) {
|
|
490
|
+
return { status: "failed", id: null, fallbackUrl: handoff(input) };
|
|
491
|
+
}
|
|
492
|
+
if (error.code === BOOKING_ERROR_CODES.stale) {
|
|
493
|
+
if (staleAttempts.has(attemptKey)) {
|
|
494
|
+
return { status: "failed", id: null, fallbackUrl: handoff(input) };
|
|
495
|
+
}
|
|
496
|
+
staleAttempts.add(attemptKey);
|
|
497
|
+
await runtime?.revalidate();
|
|
498
|
+
return { status: "stale", message: error.message };
|
|
499
|
+
}
|
|
500
|
+
if (error.code === BOOKING_ERROR_CODES.rejected) {
|
|
501
|
+
const reasons = error.context?.reasons;
|
|
502
|
+
return {
|
|
503
|
+
status: "invalid",
|
|
504
|
+
message: error.message,
|
|
505
|
+
reasons: Array.isArray(reasons) ? reasons.map(String) : []
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
if (error.code === "validation_error") {
|
|
509
|
+
return { status: "invalid", message: INVALID_DETAILS, reasons: [] };
|
|
510
|
+
}
|
|
511
|
+
return { status: "failed", id: null, fallbackUrl: handoff(input) };
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
async submit(input, { attemptKey, formSubmit }) {
|
|
515
|
+
registerCapability("booking_integration");
|
|
516
|
+
const runtime = runtimeOf(firing);
|
|
517
|
+
const booking = getBookingIntegration(runtime?.integrations());
|
|
518
|
+
if (!booking?.acceptsBookings || booking.configVersion === null) {
|
|
519
|
+
return { status: "failed", id: null, fallbackUrl: handoff(input) };
|
|
520
|
+
}
|
|
521
|
+
if (formSubmit && !submittedForms.has(attemptKey)) {
|
|
522
|
+
submittedForms.add(attemptKey);
|
|
523
|
+
const labels = new Map(booking.options.map((option) => [option.key, option.label]));
|
|
524
|
+
formSubmit.tracking.trackEvent(
|
|
525
|
+
"form_submit",
|
|
526
|
+
formSubmitPayload(input, formSubmit.formId, labels)
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
const body = {
|
|
530
|
+
idempotency_key: attemptKey,
|
|
531
|
+
// The tracking client's own visit, so the booking and its form_submit share one session.
|
|
532
|
+
session_id: formSubmit?.tracking.getSessionId() ?? peekSessionId() ?? `no-session-${attemptKey}`,
|
|
533
|
+
config_version: booking.configVersion,
|
|
534
|
+
start_date: input.startDate,
|
|
535
|
+
start_hour: input.startHour,
|
|
536
|
+
first_name: input.firstName.trim(),
|
|
537
|
+
last_name: input.lastName.trim(),
|
|
538
|
+
phone: input.phone,
|
|
539
|
+
email: input.email?.trim() || null,
|
|
540
|
+
vehicle: input.vehicle ?? null,
|
|
541
|
+
drop_off: input.dropOff ?? null,
|
|
542
|
+
services: input.services,
|
|
543
|
+
notes: input.notes?.trim() || null,
|
|
544
|
+
marketing_sms_consent: input.marketingSmsConsent === true,
|
|
545
|
+
page_path: typeof window === "undefined" ? null : window.location.pathname
|
|
546
|
+
};
|
|
547
|
+
let response;
|
|
548
|
+
try {
|
|
549
|
+
response = await salesRequest(config, "POST", "/bookings", body);
|
|
550
|
+
} catch (error) {
|
|
551
|
+
return rejected(error, input, attemptKey, runtime);
|
|
552
|
+
}
|
|
553
|
+
const outcome = outcomeOf(response);
|
|
554
|
+
return withHandoff(outcome.status === "pending" ? await poll(outcome.id) : outcome, input);
|
|
555
|
+
},
|
|
556
|
+
async status(id) {
|
|
557
|
+
return outcomeOf(
|
|
558
|
+
await salesRequest(
|
|
559
|
+
config,
|
|
560
|
+
"GET",
|
|
561
|
+
`/bookings/${encodeURIComponent(id)}`
|
|
562
|
+
)
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
|
|
287
568
|
// ../tracking-core/src/resources/intl/date.ts
|
|
288
569
|
function formatDateInTz(iso3, timeZone, opts, locale) {
|
|
289
570
|
const date = new Date(iso3);
|
|
@@ -493,7 +774,8 @@ function createSalesClient(config) {
|
|
|
493
774
|
async config() {
|
|
494
775
|
return salesRequest(config, "GET", "/business/config");
|
|
495
776
|
}
|
|
496
|
-
}
|
|
777
|
+
},
|
|
778
|
+
bookings: createSalesBookingsClient(config, config.firing)
|
|
497
779
|
};
|
|
498
780
|
}
|
|
499
781
|
|
|
@@ -502,6 +784,12 @@ var z2 = __toESM(require("zod/mini"));
|
|
|
502
784
|
|
|
503
785
|
// ../tracking-core/src/resources/sales/generated/zod.gen.ts
|
|
504
786
|
var z = __toESM(require("zod/mini"));
|
|
787
|
+
var zAutoLeapSaleFacts = z.object({
|
|
788
|
+
first_order: z.boolean(),
|
|
789
|
+
fleet_customer: z.boolean(),
|
|
790
|
+
invoice_code: z.string(),
|
|
791
|
+
invoice_id: z.string()
|
|
792
|
+
});
|
|
505
793
|
var zErrorCode = z.enum([
|
|
506
794
|
"missing_credentials",
|
|
507
795
|
"invalid_api_key",
|
|
@@ -529,6 +817,9 @@ var zErrorCode = z.enum([
|
|
|
529
817
|
"booking_not_reschedulable",
|
|
530
818
|
"manage_token_invalid",
|
|
531
819
|
"google_error",
|
|
820
|
+
"booking_unavailable",
|
|
821
|
+
"booking_config_stale",
|
|
822
|
+
"booking_rejected",
|
|
532
823
|
"calendar_not_owned",
|
|
533
824
|
"calendar_is_sandbox",
|
|
534
825
|
"sandbox_exists",
|
|
@@ -570,6 +861,7 @@ var zSaleServiceInputSchema = z.strictObject({
|
|
|
570
861
|
amount_cents: z.int().check(z.gte(0)),
|
|
571
862
|
service: z.string()
|
|
572
863
|
});
|
|
864
|
+
var zSaleSource = z.enum(["api", "admin", "autoleap"]);
|
|
573
865
|
var zSmsAutomationState = z.enum([
|
|
574
866
|
"needs_check",
|
|
575
867
|
"failed",
|
|
@@ -601,7 +893,8 @@ var zSmsWithheldReason = z.enum([
|
|
|
601
893
|
"number_not_active",
|
|
602
894
|
"a2p_registration_required",
|
|
603
895
|
"alert_recipient_cannot_receive_sms",
|
|
604
|
-
"line_type_unresolved"
|
|
896
|
+
"line_type_unresolved",
|
|
897
|
+
"sale_source_sends_own_messages"
|
|
605
898
|
]);
|
|
606
899
|
var zSaleSmsStatusSchema = z.object({
|
|
607
900
|
can_send_now: z._default(z.boolean(), false),
|
|
@@ -710,6 +1003,8 @@ var zSaleEntitySchema = z.object({
|
|
|
710
1003
|
sms_automation: z.nullable(zSaleSmsStatusSchema),
|
|
711
1004
|
sms_consent: z._default(z.boolean(), false),
|
|
712
1005
|
sms_consent_granted_at: z.nullable(z.iso.datetime({ offset: true })),
|
|
1006
|
+
source: zSaleSource,
|
|
1007
|
+
source_facts: z.nullable(zAutoLeapSaleFacts),
|
|
713
1008
|
updated_at: z.iso.datetime({ offset: true }),
|
|
714
1009
|
writeback: z.nullable(zSaleWritebackStatusSchema)
|
|
715
1010
|
});
|
|
@@ -719,6 +1014,7 @@ var saleItemSchema = zSaleItemInputSchema;
|
|
|
719
1014
|
var saleServiceSchema = zSaleServiceInputSchema;
|
|
720
1015
|
var currencySchema = zSupportedCurrency;
|
|
721
1016
|
var SUPPORTED_CURRENCIES = currencySchema.options;
|
|
1017
|
+
var SALE_SOURCES = zSaleSource.options;
|
|
722
1018
|
var centsSchema = z2.int().check(z2.gte(0));
|
|
723
1019
|
var metadataSchema = z2.record(z2.string(), z2.unknown());
|
|
724
1020
|
var customerNameSchema = z2.string().check(z2.maxLength(200));
|
|
@@ -799,6 +1095,7 @@ async function fetchServices(config) {
|
|
|
799
1095
|
0 && (module.exports = {
|
|
800
1096
|
AranovaApiError,
|
|
801
1097
|
NAMED_RANGES,
|
|
1098
|
+
SALE_SOURCES,
|
|
802
1099
|
SUPPORTED_CURRENCIES,
|
|
803
1100
|
TRACKING_RANGES,
|
|
804
1101
|
createSalesClient,
|
|
@@ -807,6 +1104,7 @@ async function fetchServices(config) {
|
|
|
807
1104
|
formatDateInTz,
|
|
808
1105
|
formatMoney,
|
|
809
1106
|
fromMinor,
|
|
1107
|
+
newBookingAttemptKey,
|
|
810
1108
|
saleCreateSchema,
|
|
811
1109
|
saleItemSchema,
|
|
812
1110
|
saleServiceSchema,
|