@riverbankcms/sdk 0.90.1 → 0.92.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 (113) hide show
  1. package/dist/{PreviewEditorSidebar-FNFRVSIM.mjs → PreviewEditorSidebar-3CI5MKV3.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-3WXJFQXG.mjs → PreviewEditorUI-DKEP636I.mjs} +3 -3
  3. package/dist/SdkPreviewModeRuntime-BRGRDQFH.mjs +8 -0
  4. package/dist/_dts/api/src/bookingConfig.d.ts +13 -1
  5. package/dist/_dts/api/src/bookingOperations.d.ts +1 -0
  6. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +6 -6
  7. package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +4 -4
  8. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +6 -0
  9. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +32 -0
  10. package/dist/_dts/blocks/src/system/blocks/courses/shared/pricing.d.ts +12 -1
  11. package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +12 -0
  12. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +4 -1
  13. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +44 -0
  14. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +24 -0
  15. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +8 -1
  16. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +8 -1
  17. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.d.ts +1 -0
  18. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +4 -0
  19. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +40 -0
  20. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.reserved-fields.d.ts +1 -1
  21. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +29 -0
  22. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +1 -0
  23. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/components.d.ts +6 -0
  24. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +8 -0
  25. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +8 -0
  26. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +1 -0
  27. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +1 -1
  28. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +1 -0
  29. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +9 -0
  30. package/dist/_dts/content-model/src/entry-slots/types.d.ts +110 -2
  31. package/dist/_dts/core/src/branded.d.ts +3 -0
  32. package/dist/_dts/core/src/event-pricing.d.ts +18 -1
  33. package/dist/_dts/core/src/money-input.d.ts +34 -4
  34. package/dist/_dts/core/src/string.d.ts +12 -0
  35. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +70 -0
  36. package/dist/_dts/media-core/src/fileAssetCompatibility.d.ts +1 -1
  37. package/dist/_dts/media-core/src/filePersistence.d.ts +5 -1
  38. package/dist/_dts/media-core/src/fileStorage.d.ts +1 -0
  39. package/dist/_dts/media-core/src/videoPrep.d.ts +15 -6
  40. package/dist/_dts/media-core/src/videoSlotPolicy.d.ts +5 -5
  41. package/dist/_dts/sdk/src/cli/commands/push/execute/diff.d.ts +2 -0
  42. package/dist/_dts/sdk/src/cli/commands/push/execute/localMediaReporting.d.ts +23 -0
  43. package/dist/_dts/sdk/src/cli/commands/push/scopes/commandBackedDatedOfferingScope.d.ts +54 -0
  44. package/dist/_dts/sdk/src/cli/commands/push/scopes/mediaPrep.d.ts +7 -2
  45. package/dist/_dts/sdk/src/cli/commands/push/scopes/types.d.ts +6 -0
  46. package/dist/_dts/sdk/src/cli/media/local-sync.d.ts +35 -0
  47. package/dist/_dts/sdk/src/cli/sync/validation.d.ts +2 -2
  48. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +23 -1
  49. package/dist/_dts/sdk/src/version.d.ts +1 -1
  50. package/dist/{chunk-SYYJZPKU.mjs → chunk-6D7PLF4M.mjs} +2 -2
  51. package/dist/{chunk-CR2VX432.mjs → chunk-I6EOKV6B.mjs} +568 -76
  52. package/dist/{chunk-FA6LVZ7C.mjs → chunk-LERKJM3E.mjs} +7 -7
  53. package/dist/{chunk-UG7I7S7W.mjs → chunk-U5YM4AWE.mjs} +1 -1
  54. package/dist/{chunk-H6TT5ZXI.mjs → chunk-UOMTCHZD.mjs} +1 -1
  55. package/dist/{chunk-BOQXMCSP.mjs → chunk-ZA2S7H34.mjs} +3 -3
  56. package/dist/cli/index.mjs +755 -414
  57. package/dist/cli/init-docs/content/workflow-add-block.md +48 -0
  58. package/dist/cli/init-docs/content/workflow-custom-block.md +10 -0
  59. package/dist/client/{accordion-4K7VGZ3I.mjs → accordion-BUDH2G3S.mjs} +2 -2
  60. package/dist/client/{bookingForm-3QXA3CIS.mjs → bookingForm-NQMCELVB.mjs} +90 -15
  61. package/dist/client/bookings.mjs +259 -32
  62. package/dist/client/{carousel-BEJKNGQ7.mjs → carousel-ONCEW6IJ.mjs} +3 -3
  63. package/dist/client/{cart-44BBM6XG.mjs → cart-V2TCK2GI.mjs} +7 -7
  64. package/dist/client/{checkout-THMHEYKF.mjs → checkout-ZI7SWNCS.mjs} +7 -7
  65. package/dist/client/{chunk-PEDNDLPB.mjs → chunk-AUMRQ242.mjs} +52 -5
  66. package/dist/client/{chunk-EJBHK74Y.mjs → chunk-B5UC2D6X.mjs} +7 -6
  67. package/dist/client/{chunk-DQIRKNZE.mjs → chunk-ERQDHUS2.mjs} +1 -1
  68. package/dist/client/{chunk-3H5CLFKT.mjs → chunk-GH6IIOOE.mjs} +39 -10
  69. package/dist/client/{chunk-ZIAF2DA4.mjs → chunk-HQWIJLYN.mjs} +1 -1
  70. package/dist/client/{chunk-4COPESPO.mjs → chunk-JXY6NHG6.mjs} +6 -6
  71. package/dist/client/{chunk-JV7ZNAOU.mjs → chunk-KXYEKEV6.mjs} +155 -17
  72. package/dist/client/{chunk-HIHOQGIP.mjs → chunk-LJCX6V7Q.mjs} +9 -9
  73. package/dist/client/{chunk-5AJIMWKS.mjs → chunk-N2WJPTF7.mjs} +3 -3
  74. package/dist/client/{chunk-KNTLBQ3N.mjs → chunk-QQNVQ62W.mjs} +1 -1
  75. package/dist/client/{chunk-B4H6QMPY.mjs → chunk-R3CZQLXF.mjs} +73 -8
  76. package/dist/client/{chunk-WHZQDPBZ.mjs → chunk-TNGL2WJF.mjs} +1 -0
  77. package/dist/client/{chunk-SLY6UDAS.mjs → chunk-ZJDBOLX7.mjs} +3 -3
  78. package/dist/client/client.mjs +548 -68
  79. package/dist/client/{courseRegistration-URX7RCCK.mjs → courseRegistration-JPWAQ6KM.mjs} +112 -12
  80. package/dist/client/{eventCalendar-GTENOQCE.mjs → eventCalendar-QDOCHBBV.mjs} +10 -10
  81. package/dist/client/{eventCombined-EZVB72MF.mjs → eventCombined-ZS2CXSIE.mjs} +10 -10
  82. package/dist/client/{eventDetails-CH4BJR5Z.mjs → eventDetails-5LOBMPLN.mjs} +10 -10
  83. package/dist/client/{eventListing-4BVOI5HS.mjs → eventListing-SBGY4I3L.mjs} +10 -10
  84. package/dist/client/{eventRegistration-37LPIKIE.mjs → eventRegistration-XGPIU3Z2.mjs} +10 -10
  85. package/dist/client/{form-FX3Y54YK.mjs → form-R7D4LZWW.mjs} +4 -4
  86. package/dist/client/{headerSection-UOZZGVYL.mjs → headerSection-RRLYUCGC.mjs} +3 -3
  87. package/dist/client/hooks.mjs +29 -9
  88. package/dist/client/{locationMap-VSIPKV35.mjs → locationMap-35ZJMRBZ.mjs} +3 -3
  89. package/dist/client/{newsletterForm-6FRJKNAF.mjs → newsletterForm-MJ2VCFUT.mjs} +4 -4
  90. package/dist/client/{productDetail-6AHMLXCO.mjs → productDetail-2O7YQNBX.mjs} +7 -7
  91. package/dist/client/{productList-M2CYIZVH.mjs → productList-FDP5BH7W.mjs} +7 -7
  92. package/dist/client/rendering/client.mjs +526 -64
  93. package/dist/client/rendering/islands.mjs +19 -19
  94. package/dist/client/rendering.mjs +547 -67
  95. package/dist/client/{shop-AUOT6GEX.mjs → shop-BGYJ3LDT.mjs} +7 -7
  96. package/dist/client/spam-protection.mjs +10 -10
  97. package/dist/preview-next/client/runtime.mjs +5 -5
  98. package/dist/{sdk-runtime-6GPJNLU6.mjs → sdk-runtime-B3TFXRXZ.mjs} +6 -6
  99. package/dist/server/components.mjs +179 -18
  100. package/dist/server/config-validation.mjs +30 -9
  101. package/dist/server/config.mjs +30 -9
  102. package/dist/server/data.mjs +29 -9
  103. package/dist/server/index.mjs +1 -1
  104. package/dist/server/navigation.mjs +2 -2
  105. package/dist/server/next.mjs +180 -19
  106. package/dist/server/page-converter.mjs +24 -7
  107. package/dist/server/prebuild.mjs +1 -1
  108. package/dist/server/rendering/server.mjs +179 -18
  109. package/dist/server/rendering.mjs +179 -18
  110. package/dist/server/routing.mjs +43 -19
  111. package/dist/server/server.mjs +30 -10
  112. package/package.json +1 -1
  113. package/dist/SdkPreviewModeRuntime-2UCIMKUB.mjs +0 -8
