@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.mjs
CHANGED
|
@@ -170,12 +170,105 @@ function fireConversionWithConsent(input, options) {
|
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
//
|
|
174
|
-
var
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
173
|
+
// ../../contracts/autoleap-booking-links.json
|
|
174
|
+
var autoleap_booking_links_default = {
|
|
175
|
+
hosts: ["myalp.io"]
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// ../tracking-core/src/integrations-public.ts
|
|
179
|
+
var HANDOFF_HOSTS = new Set(autoleap_booking_links_default.hosts);
|
|
180
|
+
function getBookingIntegration(integrations) {
|
|
181
|
+
const booking = integrations?.autoleap?.booking;
|
|
182
|
+
if (!booking) return null;
|
|
183
|
+
const rules = booking.rules ? camelRules(booking.rules) : null;
|
|
184
|
+
return {
|
|
185
|
+
provider: "autoleap",
|
|
186
|
+
enabled: booking.enabled,
|
|
187
|
+
fallbackUrl: booking.fallback_url,
|
|
188
|
+
acceptsBookings: booking.accepts_bookings && rules !== null && booking.config_version !== null,
|
|
189
|
+
timezone: booking.timezone,
|
|
190
|
+
configVersion: booking.config_version,
|
|
191
|
+
rules,
|
|
192
|
+
options: booking.options.map((option) => ({ key: option.key, label: option.label }))
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function camelRules(rules) {
|
|
196
|
+
return {
|
|
197
|
+
minDaysAhead: rules.min_days_ahead,
|
|
198
|
+
maxDaysAhead: rules.max_days_ahead,
|
|
199
|
+
hours: rules.hours,
|
|
200
|
+
closedDates: rules.closed_dates,
|
|
201
|
+
specialHours: rules.special_hours,
|
|
202
|
+
vehicleRequired: rules.vehicle_required,
|
|
203
|
+
dropOffOptions: rules.drop_off_options
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function buildBookingHandoffUrl(fallbackUrl, prefill = {}) {
|
|
207
|
+
let url;
|
|
208
|
+
try {
|
|
209
|
+
url = new URL(fallbackUrl);
|
|
210
|
+
} catch {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
if (url.protocol !== "https:" || !HANDOFF_HOSTS.has(url.hostname) || url.username || url.password || url.port) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
const [firstName, lastName] = prefill.firstName?.trim() ? [prefill.firstName, prefill.lastName] : splitFullName(prefill.name);
|
|
217
|
+
const values = [
|
|
218
|
+
["firstName", firstName?.trim()],
|
|
219
|
+
["lastName", lastName?.trim()],
|
|
220
|
+
["phone", prefill.phone ? nationalDigits(prefill.phone) : ""],
|
|
221
|
+
["email", prefill.email?.trim()]
|
|
222
|
+
];
|
|
223
|
+
for (const [key, value] of values) {
|
|
224
|
+
if (value) url.searchParams.set(key, value);
|
|
225
|
+
}
|
|
226
|
+
return url.toString();
|
|
227
|
+
}
|
|
228
|
+
function splitFullName(name) {
|
|
229
|
+
const [first = "", ...rest] = (name ?? "").trim().split(/\s+/);
|
|
230
|
+
return [first, rest.join(" ")];
|
|
231
|
+
}
|
|
232
|
+
function nationalDigits(phone) {
|
|
233
|
+
const parsed = parsePhone(phone);
|
|
234
|
+
return (parsed.isValid ? parsed.national : phone).replace(/\D/g, "");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ../tracking-core/src/uuid.ts
|
|
238
|
+
function uuidV4() {
|
|
239
|
+
const cryptoApi = globalThis.crypto;
|
|
240
|
+
if (typeof cryptoApi?.randomUUID === "function") return cryptoApi.randomUUID();
|
|
241
|
+
const bytes = new Uint8Array(16);
|
|
242
|
+
if (typeof cryptoApi?.getRandomValues === "function") cryptoApi.getRandomValues(bytes);
|
|
243
|
+
else for (let i = 0; i < 16; i += 1) bytes[i] = Math.floor(Math.random() * 256);
|
|
244
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
245
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
246
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
247
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ../tracking-core/src/session.ts
|
|
251
|
+
var SESSION_STORAGE_KEY = "aranova_tracking_session";
|
|
252
|
+
var SESSION_IDLE_MS = 30 * 60 * 1e3;
|
|
253
|
+
function readLocalStorage(key) {
|
|
254
|
+
try {
|
|
255
|
+
return window.localStorage.getItem(key);
|
|
256
|
+
} catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function peekSessionId(now = Date.now()) {
|
|
261
|
+
if (typeof window === "undefined") return null;
|
|
262
|
+
const raw = readLocalStorage(SESSION_STORAGE_KEY);
|
|
263
|
+
if (!raw) return null;
|
|
264
|
+
try {
|
|
265
|
+
const parsed = JSON.parse(raw);
|
|
266
|
+
if (typeof parsed.id !== "string" || typeof parsed.last_event_at !== "number") return null;
|
|
267
|
+
return now - parsed.last_event_at <= SESSION_IDLE_MS ? parsed.id : null;
|
|
268
|
+
} catch {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
179
272
|
|
|
180
273
|
// ../tracking-core/src/resources/http/errors.ts
|
|
181
274
|
var AranovaApiError = class extends Error {
|
|
@@ -185,9 +278,17 @@ var AranovaApiError = class extends Error {
|
|
|
185
278
|
this.status = options.status;
|
|
186
279
|
this.code = options.code;
|
|
187
280
|
this.requestId = options.requestId;
|
|
281
|
+
this.context = options.context;
|
|
188
282
|
}
|
|
189
283
|
};
|
|
190
284
|
|
|
285
|
+
// ../tracking-core/src/ingest.ts
|
|
286
|
+
var API_KEY_HEADER = "X-Aranova-Api-Key";
|
|
287
|
+
var SDK_VERSION_HEADER = "X-Aranova-Sdk-Version";
|
|
288
|
+
var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
|
|
289
|
+
var SDK_SURFACE_HEADER = "X-Aranova-Sdk-Surface";
|
|
290
|
+
var SDK_ENVIRONMENT_HEADER = "X-Aranova-Sdk-Environment";
|
|
291
|
+
|
|
191
292
|
// ../tracking-core/src/resources/http/request.ts
|
|
192
293
|
function identityHeaders(config) {
|
|
193
294
|
const headers = { [API_KEY_HEADER]: config.apiKey };
|
|
@@ -211,19 +312,24 @@ async function apiRequest(config, method, path, body, extraHeaders) {
|
|
|
211
312
|
if (!response.ok) {
|
|
212
313
|
let detail;
|
|
213
314
|
let code;
|
|
315
|
+
let context;
|
|
214
316
|
try {
|
|
215
317
|
const parsed = await response.json();
|
|
216
318
|
if (parsed && typeof parsed === "object") {
|
|
217
319
|
const record3 = parsed;
|
|
218
320
|
if (typeof record3.detail === "string") detail = record3.detail;
|
|
219
321
|
if (typeof record3.code === "string") code = record3.code;
|
|
322
|
+
if (record3.context && typeof record3.context === "object") {
|
|
323
|
+
context = record3.context;
|
|
324
|
+
}
|
|
220
325
|
}
|
|
221
326
|
} catch {
|
|
222
327
|
}
|
|
223
328
|
throw new AranovaApiError(detail ?? response.statusText ?? "Request failed", {
|
|
224
329
|
status: response.status,
|
|
225
330
|
code,
|
|
226
|
-
requestId: response.headers.get("x-request-id") ?? void 0
|
|
331
|
+
requestId: response.headers.get("x-request-id") ?? void 0,
|
|
332
|
+
context
|
|
227
333
|
});
|
|
228
334
|
}
|
|
229
335
|
if (response.status === 204) return void 0;
|
|
@@ -233,6 +339,179 @@ async function apiRequest(config, method, path, body, extraHeaders) {
|
|
|
233
339
|
// ../tracking-core/src/resources/sales/transport.ts
|
|
234
340
|
var salesRequest = apiRequest;
|
|
235
341
|
|
|
342
|
+
// ../tracking-core/src/resources/sales/bookings.ts
|
|
343
|
+
var BOOKING_ERROR_CODES = {
|
|
344
|
+
unavailable: "booking_unavailable",
|
|
345
|
+
stale: "booking_config_stale",
|
|
346
|
+
rejected: "booking_rejected"
|
|
347
|
+
};
|
|
348
|
+
var POLL_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 15e3];
|
|
349
|
+
var INVALID_DETAILS = "Please check your details and try again.";
|
|
350
|
+
var newBookingAttemptKey = uuidV4;
|
|
351
|
+
function sleep(ms) {
|
|
352
|
+
return new Promise((resolve) => {
|
|
353
|
+
setTimeout(resolve, ms);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
function outcomeOf(body) {
|
|
357
|
+
if (body.status === "created")
|
|
358
|
+
return { status: "created", id: body.id, requestCode: body.request_code };
|
|
359
|
+
if (body.status === "pending") return { status: "pending", id: body.id };
|
|
360
|
+
return { status: "failed", id: body.id, fallbackUrl: body.fallback_url };
|
|
361
|
+
}
|
|
362
|
+
function formSubmitPayload(input, formId, labels) {
|
|
363
|
+
const vehicle = input.vehicle ? `${input.vehicle.year} ${input.vehicle.make} ${input.vehicle.model}` : "";
|
|
364
|
+
const field = (name, type, label, value) => ({
|
|
365
|
+
name,
|
|
366
|
+
type,
|
|
367
|
+
label,
|
|
368
|
+
value
|
|
369
|
+
});
|
|
370
|
+
return {
|
|
371
|
+
form: {
|
|
372
|
+
id: formId,
|
|
373
|
+
action: "/tracking/bookings",
|
|
374
|
+
fields: [
|
|
375
|
+
field("first_name", "text", "First name", input.firstName),
|
|
376
|
+
field("last_name", "text", "Last name", input.lastName),
|
|
377
|
+
// E.164 on the wire: it keys the customer and enhanced-conversion matching.
|
|
378
|
+
field("phone", "tel", "Phone", toE164(input.phone) ?? input.phone),
|
|
379
|
+
field("email", "email", "Email", input.email ?? ""),
|
|
380
|
+
field(
|
|
381
|
+
"service",
|
|
382
|
+
"select",
|
|
383
|
+
"Service",
|
|
384
|
+
input.services.map((key) => labels.get(key) ?? key).join(", ")
|
|
385
|
+
),
|
|
386
|
+
field("vehicle", "text", "Vehicle", vehicle),
|
|
387
|
+
field(
|
|
388
|
+
"start",
|
|
389
|
+
"text",
|
|
390
|
+
"Requested time",
|
|
391
|
+
`${input.startDate} ${String(input.startHour).padStart(2, "0")}:00`
|
|
392
|
+
),
|
|
393
|
+
field("note", "textarea", "Notes", input.notes ?? "")
|
|
394
|
+
]
|
|
395
|
+
},
|
|
396
|
+
page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
function runtimeOf(firing) {
|
|
400
|
+
return firing && "integrations" in firing ? firing : null;
|
|
401
|
+
}
|
|
402
|
+
function createSalesBookingsClient(config, firing) {
|
|
403
|
+
const submittedForms = /* @__PURE__ */ new Set();
|
|
404
|
+
const staleAttempts = /* @__PURE__ */ new Set();
|
|
405
|
+
function handoff(input) {
|
|
406
|
+
const booking = getBookingIntegration(runtimeOf(firing)?.integrations());
|
|
407
|
+
if (!booking) return null;
|
|
408
|
+
return buildBookingHandoffUrl(booking.fallbackUrl, {
|
|
409
|
+
firstName: input.firstName,
|
|
410
|
+
lastName: input.lastName,
|
|
411
|
+
phone: input.phone,
|
|
412
|
+
email: input.email
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
function withHandoff(outcome, input) {
|
|
416
|
+
if (outcome.status === "failed" && !outcome.fallbackUrl) {
|
|
417
|
+
return { ...outcome, fallbackUrl: handoff(input) };
|
|
418
|
+
}
|
|
419
|
+
return outcome;
|
|
420
|
+
}
|
|
421
|
+
async function poll(id) {
|
|
422
|
+
let outcome = { status: "pending", id };
|
|
423
|
+
for (const delay of POLL_DELAYS_MS) {
|
|
424
|
+
await sleep(delay);
|
|
425
|
+
try {
|
|
426
|
+
const path = `/bookings/${encodeURIComponent(id)}`;
|
|
427
|
+
outcome = outcomeOf(await salesRequest(config, "GET", path));
|
|
428
|
+
} catch {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
if (outcome.status !== "pending") return outcome;
|
|
432
|
+
}
|
|
433
|
+
return outcome;
|
|
434
|
+
}
|
|
435
|
+
async function rejected(error, input, attemptKey, runtime) {
|
|
436
|
+
if (!(error instanceof AranovaApiError)) {
|
|
437
|
+
return { status: "failed", id: null, fallbackUrl: handoff(input) };
|
|
438
|
+
}
|
|
439
|
+
if (error.code === BOOKING_ERROR_CODES.stale) {
|
|
440
|
+
if (staleAttempts.has(attemptKey)) {
|
|
441
|
+
return { status: "failed", id: null, fallbackUrl: handoff(input) };
|
|
442
|
+
}
|
|
443
|
+
staleAttempts.add(attemptKey);
|
|
444
|
+
await runtime?.revalidate();
|
|
445
|
+
return { status: "stale", message: error.message };
|
|
446
|
+
}
|
|
447
|
+
if (error.code === BOOKING_ERROR_CODES.rejected) {
|
|
448
|
+
const reasons = error.context?.reasons;
|
|
449
|
+
return {
|
|
450
|
+
status: "invalid",
|
|
451
|
+
message: error.message,
|
|
452
|
+
reasons: Array.isArray(reasons) ? reasons.map(String) : []
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
if (error.code === "validation_error") {
|
|
456
|
+
return { status: "invalid", message: INVALID_DETAILS, reasons: [] };
|
|
457
|
+
}
|
|
458
|
+
return { status: "failed", id: null, fallbackUrl: handoff(input) };
|
|
459
|
+
}
|
|
460
|
+
return {
|
|
461
|
+
async submit(input, { attemptKey, formSubmit }) {
|
|
462
|
+
registerCapability("booking_integration");
|
|
463
|
+
const runtime = runtimeOf(firing);
|
|
464
|
+
const booking = getBookingIntegration(runtime?.integrations());
|
|
465
|
+
if (!booking?.acceptsBookings || booking.configVersion === null) {
|
|
466
|
+
return { status: "failed", id: null, fallbackUrl: handoff(input) };
|
|
467
|
+
}
|
|
468
|
+
if (formSubmit && !submittedForms.has(attemptKey)) {
|
|
469
|
+
submittedForms.add(attemptKey);
|
|
470
|
+
const labels = new Map(booking.options.map((option) => [option.key, option.label]));
|
|
471
|
+
formSubmit.tracking.trackEvent(
|
|
472
|
+
"form_submit",
|
|
473
|
+
formSubmitPayload(input, formSubmit.formId, labels)
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
const body = {
|
|
477
|
+
idempotency_key: attemptKey,
|
|
478
|
+
// The tracking client's own visit, so the booking and its form_submit share one session.
|
|
479
|
+
session_id: formSubmit?.tracking.getSessionId() ?? peekSessionId() ?? `no-session-${attemptKey}`,
|
|
480
|
+
config_version: booking.configVersion,
|
|
481
|
+
start_date: input.startDate,
|
|
482
|
+
start_hour: input.startHour,
|
|
483
|
+
first_name: input.firstName.trim(),
|
|
484
|
+
last_name: input.lastName.trim(),
|
|
485
|
+
phone: input.phone,
|
|
486
|
+
email: input.email?.trim() || null,
|
|
487
|
+
vehicle: input.vehicle ?? null,
|
|
488
|
+
drop_off: input.dropOff ?? null,
|
|
489
|
+
services: input.services,
|
|
490
|
+
notes: input.notes?.trim() || null,
|
|
491
|
+
marketing_sms_consent: input.marketingSmsConsent === true,
|
|
492
|
+
page_path: typeof window === "undefined" ? null : window.location.pathname
|
|
493
|
+
};
|
|
494
|
+
let response;
|
|
495
|
+
try {
|
|
496
|
+
response = await salesRequest(config, "POST", "/bookings", body);
|
|
497
|
+
} catch (error) {
|
|
498
|
+
return rejected(error, input, attemptKey, runtime);
|
|
499
|
+
}
|
|
500
|
+
const outcome = outcomeOf(response);
|
|
501
|
+
return withHandoff(outcome.status === "pending" ? await poll(outcome.id) : outcome, input);
|
|
502
|
+
},
|
|
503
|
+
async status(id) {
|
|
504
|
+
return outcomeOf(
|
|
505
|
+
await salesRequest(
|
|
506
|
+
config,
|
|
507
|
+
"GET",
|
|
508
|
+
`/bookings/${encodeURIComponent(id)}`
|
|
509
|
+
)
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
236
515
|
// ../tracking-core/src/resources/intl/date.ts
|
|
237
516
|
function formatDateInTz(iso3, timeZone, opts, locale) {
|
|
238
517
|
const date = new Date(iso3);
|
|
@@ -442,7 +721,8 @@ function createSalesClient(config) {
|
|
|
442
721
|
async config() {
|
|
443
722
|
return salesRequest(config, "GET", "/business/config");
|
|
444
723
|
}
|
|
445
|
-
}
|
|
724
|
+
},
|
|
725
|
+
bookings: createSalesBookingsClient(config, config.firing)
|
|
446
726
|
};
|
|
447
727
|
}
|
|
448
728
|
|
|
@@ -451,6 +731,12 @@ import * as z2 from "zod/mini";
|
|
|
451
731
|
|
|
452
732
|
// ../tracking-core/src/resources/sales/generated/zod.gen.ts
|
|
453
733
|
import * as z from "zod/mini";
|
|
734
|
+
var zAutoLeapSaleFacts = z.object({
|
|
735
|
+
first_order: z.boolean(),
|
|
736
|
+
fleet_customer: z.boolean(),
|
|
737
|
+
invoice_code: z.string(),
|
|
738
|
+
invoice_id: z.string()
|
|
739
|
+
});
|
|
454
740
|
var zErrorCode = z.enum([
|
|
455
741
|
"missing_credentials",
|
|
456
742
|
"invalid_api_key",
|
|
@@ -478,6 +764,9 @@ var zErrorCode = z.enum([
|
|
|
478
764
|
"booking_not_reschedulable",
|
|
479
765
|
"manage_token_invalid",
|
|
480
766
|
"google_error",
|
|
767
|
+
"booking_unavailable",
|
|
768
|
+
"booking_config_stale",
|
|
769
|
+
"booking_rejected",
|
|
481
770
|
"calendar_not_owned",
|
|
482
771
|
"calendar_is_sandbox",
|
|
483
772
|
"sandbox_exists",
|
|
@@ -519,6 +808,7 @@ var zSaleServiceInputSchema = z.strictObject({
|
|
|
519
808
|
amount_cents: z.int().check(z.gte(0)),
|
|
520
809
|
service: z.string()
|
|
521
810
|
});
|
|
811
|
+
var zSaleSource = z.enum(["api", "admin", "autoleap"]);
|
|
522
812
|
var zSmsAutomationState = z.enum([
|
|
523
813
|
"needs_check",
|
|
524
814
|
"failed",
|
|
@@ -550,7 +840,8 @@ var zSmsWithheldReason = z.enum([
|
|
|
550
840
|
"number_not_active",
|
|
551
841
|
"a2p_registration_required",
|
|
552
842
|
"alert_recipient_cannot_receive_sms",
|
|
553
|
-
"line_type_unresolved"
|
|
843
|
+
"line_type_unresolved",
|
|
844
|
+
"sale_source_sends_own_messages"
|
|
554
845
|
]);
|
|
555
846
|
var zSaleSmsStatusSchema = z.object({
|
|
556
847
|
can_send_now: z._default(z.boolean(), false),
|
|
@@ -659,6 +950,8 @@ var zSaleEntitySchema = z.object({
|
|
|
659
950
|
sms_automation: z.nullable(zSaleSmsStatusSchema),
|
|
660
951
|
sms_consent: z._default(z.boolean(), false),
|
|
661
952
|
sms_consent_granted_at: z.nullable(z.iso.datetime({ offset: true })),
|
|
953
|
+
source: zSaleSource,
|
|
954
|
+
source_facts: z.nullable(zAutoLeapSaleFacts),
|
|
662
955
|
updated_at: z.iso.datetime({ offset: true }),
|
|
663
956
|
writeback: z.nullable(zSaleWritebackStatusSchema)
|
|
664
957
|
});
|
|
@@ -668,6 +961,7 @@ var saleItemSchema = zSaleItemInputSchema;
|
|
|
668
961
|
var saleServiceSchema = zSaleServiceInputSchema;
|
|
669
962
|
var currencySchema = zSupportedCurrency;
|
|
670
963
|
var SUPPORTED_CURRENCIES = currencySchema.options;
|
|
964
|
+
var SALE_SOURCES = zSaleSource.options;
|
|
671
965
|
var centsSchema = z2.int().check(z2.gte(0));
|
|
672
966
|
var metadataSchema = z2.record(z2.string(), z2.unknown());
|
|
673
967
|
var customerNameSchema = z2.string().check(z2.maxLength(200));
|
|
@@ -747,6 +1041,7 @@ async function fetchServices(config) {
|
|
|
747
1041
|
export {
|
|
748
1042
|
AranovaApiError,
|
|
749
1043
|
NAMED_RANGES,
|
|
1044
|
+
SALE_SOURCES,
|
|
750
1045
|
SUPPORTED_CURRENCIES,
|
|
751
1046
|
TRACKING_RANGES,
|
|
752
1047
|
createSalesClient,
|
|
@@ -755,6 +1050,7 @@ export {
|
|
|
755
1050
|
formatDateInTz,
|
|
756
1051
|
formatMoney,
|
|
757
1052
|
fromMinor,
|
|
1053
|
+
newBookingAttemptKey,
|
|
758
1054
|
saleCreateSchema,
|
|
759
1055
|
saleItemSchema,
|
|
760
1056
|
saleServiceSchema,
|