@aranova/tracking-next 0.27.0 → 1.1.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.
Files changed (73) hide show
  1. package/dist/blog-server.d.mts +2 -1
  2. package/dist/blog-server.d.ts +2 -1
  3. package/dist/blog-server.js +121 -98
  4. package/dist/blog-server.js.map +1 -1
  5. package/dist/blog-server.mjs +86 -63
  6. package/dist/blog-server.mjs.map +1 -1
  7. package/dist/blog.d.mts +651 -1755
  8. package/dist/blog.d.ts +651 -1755
  9. package/dist/blog.js +121 -98
  10. package/dist/blog.js.map +1 -1
  11. package/dist/blog.mjs +86 -63
  12. package/dist/blog.mjs.map +1 -1
  13. package/dist/calendar-server.d.mts +2 -2
  14. package/dist/calendar-server.d.ts +2 -2
  15. package/dist/calendar-server.js +0 -26
  16. package/dist/calendar-server.js.map +1 -1
  17. package/dist/calendar-server.mjs +0 -26
  18. package/dist/calendar-server.mjs.map +1 -1
  19. package/dist/calendar.d.mts +3 -3
  20. package/dist/calendar.d.ts +3 -3
  21. package/dist/calendar.js +227 -126
  22. package/dist/calendar.js.map +1 -1
  23. package/dist/calendar.mjs +216 -125
  24. package/dist/calendar.mjs.map +1 -1
  25. package/dist/client.d.mts +11 -4
  26. package/dist/client.d.ts +11 -4
  27. package/dist/client.js +611 -347
  28. package/dist/client.js.map +1 -1
  29. package/dist/client.mjs +611 -347
  30. package/dist/client.mjs.map +1 -1
  31. package/dist/index.d.mts +9 -8
  32. package/dist/index.d.ts +9 -8
  33. package/dist/index.js +550 -487
  34. package/dist/index.js.map +1 -1
  35. package/dist/index.mjs +539 -487
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/ingest-typed-MBuMe9Pn.d.ts +883 -0
  38. package/dist/ingest-typed-UA13xTfI.d.mts +883 -0
  39. package/dist/middleware.js +0 -467
  40. package/dist/middleware.js.map +1 -1
  41. package/dist/middleware.mjs +0 -467
  42. package/dist/middleware.mjs.map +1 -1
  43. package/dist/{phone-utils-BVzSNBf1.d.mts → phone-utils-C0ds6cqZ.d.mts} +24 -78
  44. package/dist/{phone-utils-BVzSNBf1.d.ts → phone-utils-C0ds6cqZ.d.ts} +24 -78
  45. package/dist/phone.d.mts +2 -2
  46. package/dist/phone.d.ts +2 -2
  47. package/dist/phone.js +0 -464
  48. package/dist/phone.js.map +1 -1
  49. package/dist/phone.mjs +0 -464
  50. package/dist/phone.mjs.map +1 -1
  51. package/dist/{sales-IGC2tq4J.d.ts → sales-DQC815f3.d.ts} +90 -329
  52. package/dist/{sales-DQGzXSgL.d.mts → sales-w1reW_Y3.d.mts} +90 -329
  53. package/dist/sales.d.mts +3 -3
  54. package/dist/sales.d.ts +3 -3
  55. package/dist/sales.js +270 -127
  56. package/dist/sales.js.map +1 -1
  57. package/dist/sales.mjs +259 -127
  58. package/dist/sales.mjs.map +1 -1
  59. package/dist/server.d.mts +2 -2
  60. package/dist/server.d.ts +2 -2
  61. package/dist/server.js +0 -467
  62. package/dist/server.js.map +1 -1
  63. package/dist/server.mjs +0 -467
  64. package/dist/server.mjs.map +1 -1
  65. package/dist/{tracking-config-runtime-D7prdTE1.d.mts → tracking-config-runtime-C6H7ofmo.d.mts} +6 -0
  66. package/dist/{tracking-config-runtime-D7prdTE1.d.ts → tracking-config-runtime-C6H7ofmo.d.ts} +6 -0
  67. package/dist/transport-CDmGOiCq.d.ts +253 -0
  68. package/dist/transport-I_cMSFQ6.d.mts +253 -0
  69. package/package.json +2 -2
  70. package/dist/ingest-typed-BxLFlZ7N.d.mts +0 -1371
  71. package/dist/ingest-typed-ByQVRMvP.d.ts +0 -1371
  72. package/dist/transport-C-_rFSR4.d.ts +0 -721
  73. package/dist/transport-yUF5Wize.d.mts +0 -721