@@ -126,6 +126,8 @@ function err(error) {
126
126
 
127
127
  // ../core/src/branded.ts
128
128
  var unsafeAsMediaAssetId = (id) => id;
129
+ var unsafeAsStorageBucketName = (value) => value;
130
+ var unsafeAsStoragePath = (value) => value;
129
131
 
130
132
  // ../core/src/assert-never.ts
131
133
  function assertNever(value, message = "Unexpected variant") {
@@ -180,6 +182,7 @@ function publicEventPricingType(pricing) {
180
182
  return "free";
181
183
  case "single_paid":
182
184
  case "ticket_types":
185
+ case "sliding_scale":
183
186
  case "course":
184
187
  return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
185
188
  case "external":
@@ -192,6 +195,7 @@ function publicEventPricingCurrency(pricing) {
192
195
  case "free_registration":
193
196
  case "single_paid":
194
197
  case "ticket_types":
198
+ case "sliding_scale":
195
199
  return pricing.currency;
196
200
  case "course":
197
201
  return pricing.display.display.currency;
@@ -223,6 +227,8 @@ function formatCoursePriceDisplayLabel(display, options) {
223
227
  return `Course (${formatCurrencyAmount(display.amount, display.currency, options)})`;
224
228
  case "from":
225
229
  return `Course (From ${formatCurrencyAmount(display.amount, display.currency, options)})`;
230
+ case "range":
231
+ return `Course (${formatCurrencyAmount(display.minAmount, display.currency, options)} - ${formatCurrencyAmount(display.maxAmount, display.currency, options)})`;
226
232
  default:
227
233
  return assertNever(display);
228
234
  }
@@ -266,11 +272,11 @@ function isValidTimeZone(timeZone) {
266
272
  }
267
273
  function getSafeTimeZone(timeZone) {
268
274
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
269
- return normalized && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
275
+ return normalized.length > 0 && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
270
276
  }
271
277
  function parseStrictBookingTimeZone(timeZone) {
272
278
  const normalized = timeZone.trim();
273
- if (!normalized || !isValidTimeZone(normalized)) {
279
+ if (normalized.length === 0 || !isValidTimeZone(normalized)) {
274
280
  return null;
275
281
  }
276
282
  return normalized;
@@ -347,7 +353,7 @@ function parseScheduledBookingDateTime(input) {
347
353
  try {
348
354
  const startsAt = toUtcIsoDateTimeString(input.startsAt);
349
355
  const timeZone = parseStrictBookingTimeZone(input.timeZone);
350
- if (!timeZone) {
356
+ if (timeZone === null) {
351
357
  return {
352
358
  ok: false,
353
359
  field: "timeZone",
@@ -482,10 +488,10 @@ function normalizeLocationAddressText(value) {
482
488
  return null;
483
489
  }
484
490
  const trimmed = value.trim();
485
- return trimmed ? trimmed : null;
491
+ return trimmed.length > 0 ? trimmed : null;
486
492
  }
487
493
  function hasLocationCoordinates(value) {
488
- return typeof value?.lat === "number" && typeof value?.lng === "number";
494
+ return value != null && typeof value.lat === "number" && typeof value.lng === "number";
489
495
  }
490
496
  function toLocationCoordinates(value) {
491
497
  if (!hasLocationCoordinates(value)) {
@@ -514,6 +520,77 @@ function resolvePlanningDateInput(input = {}) {
514
520
  return resolvePlanningNowDate(input);
515
521
  }
516
522
 
523
+ // ../media-core/src/fileSafety.ts
524
+ var CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
525
+ function containsUnsafePathSegmentCharacter(value) {
526
+ return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
527
+ }
528
+ function isReservedPathSegment(value) {
529
+ return value === "." || value === "..";
530
+ }
531
+ function isUnsafePathSegment(segment) {
532
+ return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
533
+ }
534
+
535
+ // ../media-core/src/fileStorage.ts
536
+ var FILE_STORAGE_BUCKETS = {
537
+ publicSite: unsafeAsStorageBucketName("media"),
538
+ privateSite: unsafeAsStorageBucketName("site-files-private"),
539
+ temporary: unsafeAsStorageBucketName("temp-uploads")
540
+ };
541
+ var PUBLIC_SITE_FILE_STORAGE_BUCKETS = [
542
+ FILE_STORAGE_BUCKETS.publicSite,
543
+ // Existing site logo and font uploads predate the unified file buckets.
544
+ unsafeAsStorageBucketName("site-assets"),
545
+ unsafeAsStorageBucketName("site-fonts")
546
+ ];
547
+ var PRIVATE_SITE_FILE_BUCKET_MIME_TYPES = [
548
+ "application/pdf",
549
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
550
+ "text/plain",
551
+ "application/rtf",
552
+ "text/rtf",
553
+ "image/jpeg",
554
+ "image/png",
555
+ "image/webp",
556
+ "image/gif",
557
+ "image/avif",
558
+ "image/heic",
559
+ "image/heif",
560
+ "image/svg+xml",
561
+ "text/csv",
562
+ "application/csv",
563
+ "application/vnd.ms-excel",
564
+ "application/zip",
565
+ "application/x-zip-compressed",
566
+ "audio/mpeg",
567
+ "audio/mp4",
568
+ "audio/wav",
569
+ "audio/x-wav",
570
+ "audio/ogg",
571
+ "audio/webm",
572
+ "audio/flac",
573
+ "video/mp4",
574
+ "video/webm",
575
+ "video/quicktime"
576
+ ];
577
+ var TEMP_UPLOAD_BUCKET_MIME_TYPES = [
578
+ ...PRIVATE_SITE_FILE_BUCKET_MIME_TYPES,
579
+ "font/woff2",
580
+ "application/font-woff2",
581
+ "application/x-font-woff2",
582
+ "application/octet-stream"
583
+ ];
584
+ function parseStoragePath(value) {
585
+ return joinStoragePathSegments(value.split("/"));
586
+ }
587
+ function joinStoragePathSegments(segments) {
588
+ if (segments.some(isUnsafePathSegment)) {
589
+ return err("unsafe-path-segment");
590
+ }
591
+ return ok(unsafeAsStoragePath(segments.join("/")));
592
+ }
593
+
517
594
  // ../media-core/src/typeGuards.ts
518
595
  function isRecord(value) {
519
596
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -530,10 +607,10 @@ var RELATIVE_STORAGE_PATH_PREFIXES = [
530
607
  "imports/"
531
608
  ];
532
609
  function isRelativeDirectImageStoragePath(storagePath) {
533
- return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix));
610
+ return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix)) && parseStoragePath(storagePath).ok;
534
611
  }
535
612
  function isSiteScopedDirectImageStoragePath(storagePath) {
536
- return storagePath.startsWith("sites/");
613
+ return storagePath.startsWith("sites/") && parseStoragePath(storagePath).ok;
537
614
  }
538
615
  function encodeStoragePath(storagePath) {
539
616
  return storagePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
@@ -3006,6 +3083,21 @@ function fieldPlanToZod(plan, options = {}) {
3006
3083
  }
3007
3084
  });
3008
3085
  }
3086
+ function fieldPresenceForPlan(plan) {
3087
+ return plan.required ? { kind: "required" } : { kind: "optional" };
3088
+ }
3089
+ function fieldPlanToObjectPropertyZod(plan, options = {}) {
3090
+ const schema = fieldPlanToZod(plan, options);
3091
+ const presence = fieldPresenceForPlan(plan);
3092
+ switch (presence.kind) {
3093
+ case "required":
3094
+ return schema;
3095
+ case "optional":
3096
+ return schema.optional();
3097
+ default:
3098
+ return assertNever2(presence);
3099
+ }
3100
+ }
3009
3101
  function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
3010
3102
  const message = fieldIssueToMessage(validationIssue);
3011
3103
  const path = relativeZodIssuePath(validationIssue.path, rootPath);
@@ -3218,7 +3310,7 @@ function createManifestValidator(manifestOrFields, options = {}) {
3218
3310
  function deriveContentZodFromPlans(plans, options) {
3219
3311
  const shape = {};
3220
3312
  for (const plan of plans) {
3221
- shape[plan.fieldId] = fieldPlanToZod(plan, options);
3313
+ shape[plan.fieldId] = fieldPlanToObjectPropertyZod(plan, options);
3222
3314
  }
3223
3315
  return z5.object(shape).catchall(z5.unknown()).passthrough();
3224
3316
  }
@@ -26327,9 +26419,12 @@ var coursePricingOptionSchema = z43.object({
26327
26419
  });
26328
26420
  var coursePricingSchema = z43.object({
26329
26421
  bookingRequirement: z43.enum(["none", "required"]),
26330
- pricingStrategy: z43.enum(["free", "single", "tiered"]),
26422
+ pricingStrategy: z43.enum(["free", "single", "tiered", "sliding_scale"]),
26331
26423
  currency: z43.string(),
26332
26424
  singlePriceAmount: z43.number().nullable(),
26425
+ slidingMinAmount: z43.number().nullable().optional(),
26426
+ slidingMaxAmount: z43.number().nullable().optional(),
26427
+ slidingSuggestedAmount: z43.number().nullable().optional(),
26333
26428
  paymentTerms: blockBookingPaymentTermsSchema,
26334
26429
  options: z43.array(coursePricingOptionSchema)
26335
26430
  });
@@ -26483,6 +26578,19 @@ var publicEventPricingSchema = z44.discriminatedUnion("kind", [
26483
26578
  ticketTypes: z44.array(publicEventTicketTypeSchema),
26484
26579
  display: publicEventTicketTypePriceDisplaySchema
26485
26580
  }),
26581
+ z44.object({
26582
+ kind: z44.literal("sliding_scale"),
26583
+ minAmount: z44.number(),
26584
+ maxAmount: z44.number(),
26585
+ suggestedAmount: z44.number().nullable(),
26586
+ currency: z44.string(),
26587
+ display: z44.object({
26588
+ kind: z44.literal("range"),
26589
+ minAmount: z44.number(),
26590
+ maxAmount: z44.number(),
26591
+ currency: z44.string()
26592
+ })
26593
+ }),
26486
26594
  z44.object({
26487
26595
  kind: z44.literal("course"),
26488
26596
  display: z44.object({ kind: z44.literal("course"), display: publicCoursePriceDisplaySchema })
@@ -26899,7 +27007,7 @@ function isRecord6(value) {
26899
27007
  }
26900
27008
  function isPublicEventPricing(value) {
26901
27009
  if (!isRecord6(value) || typeof value.kind !== "string") return false;
26902
- return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
27010
+ return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "sliding_scale" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
26903
27011
  }
26904
27012
  function isPublicEventTicketType(value) {
26905
27013
  return isRecord6(value) && typeof value.id === "string";
@@ -27516,7 +27624,9 @@ function getSelectableCoursePricingOptionsForNow(course, now) {
27516
27624
  return left.name.localeCompare(right.name);
27517
27625
  });
27518
27626
  }
27519
- function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {}) {
27627
+ function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
27628
+ const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
27629
+ const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
27520
27630
  const currency = course.pricing?.currency ?? course.currency;
27521
27631
  if (!course.pricing) {
27522
27632
  const legacyAmount = course.priceCents ?? 0;
@@ -27526,6 +27636,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
27526
27636
  selectableOptions: [],
27527
27637
  requiresSelection: false,
27528
27638
  selectedOption: null,
27639
+ slidingScale: null,
27640
+ selectedSlidingAmount: null,
27529
27641
  selectedPriceAmount: legacyAmount,
27530
27642
  selectedRequiresPayment: legacyAmount > 0,
27531
27643
  hasPaidSelection: legacyAmount > 0,
@@ -27540,6 +27652,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
27540
27652
  selectableOptions: [],
27541
27653
  requiresSelection: false,
27542
27654
  selectedOption: null,
27655
+ slidingScale: null,
27656
+ selectedSlidingAmount: null,
27543
27657
  selectedPriceAmount: 0,
27544
27658
  selectedRequiresPayment: false,
27545
27659
  hasPaidSelection: false,
@@ -27553,6 +27667,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
27553
27667
  selectableOptions: [],
27554
27668
  requiresSelection: false,
27555
27669
  selectedOption: null,
27670
+ slidingScale: null,
27671
+ selectedSlidingAmount: null,
27556
27672
  selectedPriceAmount: amount,
27557
27673
  selectedRequiresPayment: amount > 0,
27558
27674
  hasPaidSelection: amount > 0,
@@ -27562,7 +27678,7 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
27562
27678
  case "tiered": {
27563
27679
  const selectableOptions = getSelectableCoursePricingOptionsForNow(
27564
27680
  course,
27565
- resolvePlanningDateInput(nowInput)
27681
+ resolvePlanningDateInput(effectiveNowInput)
27566
27682
  );
27567
27683
  const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
27568
27684
  const lowestAmount = selectableOptions.reduce((lowest, option) => {
@@ -27578,12 +27694,51 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
27578
27694
  selectableOptions,
27579
27695
  requiresSelection: selectableOptions.length > 1,
27580
27696
  selectedOption,
27697
+ slidingScale: null,
27698
+ selectedSlidingAmount: null,
27581
27699
  selectedPriceAmount: selectedOption?.priceAmount ?? null,
27582
27700
  selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
27583
27701
  hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
27584
27702
  hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
27585
27703
  };
27586
27704
  }
27705
+ case "sliding_scale": {
27706
+ const minAmount = course.pricing.slidingMinAmount ?? null;
27707
+ const maxAmount = course.pricing.slidingMaxAmount ?? null;
27708
+ if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) {
27709
+ return {
27710
+ currency,
27711
+ display: { kind: "unavailable", currency },
27712
+ selectableOptions: [],
27713
+ requiresSelection: true,
27714
+ selectedOption: null,
27715
+ slidingScale: null,
27716
+ selectedSlidingAmount: null,
27717
+ selectedPriceAmount: null,
27718
+ selectedRequiresPayment: false,
27719
+ hasPaidSelection: false,
27720
+ hasFreeSelection: false
27721
+ };
27722
+ }
27723
+ const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
27724
+ return {
27725
+ currency,
27726
+ display: { kind: "range", minAmount, maxAmount, currency },
27727
+ selectableOptions: [],
27728
+ requiresSelection: normalizedSelectedAmount === null,
27729
+ selectedOption: null,
27730
+ slidingScale: {
27731
+ minAmount,
27732
+ maxAmount,
27733
+ suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
27734
+ },
27735
+ selectedSlidingAmount: normalizedSelectedAmount,
27736
+ selectedPriceAmount: normalizedSelectedAmount,
27737
+ selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
27738
+ hasPaidSelection: maxAmount > 0,
27739
+ hasFreeSelection: minAmount === 0
27740
+ };
27741
+ }
27587
27742
  }
27588
27743
  }
27589
27744
  function formatCoursePriceDisplay(display, locale) {
@@ -28510,7 +28665,7 @@ function formatCalendarTitle(viewDate, view, days, monthNames = MONTH_NAMES) {
28510
28665
  if (view === "week") {
28511
28666
  const weekStart = days[0];
28512
28667
  const weekEnd = days[6];
28513
- if (!weekStart || !weekEnd) {
28668
+ if (weekStart === void 0 || weekEnd === void 0) {
28514
28669
  return `${monthNames[viewDate.getMonth()] ?? ""} ${viewDate.getFullYear()}`;
28515
28670
  }
28516
28671
  const startMonth = monthNames[weekStart.getMonth()] ?? "";
@@ -28616,7 +28771,9 @@ function getLocalDateKey(isoTimestamp, timeZone) {
28616
28771
  const year = parts.find((part) => part.type === "year")?.value;
28617
28772
  const month = parts.find((part) => part.type === "month")?.value;
28618
28773
  const day = parts.find((part) => part.type === "day")?.value;
28619
- if (!year || !month || !day) return null;
28774
+ if (year === void 0 || year.length === 0) return null;
28775
+ if (month === void 0 || month.length === 0) return null;
28776
+ if (day === void 0 || day.length === 0) return null;
28620
28777
  return `${year}-${month}-${day}`;
28621
28778
  }
28622
28779
  var validTimeZoneCache = /* @__PURE__ */ new Map();
@@ -28873,7 +29030,7 @@ function enumerateDateKeys(startDateKey, endDateKey) {
28873
29030
  }
28874
29031
  function parseDateKey(dateKey) {
28875
29032
  const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(dateKey);
28876
- if (!match) {
29033
+ if (match === null) {
28877
29034
  throw new Error(`Invalid timetable date key: ${dateKey}`);
28878
29035
  }
28879
29036
  const [, year, month, day] = match;
@@ -28893,7 +29050,7 @@ function groupItemsByDate(items, accessors) {
28893
29050
  const dateKey = getLocalDateKey(startsAt, timeZone);
28894
29051
  if (dateKey == null) continue;
28895
29052
  const existing = grouped.get(dateKey);
28896
- if (existing) {
29053
+ if (existing !== void 0) {
28897
29054
  existing.push(item);
28898
29055
  } else {
28899
29056
  grouped.set(dateKey, [item]);
@@ -37992,11 +38149,11 @@ function extractRouteUpdatedAt(candidate) {
37992
38149
  }
37993
38150
  function resolveRouteTargetForStage(routeIdValue, routes, stageInput) {
37994
38151
  const routeId = typeof routeIdValue === "string" ? routeIdValue : null;
37995
- if (!routeId || !routes) return null;
38152
+ if (routeId === null || routeId.length === 0 || routes === void 0) return null;
37996
38153
  const routeEntry = routes[routeId];
37997
38154
  if (!isRouteVisibleInStage(routeEntry, stageInput)) return null;
37998
38155
  const href = extractRouteHref(routeEntry, stageInput);
37999
- if (!href) return null;
38156
+ if (href === null) return null;
38000
38157
  return {
38001
38158
  routeId,
38002
38159
  href,
@@ -40067,6 +40224,7 @@ var bookingServiceSchema = z64.object({
40067
40224
  title: z64.string(),
40068
40225
  description: z64.string().nullable().optional().transform((value) => value ?? void 0),
40069
40226
  durationMinutes: z64.number().optional(),
40227
+ pricing: z64.custom().optional(),
40070
40228
  priceAmount: z64.number().nullable().optional(),
40071
40229
  priceCurrency: z64.string().nullable().optional(),
40072
40230
  paymentTerms: blockBookingPaymentTermsSchema.optional(),
@@ -68223,6 +68381,7 @@ var CANONICAL_REFUND_CONFLICT_CODES = [
68223
68381
  ];
68224
68382
  var CANONICAL_REFUND_PLANNER_ERROR_CODES = [
68225
68383
  ...CANONICAL_REFUND_CONFLICT_CODES,
68384
+ "invalid_amount",
68226
68385
  "amount_exceeds_remaining",
68227
68386
  "pass_revoke_requires_full_refund",
68228
68387
  "refund_failed"
@@ -68249,6 +68408,7 @@ var CUSTOMER_MEMBERSHIP_PAYMENT_REFUND_FAILED_CODES = [
68249
68408
  // ../api/src/bookingRefundOutcomes.ts
68250
68409
  var STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
68251
68410
  "missing_amount",
68411
+ "invalid_amount",
68252
68412
  "amount_exceeds_remaining",
68253
68413
  "credit_refunds_disabled",
68254
68414
  "missing_credit_customer",
@@ -68263,6 +68423,7 @@ var EVENT_ATTENDEE_REFUND_INVALID_CODES = [
68263
68423
  var MANAGED_PRODUCT_REFUND_INVALID_CODES = [
68264
68424
  "credit_refunds_disabled",
68265
68425
  "not_refundable",
68426
+ "invalid_amount",
68266
68427
  "amount_exceeds_remaining"
68267
68428
  ];
68268
68429
  var CUSTOMER_PASS_REFUND_INVALID_CODES = [
@@ -6607,6 +6607,7 @@ function publicEventPricingType(pricing) {
6607
6607
  return "free";
6608
6608
  case "single_paid":
6609
6609
  case "ticket_types":
6610
+ case "sliding_scale":
6610
6611
  case "course":
6611
6612
  return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
6612
6613
  case "external":
@@ -6673,11 +6674,11 @@ function isValidTimeZone(timeZone) {
6673
6674
  }
6674
6675
  function getSafeTimeZone(timeZone) {
6675
6676
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
6676
- return normalized && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
6677
+ return normalized.length > 0 && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
6677
6678
  }
6678
6679
  function parseStrictBookingTimeZone(timeZone) {
6679
6680
  const normalized = timeZone.trim();
6680
- if (!normalized || !isValidTimeZone(normalized)) {
6681
+ if (normalized.length === 0 || !isValidTimeZone(normalized)) {
6681
6682
  return null;
6682
6683
  }
6683
6684
  return normalized;
@@ -6751,7 +6752,7 @@ function parseScheduledBookingDateTime(input) {
6751
6752
  try {
6752
6753
  const startsAt = toUtcIsoDateTimeString(input.startsAt);
6753
6754
  const timeZone = parseStrictBookingTimeZone(input.timeZone);
6754
- if (!timeZone) {
6755
+ if (timeZone === null) {
6755
6756
  return {
6756
6757
  ok: false,
6757
6758
  field: "timeZone",
@@ -6820,10 +6821,10 @@ function normalizeLocationAddressText(value) {
6820
6821
  return null;
6821
6822
  }
6822
6823
  const trimmed = value.trim();
6823
- return trimmed ? trimmed : null;
6824
+ return trimmed.length > 0 ? trimmed : null;
6824
6825
  }
6825
6826
  function hasLocationCoordinates(value) {
6826
- return typeof value?.lat === "number" && typeof value?.lng === "number";
6827
+ return value != null && typeof value.lat === "number" && typeof value.lng === "number";
6827
6828
  }
6828
6829
  function toLocationCoordinates(value) {
6829
6830
  if (!hasLocationCoordinates(value)) {
@@ -6840,6 +6841,13 @@ var init_location = __esm({
6840
6841
  }
6841
6842
  });
6842
6843
 
6844
+ // ../core/src/string.ts
6845
+ var init_string = __esm({
6846
+ "../core/src/string.ts"() {
6847
+ "use strict";
6848
+ }
6849
+ });
6850
+
6843
6851
  // ../core/src/business-address.ts
6844
6852
  var init_business_address = __esm({
6845
6853
  "../core/src/business-address.ts"() {
@@ -6980,13 +6988,6 @@ var init_slug = __esm({
6980
6988
  }
6981
6989
  });
6982
6990
 
6983
- // ../core/src/string.ts
6984
- var init_string = __esm({
6985
- "../core/src/string.ts"() {
6986
- "use strict";
6987
- }
6988
- });
6989
-
6990
6991
  // ../core/src/uuid.ts
6991
6992
  var init_uuid = __esm({
6992
6993
  "../core/src/uuid.ts"() {
@@ -7543,14 +7544,18 @@ var init_uploadVerificationContract = __esm({
7543
7544
  });
7544
7545
 
7545
7546
  // ../media-core/src/videoPrep.ts
7547
+ function unsafeAsPositiveVideoDurationSeconds(value) {
7548
+ return value;
7549
+ }
7546
7550
  var VIDEO_PREP_LIMITS;
7547
7551
  var init_videoPrep = __esm({
7548
7552
  "../media-core/src/videoPrep.ts"() {
7549
7553
  "use strict";
7554
+ init_src();
7550
7555
  VIDEO_PREP_LIMITS = {
7551
- maxRawByteCount: 500 * 1024 * 1024,
7552
- inlineContentMaxDurationSeconds: 60,
7553
- backgroundVideoMaxDurationSeconds: 30,
7556
+ maxRawByteCount: unsafeAsPositiveByteCount(500 * 1024 * 1024),
7557
+ inlineContentMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(60),
7558
+ backgroundVideoMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(30),
7554
7559
  targetMaxDimensionPixels: 1080
7555
7560
  };
7556
7561
  }
@@ -32466,9 +32471,12 @@ var init_schemas = __esm({
32466
32471
  });
32467
32472
  coursePricingSchema = z45.object({
32468
32473
  bookingRequirement: z45.enum(["none", "required"]),
32469
- pricingStrategy: z45.enum(["free", "single", "tiered"]),
32474
+ pricingStrategy: z45.enum(["free", "single", "tiered", "sliding_scale"]),
32470
32475
  currency: z45.string(),
32471
32476
  singlePriceAmount: z45.number().nullable(),
32477
+ slidingMinAmount: z45.number().nullable().optional(),
32478
+ slidingMaxAmount: z45.number().nullable().optional(),
32479
+ slidingSuggestedAmount: z45.number().nullable().optional(),
32472
32480
  paymentTerms: blockBookingPaymentTermsSchema,
32473
32481
  options: z45.array(coursePricingOptionSchema)
32474
32482
  });
@@ -32633,6 +32641,19 @@ var init_schemas2 = __esm({
32633
32641
  ticketTypes: z46.array(publicEventTicketTypeSchema),
32634
32642
  display: publicEventTicketTypePriceDisplaySchema
32635
32643
  }),
32644
+ z46.object({
32645
+ kind: z46.literal("sliding_scale"),
32646
+ minAmount: z46.number(),
32647
+ maxAmount: z46.number(),
32648
+ suggestedAmount: z46.number().nullable(),
32649
+ currency: z46.string(),
32650
+ display: z46.object({
32651
+ kind: z46.literal("range"),
32652
+ minAmount: z46.number(),
32653
+ maxAmount: z46.number(),
32654
+ currency: z46.string()
32655
+ })
32656
+ }),
32636
32657
  z46.object({
32637
32658
  kind: z46.literal("course"),
32638
32659
  display: z46.object({ kind: z46.literal("course"), display: publicCoursePriceDisplaySchema })
@@ -33101,7 +33122,7 @@ function isRecord4(value) {
33101
33122
  }
33102
33123
  function isPublicEventPricing(value) {
33103
33124
  if (!isRecord4(value) || typeof value.kind !== "string") return false;
33104
- return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
33125
+ return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "sliding_scale" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
33105
33126
  }
33106
33127
  function isPublicEventTicketType(value) {
33107
33128
  return isRecord4(value) && typeof value.id === "string";
@@ -42214,11 +42235,11 @@ function extractRouteUpdatedAt(candidate) {
42214
42235
  }
42215
42236
  function resolveRouteTargetForStage(routeIdValue, routes, stageInput) {
42216
42237
  const routeId = typeof routeIdValue === "string" ? routeIdValue : null;
42217
- if (!routeId || !routes) return null;
42238
+ if (routeId === null || routeId.length === 0 || routes === void 0) return null;
42218
42239
  const routeEntry = routes[routeId];
42219
42240
  if (!isRouteVisibleInStage(routeEntry, stageInput)) return null;
42220
42241
  const href = extractRouteHref(routeEntry, stageInput);
42221
- if (!href) return null;
42242
+ if (href === null) return null;
42222
42243
  return {
42223
42244
  routeId,
42224
42245
  href,
@@ -45440,6 +45461,7 @@ var init_customerMembershipOutcomes = __esm({
45440
45461
  ];
45441
45462
  CANONICAL_REFUND_PLANNER_ERROR_CODES = [
45442
45463
  ...CANONICAL_REFUND_CONFLICT_CODES,
45464
+ "invalid_amount",
45443
45465
  "amount_exceeds_remaining",
45444
45466
  "pass_revoke_requires_full_refund",
45445
45467
  "refund_failed"
@@ -45473,6 +45495,7 @@ var init_bookingRefundOutcomes = __esm({
45473
45495
  init_customerMembershipOutcomes();
45474
45496
  STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
45475
45497
  "missing_amount",
45498
+ "invalid_amount",
45476
45499
  "amount_exceeds_remaining",
45477
45500
  "credit_refunds_disabled",
45478
45501
  "missing_credit_customer",
@@ -45487,6 +45510,7 @@ var init_bookingRefundOutcomes = __esm({
45487
45510
  MANAGED_PRODUCT_REFUND_INVALID_CODES = [
45488
45511
  "credit_refunds_disabled",
45489
45512
  "not_refundable",
45513
+ "invalid_amount",
45490
45514
  "amount_exceeds_remaining"
45491
45515
  ];
45492
45516
  CUSTOMER_PASS_REFUND_INVALID_CODES = [