@aranova/tracking-next 0.27.0 → 1.0.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 (71) 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 +4 -3
  26. package/dist/client.d.ts +4 -3
  27. package/dist/client.js +185 -277
  28. package/dist/client.js.map +1 -1
  29. package/dist/client.mjs +157 -249
  30. package/dist/client.mjs.map +1 -1
  31. package/dist/index.d.mts +8 -7
  32. package/dist/index.d.ts +8 -7
  33. package/dist/index.js +482 -484
  34. package/dist/index.js.map +1 -1
  35. package/dist/index.mjs +471 -484
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/ingest-typed-BdKmlouW.d.ts +791 -0
  38. package/dist/ingest-typed-Bo7WPmpU.d.mts +791 -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-CubQif9Z.d.mts} +18 -78
  44. package/dist/{phone-utils-BVzSNBf1.d.ts → phone-utils-CubQif9Z.d.ts} +18 -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-DQGzXSgL.d.mts → sales-D7KstKA-.d.mts} +89 -328
  52. package/dist/{sales-IGC2tq4J.d.ts → sales-DG150g3o.d.ts} +89 -328
  53. package/dist/sales.d.mts +2 -2
  54. package/dist/sales.d.ts +2 -2
  55. package/dist/sales.js +265 -127
  56. package/dist/sales.js.map +1 -1
  57. package/dist/sales.mjs +254 -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/transport-CDmGOiCq.d.ts +253 -0
  66. package/dist/transport-I_cMSFQ6.d.mts +253 -0
  67. package/package.json +2 -2
  68. package/dist/ingest-typed-BxLFlZ7N.d.mts +0 -1371
  69. package/dist/ingest-typed-ByQVRMvP.d.ts +0 -1371
  70. package/dist/transport-C-_rFSR4.d.ts +0 -721
  71. 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,264 @@ 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