package/dist/sales.mjs CHANGED
@@ -37,7 +37,7 @@ function normalizeEmail(raw) {
37
37
  return EMAIL_SHAPE.test(cleaned) ? cleaned : null;
38
38
  }
39
39
  function stashUserData(data, country) {
40
- const email = normalizeEmail(data.email);
40
+ const email3 = normalizeEmail(data.email);
41
41
  let phoneNumber = null;
42
42
  if (typeof data.phone === "string" && data.phone.length > 0) {
43
43
  try {
@@ -47,17 +47,17 @@ function stashUserData(data, country) {
47
47
  }
48
48
  }
49
49
  stash = {
50
- email: email ?? stash.email,
50
+ email: email3 ?? stash.email,
51
51
  phoneNumber: phoneNumber ?? stash.phoneNumber
52
52
  };
53
53
  }
54
54
  function applyUserDataForConversion(explicit, country) {
55
55
  if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
56
- let email = stash.email;
56
+ let email3 = stash.email;
57
57
  let phoneNumber = stash.phoneNumber;
58
58
  if (explicit) {
59
59
  const normalizedEmail = normalizeEmail(explicit.email);
60
- if (normalizedEmail) email = normalizedEmail;
60
+ if (normalizedEmail) email3 = normalizedEmail;
61
61
  if (typeof explicit.phone === "string" && explicit.phone.length > 0) {
62
62
  try {
63
63
  phoneNumber = toE164(explicit.phone, country) ?? phoneNumber;
@@ -65,10 +65,10 @@ function applyUserDataForConversion(explicit, country) {
65
65
  }
66
66
  }
67
67
  }
68
- if (email === null && phoneNumber === null) return false;
68
+ if (email3 === null && phoneNumber === null) return false;
69
69
  try {
70
70
  window.gtag("set", "user_data", {
71
- ...email !== null ? { email } : {},
71
+ ...email3 !== null ? { email: email3 } : {},
72
72
  ...phoneNumber !== null ? { phone_number: phoneNumber } : {}
73
73
  });
74
74
  return true;
@@ -170,29 +170,6 @@ function fireConversionWithConsent(input, options) {
170
170
  }
171
171
  }
172
172
 
173
- // ../tracking-core/src/events/page-view.ts
174
- import { z } from "zod";
175
- var pageViewMetadataSchema = z.object({
176
- page: z.object({
177
- title: z.string().nullable(),
178
- path: z.string(),
179
- search: z.string(),
180
- hash: z.string()
181
- }).strict(),
182
- referrer: z.string().nullable(),
183
- // `.nullable().optional()` — absent (undefined) OR explicit null OR a
184
- // real viewport object. Mirrors Pydantic's `_Viewport | None = None`
185
- // on the backend side so the drift test stays clean.
186
- viewport: z.object({
187
- w: z.number(),
188
- h: z.number()
189
- }).strict().nullable().optional()
190
- }).strict();
191
- var pageViewConfigSchema = z.object({}).strict();
192
-
193
- // ../tracking-core/src/session.ts
194
- var SESSION_IDLE_MS = 30 * 60 * 1e3;
195
-
196
173
  // ../tracking-core/src/ingest.ts
197
174
  var API_KEY_HEADER = "X-Aranova-Api-Key";
198
175
  var SDK_VERSION_HEADER = "X-Aranova-Sdk-Version";
@@ -237,9 +214,9 @@ async function apiRequest(config, method, path, body, extraHeaders) {
237
214
  try {
238
215
  const parsed = await response.json();
239
216
  if (parsed && typeof parsed === "object") {
240
- const record = parsed;
241
- if (typeof record.detail === "string") detail = record.detail;
242
- if (typeof record.code === "string") code = record.code;
217
+ const record3 = parsed;
218
+ if (typeof record3.detail === "string") detail = record3.detail;
219
+ if (typeof record3.code === "string") code = record3.code;
243
220
  }
244
221
  } catch {
245
222
  }
@@ -257,9 +234,9 @@ async function apiRequest(config, method, path, body, extraHeaders) {
257
234
  var salesRequest = apiRequest;
258
235
 
259
236
  // ../tracking-core/src/resources/intl/date.ts
260
- function formatDateInTz(iso, timeZone, opts, locale) {
261
- const date = new Date(iso);
262
- if (Number.isNaN(date.getTime())) return iso;
237
+ function formatDateInTz(iso3, timeZone, opts, locale) {
238
+ const date = new Date(iso3);
239
+ if (Number.isNaN(date.getTime())) return iso3;
263
240
  return new Intl.DateTimeFormat(locale, {
264
241
  year: "numeric",
265
242
  month: "short",
@@ -323,7 +300,7 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
323
300
  }
324
301
  function createSalesClient(config) {
325
302
  if (config.firing) registerCapability("conversion_goals_manual");
326
- async function record(input) {
303
+ async function record3(input) {
327
304
  const currency = input.currency ?? config.defaultCurrency;
328
305
  if (!currency) {
329
306
  throw new Error(
@@ -349,9 +326,9 @@ function createSalesClient(config) {
349
326
  return sale;
350
327
  }
351
328
  return {
352
- record,
329
+ record: record3,
353
330
  // recordSale is the intent-revealing alias — same behavior, clearer call site.
354
- recordSale: record,
331
+ recordSale: record3,
355
332
  trackConversion(key, options) {
356
333
  if (config.firing && "fireConversion" in config.firing) {
357
334
  if (options?.userData && getConsentState() !== "denied") stashUserData(options.userData);
@@ -470,115 +447,269 @@ function createSalesClient(config) {
470
447
  }
471
448
 
472
449
  // ../tracking-core/src/resources/sales/schema.ts
473
- import { z as z2 } from "zod";
474
- var SUPPORTED_CURRENCIES = ["USD", "CAD"];
475
- var TRACKING_ENVIRONMENTS = ["production", "development"];
476
- var currencySchema = z2.enum(SUPPORTED_CURRENCIES);
477
- var centsSchema = z2.number().int().nonnegative();
478
- var quantitySchema = z2.string().regex(/^\d+(\.\d{1,3})?$/);
479
- var metadataSchema = z2.record(z2.unknown());
480
- var saleItemSchema = z2.object({
481
- external_item_id: z2.string().nullable().optional(),
482
- name: z2.string().nullable().optional(),
483
- category: z2.string().nullable().optional(),
484
- quantity: quantitySchema,
485
- unit_price_cents: centsSchema,
486
- // Non-negativity validated on the wire — same contract as the other cents
487
- // fields — and backstopped by the DB CHECK.
488
- unit_cost_cents: centsSchema.nullable().optional()
489
- }).strict();
490
- var saleServiceSchema = z2.object({
491
- service: z2.string(),
492
- amount_cents: centsSchema
493
- }).strict();
494
- var customerNameSchema = z2.string().max(200);
495
- var customerPhoneSchema = z2.string().max(64);
496
- var customerEmailSchema = z2.string().max(320).email();
450
+ import * as z2 from "zod/mini";
451
+
452
+ // ../tracking-core/src/resources/sales/generated/zod.gen.ts
453
+ import * as z from "zod/mini";
454
+ var zErrorCode = z.enum([
455
+ "missing_credentials",
456
+ "invalid_api_key",
457
+ "not_authenticated",
458
+ "wrong_key_type",
459
+ "origin_missing",
460
+ "origin_not_allowed",
461
+ "capability_denied",
462
+ "session_required",
463
+ "operator_only",
464
+ "cross_tenant",
465
+ "business_id_required",
466
+ "bad_request",
467
+ "not_found",
468
+ "conflict",
469
+ "incompatible_payload",
470
+ "repeat_confirmation_required",
471
+ "idempotency_conflict",
472
+ "validation_error",
473
+ "unknown_service",
474
+ "invalid_sale_properties",
475
+ "invalid_cursor",
476
+ "rate_limited",
477
+ "internal_error"
478
+ ]);
479
+ var zSaleItemEntitySchema = z.object({
480
+ category: z.nullable(z.string()),
481
+ external_item_id: z.nullable(z.string()),
482
+ id: z.uuid(),
483
+ name: z.nullable(z.string()),
484
+ quantity: z.string().check(z.regex(/^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$/)),
485
+ unit_cost_cents: z.nullable(z.int()),
486
+ unit_price_cents: z.int()
487
+ });
488
+ var zSaleItemInputSchema = z.strictObject({
489
+ category: z.nullish(z.string()),
490
+ external_item_id: z.nullish(z.string()),
491
+ name: z.nullish(z.string()),
492
+ quantity: z.string().check(z.regex(/^\d+(\.\d{1,3})?$/)),
493
+ unit_cost_cents: z.nullish(z.int().check(z.gte(0))),
494
+ unit_price_cents: z.int().check(z.gte(0))
495
+ });
496
+ var zSaleServiceEntitySchema = z.object({
497
+ amount_cents: z.int(),
498
+ id: z.uuid(),
499
+ mapped: z.nullable(z.boolean()),
500
+ service_id: z.uuid(),
501
+ service_key: z.string(),
502
+ service_label: z.string()
503
+ });
504
+ var zSaleServiceInputSchema = z.strictObject({
505
+ amount_cents: z.int().check(z.gte(0)),
506
+ service: z.string()
507
+ });
508
+ var zSmsAutomationState = z.enum([
509
+ "needs_check",
510
+ "failed",
511
+ "undelivered",
512
+ "blocked_opted_out",
513
+ "withheld",
514
+ "queued",
515
+ "sent",
516
+ "delivered",
517
+ "eligible",
518
+ "not_applicable"
519
+ ]);
520
+ var zSmsWithheldReason = z.enum([
521
+ "automation_disabled",
522
+ "sms_disabled",
523
+ "no_phone",
524
+ "no_consent",
525
+ "no_customer_identity",
526
+ "missing_customer_name",
527
+ "placeholder_customer_name",
528
+ "opted_out",
529
+ "already_messaged",
530
+ "sender_not_ready",
531
+ "missing_review_url",
532
+ "no_handler",
533
+ "dispatch_already_recorded",
534
+ "text_back_disabled",
535
+ "number_not_active",
536
+ "a2p_registration_required",
537
+ "alert_recipient_cannot_receive_sms",
538
+ "line_type_unresolved"
539
+ ]);
540
+ var zSaleSmsStatusSchema = z.object({
541
+ can_send_now: z._default(z.boolean(), false),
542
+ last_message_at: z.nullable(z.iso.datetime({ offset: true })),
543
+ reason_detail: z.nullable(z.string()),
544
+ state: zSmsAutomationState,
545
+ suppressed_by_other_sale: z._default(z.boolean(), false),
546
+ withheld_reason: z.nullable(zSmsWithheldReason)
547
+ });
548
+ var zSupportedCurrency = z.enum(["USD", "CAD"]);
549
+ var zTrackingEnvironment = z.enum(["production", "development"]);
550
+ var zSaleCreateSchema = z.strictObject({
551
+ amount_total_cents: z.nullish(z.int().check(z.gte(0))),
552
+ currency: zSupportedCurrency,
553
+ customer_email: z.nullish(z.email().check(z.maxLength(320))),
554
+ customer_name: z.nullish(z.string().check(z.maxLength(200))),
555
+ customer_phone: z.nullish(z.string().check(z.maxLength(64))),
556
+ description: z.nullish(z.string()),
557
+ environment: z._default(z.optional(zTrackingEnvironment), "production"),
558
+ external_id: z.nullish(z.string()),
559
+ items: z.optional(z.array(zSaleItemInputSchema)),
560
+ metadata: z.nullish(z.record(z.string(), z.unknown())),
561
+ occurred_at: z.iso.datetime({ offset: true }),
562
+ service: z.nullish(z.string()),
563
+ services: z.nullish(z.array(zSaleServiceInputSchema)),
564
+ sms_consent: z.nullish(z.boolean())
565
+ });
566
+ var zValidationError = z.object({
567
+ ctx: z.optional(z.record(z.string(), z.unknown())),
568
+ input: z.optional(z.unknown()),
569
+ loc: z.array(z.union([z.string(), z.int()])),
570
+ msg: z.string(),
571
+ type: z.string()
572
+ });
573
+ var zHttpValidationError = z.object({
574
+ detail: z.optional(z.array(zValidationError))
575
+ });
576
+ var zValidationErrorItem = z.object({
577
+ loc: z.array(z.union([z.string(), z.int()])),
578
+ msg: z.string(),
579
+ type: z.string()
580
+ });
581
+ var zApiErrorSchema = z.object({
582
+ code: zErrorCode,
583
+ context: z._default(z.nullish(z.record(z.string(), z.unknown())), null),
584
+ detail: z.string(),
585
+ errors: z._default(z.nullish(z.array(zValidationErrorItem)), null),
586
+ request_id: z._default(z.nullish(z.string()), null)
587
+ });
588
+ var zWritebackEmailSource = z.enum(["NONE", "SALE", "CUSTOMER", "HARVESTED"]);
589
+ var zWritebackEnrichmentStatus = z.enum(["NONE", "MATCHED", "AMBIGUOUS"]);
590
+ var zWritebackSaleUploadCounts = z.object({
591
+ failed: z._default(z.int(), 0),
592
+ pending: z._default(z.int(), 0),
593
+ skipped: z._default(z.int(), 0),
594
+ submitted: z._default(z.int(), 0),
595
+ total: z._default(z.int(), 0),
596
+ uploaded: z._default(z.int(), 0)
597
+ });
598
+ var zSaleWritebackStatusSchema = z.object({
599
+ blocked_reason: z.nullable(z.string()),
600
+ can_dispatch: z._default(z.boolean(), false),
601
+ email_source: z.nullable(zWritebackEmailSource),
602
+ enrichment_status: z.nullable(zWritebackEnrichmentStatus),
603
+ gclid_attached: z._default(z.boolean(), false),
604
+ identifiers_sent: z.nullable(z.string()),
605
+ mapped_service_ids: z.array(z.uuid()),
606
+ matched_submit_count: z.nullable(z.int()),
607
+ needs_force: z._default(z.boolean(), false),
608
+ rollup: z.enum([
609
+ "failed",
610
+ "skipped",
611
+ "pending",
612
+ "submitted",
613
+ "uploaded",
614
+ "not_uploaded",
615
+ "out_of_window",
616
+ "blocked"
617
+ ]),
618
+ stale: z._default(z.boolean(), false),
619
+ uncovered_service_ids: z.array(z.uuid()),
620
+ uploads: zWritebackSaleUploadCounts
621
+ });
622
+ var zSaleEntitySchema = z.object({
623
+ amount_total_cents: z.int(),
624
+ business_id: z.uuid(),
625
+ business_name: z.nullable(z.string()),
626
+ created_at: z.iso.datetime({ offset: true }),
627
+ currency: z.string(),
628
+ customer_email: z.nullable(z.string()),
629
+ customer_name: z.nullable(z.string()),
630
+ customer_name_placeholder_confirmed: z._default(z.boolean(), false),
631
+ customer_name_placeholder_confirmed_at: z.nullable(z.iso.datetime({ offset: true })),
632
+ customer_phone: z.nullable(z.string()),
633
+ description: z.nullable(z.string()),
634
+ environment: zTrackingEnvironment,
635
+ external_id: z.nullable(z.string()),
636
+ id: z.uuid(),
637
+ items: z.array(zSaleItemEntitySchema),
638
+ metadata: z.nullable(z.record(z.string(), z.unknown())),
639
+ occurred_at: z.iso.datetime({ offset: true }),
640
+ service_id: z.nullable(z.uuid()),
641
+ service_key: z.nullable(z.string()),
642
+ service_label: z.nullable(z.string()),
643
+ services: z.array(zSaleServiceEntitySchema),
644
+ sms_automation: z.nullable(zSaleSmsStatusSchema),
645
+ sms_consent: z._default(z.boolean(), false),
646
+ sms_consent_granted_at: z.nullable(z.iso.datetime({ offset: true })),
647
+ updated_at: z.iso.datetime({ offset: true }),
648
+ writeback: z.nullable(zSaleWritebackStatusSchema)
649
+ });
650
+
651
+ // ../tracking-core/src/resources/sales/schema.ts
652
+ var saleItemSchema = zSaleItemInputSchema;
653
+ var saleServiceSchema = zSaleServiceInputSchema;
654
+ var currencySchema = zSupportedCurrency;
655
+ var SUPPORTED_CURRENCIES = currencySchema.options;
656
+ var centsSchema = z2.int().check(z2.gte(0));
657
+ var metadataSchema = z2.record(z2.string(), z2.unknown());
658
+ var customerNameSchema = z2.string().check(z2.maxLength(200));
659
+ var customerPhoneSchema = z2.string().check(z2.maxLength(64));
660
+ var customerEmailSchema = z2.email().check(z2.maxLength(320));
661
+ function addIssue(ctx, path, message) {
662
+ ctx.issues.push({ code: "custom", input: ctx.value, path, message });
663
+ }
497
664
  function refineServiceXor(val, ctx, { requireAmount }) {
498
665
  if (val.services != null) {
499
666
  if (val.service != null) {
500
- ctx.addIssue({
501
- code: z2.ZodIssueCode.custom,
502
- message: "pass either `service` or `services`, not both",
503
- path: ["services"]
504
- });
667
+ addIssue(ctx, ["services"], "pass either `service` or `services`, not both");
505
668
  }
506
669
  if (val.services.length === 0) {
507
- ctx.addIssue({
508
- code: z2.ZodIssueCode.custom,
509
- message: "`services` must not be empty",
510
- path: ["services"]
511
- });
670
+ addIssue(ctx, ["services"], "`services` must not be empty");
512
671
  }
513
672
  const keys = val.services.map((s) => s.service);
514
673
  if (new Set(keys).size !== keys.length) {
515
- ctx.addIssue({
516
- code: z2.ZodIssueCode.custom,
517
- message: "`services` must not list the same service more than once",
518
- path: ["services"]
519
- });
674
+ addIssue(ctx, ["services"], "`services` must not list the same service more than once");
520
675
  }
521
676
  if (val.amount_total_cents != null) {
522
677
  const sum = val.services.reduce((acc, s) => acc + s.amount_cents, 0);
523
678
  if (val.amount_total_cents !== sum) {
524
- ctx.addIssue({
525
- code: z2.ZodIssueCode.custom,
526
- message: "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)",
527
- path: ["amount_total_cents"]
528
- });
679
+ addIssue(
680
+ ctx,
681
+ ["amount_total_cents"],
682
+ "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)"
683
+ );
529
684
  }
530
685
  }
531
686
  } else if (requireAmount && val.amount_total_cents == null) {
532
- ctx.addIssue({
533
- code: z2.ZodIssueCode.custom,
534
- message: "amount_total_cents is required unless `services` is provided",
535
- path: ["amount_total_cents"]
536
- });
687
+ addIssue(
688
+ ctx,
689
+ ["amount_total_cents"],
690
+ "amount_total_cents is required unless `services` is provided"
691
+ );
537
692
  }
538
693
  }
539
- var saleCreateSchema = z2.object({
540
- external_id: z2.string().nullable().optional(),
541
- description: z2.string().nullable().optional(),
542
- service: z2.string().nullable().optional(),
543
- services: z2.array(saleServiceSchema).nullable().optional(),
544
- currency: currencySchema,
545
- // Optional only because the plural `services` form derives it from the sum
546
- // (see refineServiceXor); the singular/serviceless path still requires it.
547
- amount_total_cents: centsSchema.nullable().optional(),
548
- occurred_at: z2.string().datetime(),
549
- environment: z2.enum(TRACKING_ENVIRONMENTS).default("production"),
550
- items: z2.array(saleItemSchema).default([]),
551
- metadata: metadataSchema.nullable().optional(),
552
- customer_name: customerNameSchema.nullable().optional(),
553
- customer_phone: customerPhoneSchema.nullable().optional(),
554
- customer_email: customerEmailSchema.nullable().optional(),
555
- // CASL consent attestation: the customer agreed to receive SMS. Recorded
556
- // with a timestamp server-side; every SMS send path gates on it.
557
- //
558
- // Tri-state: omit it (or send null) to let the server apply the business's
559
- // configured default-opt-in policy, honouring a returning customer's
560
- // remembered preference. Send an explicit boolean to assert consent state
561
- // yourself — `false` records a deliberate opt-out.
562
- sms_consent: z2.boolean().nullable().optional()
563
- }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: true }));
564
- var saleUpdateSchema = z2.object({
565
- description: z2.string().nullable().optional(),
566
- service: z2.string().nullable().optional(),
567
- services: z2.array(saleServiceSchema).nullable().optional(),
568
- currency: currencySchema.optional(),
569
- amount_total_cents: centsSchema.optional(),
570
- occurred_at: z2.string().datetime().optional(),
571
- items: z2.array(saleItemSchema).optional(),
572
- metadata: metadataSchema.nullable().optional(),
573
- customer_name: customerNameSchema.nullable().optional(),
694
+ var saleCreateSchema = z2.extend(zSaleCreateSchema, { items: z2._default(z2.array(saleItemSchema), []) }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: true }));
695
+ var saleUpdateSchema = z2.strictObject({
696
+ description: z2.nullish(z2.string()),
697
+ service: z2.nullish(z2.string()),
698
+ services: z2.nullish(z2.array(saleServiceSchema)),
699
+ currency: z2.optional(currencySchema),
700
+ amount_total_cents: z2.optional(centsSchema),
701
+ occurred_at: z2.optional(z2.iso.datetime()),
702
+ items: z2.optional(z2.array(saleItemSchema)),
703
+ metadata: z2.nullish(metadataSchema),
704
+ customer_name: z2.nullish(customerNameSchema),
574
705
  // Re-attest when changing a filler-looking name; the server clears the
575
706
  // prior attestation whenever `customer_name` changes.
576
- customer_name_placeholder_confirmed: z2.boolean().optional(),
577
- customer_phone: customerPhoneSchema.nullable().optional(),
578
- customer_email: customerEmailSchema.nullable().optional(),
707
+ customer_name_placeholder_confirmed: z2.optional(z2.boolean()),
708
+ customer_phone: z2.nullish(customerPhoneSchema),
709
+ customer_email: z2.nullish(customerEmailSchema),
579
710
  // NOT NULL server-side: omit to leave unchanged (explicit null is rejected).
580
- sms_consent: z2.boolean().optional()
581
- }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: false }));
711
+ sms_consent: z2.optional(z2.boolean())
712
+ }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: false }));
582
713
  var TRACKING_RANGES = ["24h", "7d", "30d"];
583
714
  var NAMED_RANGES = [
584
715
  "today",
@@ -604,6 +735,7 @@ export {
604
735
  SUPPORTED_CURRENCIES,
605
736
  TRACKING_RANGES,
606
737
  createSalesClient,
738
+ currencySchema,
607
739
  fetchServices,
608
740
  formatDateInTz,
609
741
  formatMoney,