+ ]);
535
+ var zSaleSmsStatusSchema = z.object({
536
+ can_send_now: z._default(z.boolean(), false),
537
+ last_message_at: z.nullable(z.iso.datetime({ offset: true })),
538
+ reason_detail: z.nullable(z.string()),
539
+ state: zSmsAutomationState,
540
+ suppressed_by_other_sale: z._default(z.boolean(), false),
541
+ withheld_reason: z.nullable(zSmsWithheldReason)
542
+ });
543
+ var zSupportedCurrency = z.enum(["USD", "CAD"]);
544
+ var zTrackingEnvironment = z.enum(["production", "development"]);
545
+ var zSaleCreateSchema = z.strictObject({
546
+ amount_total_cents: z.nullish(z.int().check(z.gte(0))),
547
+ currency: zSupportedCurrency,
548
+ customer_email: z.nullish(z.email().check(z.maxLength(320))),
549
+ customer_name: z.nullish(z.string().check(z.maxLength(200))),
550
+ customer_phone: z.nullish(z.string().check(z.maxLength(64))),
551
+ description: z.nullish(z.string()),
552
+ environment: z._default(z.optional(zTrackingEnvironment), "production"),
553
+ external_id: z.nullish(z.string()),
554
+ items: z.optional(z.array(zSaleItemInputSchema)),
555
+ metadata: z.nullish(z.record(z.string(), z.unknown())),
556
+ occurred_at: z.iso.datetime({ offset: true }),
557
+ service: z.nullish(z.string()),
558
+ services: z.nullish(z.array(zSaleServiceInputSchema)),
559
+ sms_consent: z.nullish(z.boolean())
560
+ });
561
+ var zValidationError = z.object({
562
+ ctx: z.optional(z.record(z.string(), z.unknown())),
563
+ input: z.optional(z.unknown()),
564
+ loc: z.array(z.union([z.string(), z.int()])),
565
+ msg: z.string(),
566
+ type: z.string()
567
+ });
568
+ var zHttpValidationError = z.object({
569
+ detail: z.optional(z.array(zValidationError))
570
+ });
571
+ var zValidationErrorItem = z.object({
572
+ loc: z.array(z.union([z.string(), z.int()])),
573
+ msg: z.string(),
574
+ type: z.string()
575
+ });
576
+ var zApiErrorSchema = z.object({
577
+ code: zErrorCode,
578
+ context: z._default(z.nullish(z.record(z.string(), z.unknown())), null),
579
+ detail: z.string(),
580
+ errors: z._default(z.nullish(z.array(zValidationErrorItem)), null),
581
+ request_id: z._default(z.nullish(z.string()), null)
582
+ });
583
+ var zWritebackEmailSource = z.enum(["NONE", "SALE", "CUSTOMER", "HARVESTED"]);
584
+ var zWritebackEnrichmentStatus = z.enum(["NONE", "MATCHED", "AMBIGUOUS"]);
585
+ var zWritebackSaleUploadCounts = z.object({
586
+ failed: z._default(z.int(), 0),
587
+ pending: z._default(z.int(), 0),
588
+ skipped: z._default(z.int(), 0),
589
+ submitted: z._default(z.int(), 0),
590
+ total: z._default(z.int(), 0),
591
+ uploaded: z._default(z.int(), 0)
592
+ });
593
+ var zSaleWritebackStatusSchema = z.object({
594
+ blocked_reason: z.nullable(z.string()),
595
+ can_dispatch: z._default(z.boolean(), false),
596
+ email_source: z.nullable(zWritebackEmailSource),
597
+ enrichment_status: z.nullable(zWritebackEnrichmentStatus),
598
+ gclid_attached: z._default(z.boolean(), false),
599
+ identifiers_sent: z.nullable(z.string()),
600
+ mapped_service_ids: z.array(z.uuid()),
601
+ matched_submit_count: z.nullable(z.int()),
602
+ needs_force: z._default(z.boolean(), false),
603
+ rollup: z.enum([
604
+ "failed",
605
+ "skipped",
606
+ "pending",
607
+ "submitted",
608
+ "uploaded",
609
+ "not_uploaded",
610
+ "out_of_window",
611
+ "blocked"
612
+ ]),
613
+ stale: z._default(z.boolean(), false),
614
+ uncovered_service_ids: z.array(z.uuid()),
615
+ uploads: zWritebackSaleUploadCounts
616
+ });
617
+ var zSaleEntitySchema = z.object({
618
+ amount_total_cents: z.int(),
619
+ business_id: z.uuid(),
620
+ business_name: z.nullable(z.string()),
621
+ created_at: z.iso.datetime({ offset: true }),
622
+ currency: z.string(),
623
+ customer_email: z.nullable(z.string()),
624
+ customer_name: z.nullable(z.string()),
625
+ customer_name_placeholder_confirmed: z._default(z.boolean(), false),
626
+ customer_name_placeholder_confirmed_at: z.nullable(z.iso.datetime({ offset: true })),
627
+ customer_phone: z.nullable(z.string()),
628
+ description: z.nullable(z.string()),
629
+ environment: zTrackingEnvironment,
630
+ external_id: z.nullable(z.string()),
631
+ id: z.uuid(),
632
+ items: z.array(zSaleItemEntitySchema),
633
+ metadata: z.nullable(z.record(z.string(), z.unknown())),
634
+ occurred_at: z.iso.datetime({ offset: true }),
635
+ service_id: z.nullable(z.uuid()),
636
+ service_key: z.nullable(z.string()),
637
+ service_label: z.nullable(z.string()),
638
+ services: z.array(zSaleServiceEntitySchema),
639
+ sms_automation: z.nullable(zSaleSmsStatusSchema),
640
+ sms_consent: z._default(z.boolean(), false),
641
+ sms_consent_granted_at: z.nullable(z.iso.datetime({ offset: true })),
642
+ updated_at: z.iso.datetime({ offset: true }),
643
+ writeback: z.nullable(zSaleWritebackStatusSchema)
644
+ });
645
+
646
+ // ../tracking-core/src/resources/sales/schema.ts
647
+ var saleItemSchema = zSaleItemInputSchema;
648
+ var saleServiceSchema = zSaleServiceInputSchema;
649
+ var currencySchema = zSupportedCurrency;
650
+ var SUPPORTED_CURRENCIES = currencySchema.options;
651
+ var centsSchema = z2.int().check(z2.gte(0));
652
+ var metadataSchema = z2.record(z2.string(), z2.unknown());
653
+ var customerNameSchema = z2.string().check(z2.maxLength(200));
654
+ var customerPhoneSchema = z2.string().check(z2.maxLength(64));
655
+ var customerEmailSchema = z2.email().check(z2.maxLength(320));
656
+ function addIssue(ctx, path, message) {
657
+ ctx.issues.push({ code: "custom", input: ctx.value, path, message });
658
+ }
497
659
  function refineServiceXor(val, ctx, { requireAmount }) {
498
660
  if (val.services != null) {
499
661
  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
- });
662
+ addIssue(ctx, ["services"], "pass either `service` or `services`, not both");
505
663
  }
506
664
  if (val.services.length === 0) {
507
- ctx.addIssue({
508
- code: z2.ZodIssueCode.custom,
509
- message: "`services` must not be empty",
510
- path: ["services"]
511
- });
665
+ addIssue(ctx, ["services"], "`services` must not be empty");
512
666
  }
513
667
  const keys = val.services.map((s) => s.service);
514
668
  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
- });
669
+ addIssue(ctx, ["services"], "`services` must not list the same service more than once");
520
670
  }
521
671
  if (val.amount_total_cents != null) {
522
672
  const sum = val.services.reduce((acc, s) => acc + s.amount_cents, 0);
523
673
  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
- });
674
+ addIssue(
675
+ ctx,
676
+ ["amount_total_cents"],
677
+ "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)"
678
+ );
529
679
  }
530
680
  }
531
681
  } 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
- });
682
+ addIssue(
683
+ ctx,
684
+ ["amount_total_cents"],
685
+ "amount_total_cents is required unless `services` is provided"
686
+ );
537
687
  }
538
688
  }
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(),
689
+ var saleCreateSchema = z2.extend(zSaleCreateSchema, { items: z2._default(z2.array(saleItemSchema), []) }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: true }));
690
+ var saleUpdateSchema = z2.strictObject({
691
+ description: z2.nullish(z2.string()),
692
+ service: z2.nullish(z2.string()),
693
+ services: z2.nullish(z2.array(saleServiceSchema)),
694
+ currency: z2.optional(currencySchema),
695
+ amount_total_cents: z2.optional(centsSchema),
696
+ occurred_at: z2.optional(z2.iso.datetime()),
697
+ items: z2.optional(z2.array(saleItemSchema)),
698
+ metadata: z2.nullish(metadataSchema),
699
+ customer_name: z2.nullish(customerNameSchema),
574
700
  // Re-attest when changing a filler-looking name; the server clears the
575
701
  // 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(),
702
+ customer_name_placeholder_confirmed: z2.optional(z2.boolean()),
703
+ customer_phone: z2.nullish(customerPhoneSchema),
704
+ customer_email: z2.nullish(customerEmailSchema),
579
705
  // 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 }));
706
+ sms_consent: z2.optional(z2.boolean())
707
+ }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: false }));
582
708
  var TRACKING_RANGES = ["24h", "7d", "30d"];
583
709
  var NAMED_RANGES = [
584
710
  "today",
@@ -604,6 +730,7 @@ export {
604
730
  SUPPORTED_CURRENCIES,
605
731
  TRACKING_RANGES,
606
732
  createSalesClient,
733
+ currencySchema,
607
734
  fetchServices,
608
735
  formatDateInTz,
609
736
  formatMoney,