@riverbankcms/sdk 0.84.2 → 0.88.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 (143) hide show
  1. package/dist/{PreviewEditorSidebar-4PH35ZIE.mjs → PreviewEditorSidebar-EVRS3C7T.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-WHMCRJGM.mjs → PreviewEditorUI-54WD4IGE.mjs} +3 -3
  3. package/dist/SdkPreviewModeRuntime-ZALZDJEK.mjs +8 -0
  4. package/dist/_dts/ai/src/contracts/proposals.d.ts +684 -0
  5. package/dist/_dts/api/src/endpoints.d.ts +58 -14
  6. package/dist/_dts/api/src/index.d.ts +4 -1
  7. package/dist/_dts/api/src/launchReadiness.d.ts +3 -3
  8. package/dist/_dts/api/src/mailchimpIntegration.d.ts +215 -0
  9. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +35 -15
  10. package/dist/_dts/api/src/siteInfrastructure.d.ts +0 -14
  11. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +1 -13
  12. package/dist/_dts/api/src/types.d.ts +6 -3
  13. package/dist/_dts/blocks/src/PageRenderer.d.ts +1 -0
  14. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -0
  15. package/dist/_dts/blocks/src/index.d.ts +2 -1
  16. package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +288 -288
  17. package/dist/_dts/blocks/src/system/blocks/blog-listing.d.ts +288 -288
  18. package/dist/_dts/blocks/src/system/blocks/cart.d.ts +288 -288
  19. package/dist/_dts/blocks/src/system/blocks/checkout.d.ts +288 -288
  20. package/dist/_dts/blocks/src/system/blocks/collection.d.ts +288 -288
  21. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +42 -0
  22. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +4 -0
  23. package/dist/_dts/blocks/src/system/blocks/faq.d.ts +288 -288
  24. package/dist/_dts/blocks/src/system/blocks/gifting.d.ts +288 -288
  25. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +1 -1
  26. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +42 -42
  27. package/dist/_dts/blocks/src/system/blocks/newsletter-signup-destination.d.ts +300 -0
  28. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +63 -3
  29. package/dist/_dts/blocks/src/system/blocks/product-detail.d.ts +288 -288
  30. package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +288 -288
  31. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +288 -288
  32. package/dist/_dts/blocks/src/system/fragments/library/newsletterForm.d.ts +53 -1
  33. package/dist/_dts/blocks/src/system/manifest/richTextSchema.d.ts +27 -0
  34. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +23 -23
  35. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +10 -2
  36. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +24 -0
  37. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +12 -0
  38. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +1 -0
  39. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +4 -0
  40. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +1 -1
  41. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/utils.d.ts +11 -1
  42. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +15 -0
  43. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.server.d.ts +1 -1
  44. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.submission.d.ts +32 -0
  45. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +5 -1
  46. package/dist/_dts/blocks/src/system/runtime/shared/components/ModalShell.d.ts +5 -1
  47. package/dist/_dts/blocks/src/system/runtime/shared/utils/formatting.d.ts +1 -1
  48. package/dist/_dts/content-model/src/referenceFields.d.ts +1 -1
  49. package/dist/_dts/core/src/currency-format.d.ts +37 -2
  50. package/dist/_dts/core/src/event-pricing.d.ts +24 -0
  51. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +551 -20
  52. package/dist/_dts/editor-blocks/src/widgets/reference/loaders.d.ts +3 -1
  53. package/dist/_dts/sdk/src/cli/canonical-entry-policy.d.ts +53 -0
  54. package/dist/_dts/sdk/src/cli/commands/migrate.d.ts +1 -0
  55. package/dist/_dts/sdk/src/cli/commands/pull.d.ts +7 -1
  56. package/dist/_dts/sdk/src/cli/content/reader.d.ts +2 -0
  57. package/dist/_dts/sdk/src/cli/migrations/events.d.ts +73 -0
  58. package/dist/_dts/sdk/src/client/types.d.ts +9 -0
  59. package/dist/_dts/sdk/src/config/validation.d.ts +3 -0
  60. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +3 -0
  61. package/dist/_dts/sdk/src/data/prefetchBlockData.d.ts +3 -9
  62. package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +1 -1
  63. package/dist/_dts/sdk/src/manifest/three-pass-converter.d.ts +7 -18
  64. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -0
  65. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +3 -1
  66. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +7 -3
  67. package/dist/_dts/sdk/src/rendering/helpers/loadPage.d.ts +4 -24
  68. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +45 -0
  69. package/dist/_dts/sdk/src/version.d.ts +1 -1
  70. package/dist/_dts/site-commands/src/commands.d.ts +57 -0
  71. package/dist/_dts/surfaces/src/index.d.ts +12 -0
  72. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  73. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +9 -9
  74. package/dist/_dts/theme-core/src/schema.d.ts +11 -11
  75. package/dist/{chunk-ZR2GQK2A.mjs → chunk-7KOO7RPP.mjs} +953 -315
  76. package/dist/{chunk-OCGTXHSO.mjs → chunk-ER4UIW4X.mjs} +7 -7
  77. package/dist/{chunk-WFPYN7KA.mjs → chunk-HVOBXA3Y.mjs} +2 -2
  78. package/dist/{chunk-NFWGLRZZ.mjs → chunk-K3JWH6HE.mjs} +37 -3
  79. package/dist/{chunk-4QNLOTES.mjs → chunk-O4LVYUVH.mjs} +58 -14
  80. package/dist/{chunk-PYDHOMEO.mjs → chunk-YDMBIIS5.mjs} +1 -1
  81. package/dist/cli/index.mjs +1858 -512
  82. package/dist/client/{accordion-2UZPBMYM.mjs → accordion-PT5CGW5N.mjs} +2 -2
  83. package/dist/client/{bookingForm-36CWQUMV.mjs → bookingForm-2HLRTEYS.mjs} +7 -7
  84. package/dist/client/bookings.mjs +51 -6
  85. package/dist/client/{carousel-QH77HR6X.mjs → carousel-Z2LKYSWA.mjs} +3 -3
  86. package/dist/client/cart-ND5IK4A6.mjs +18 -0
  87. package/dist/client/checkout-EYUSGAY7.mjs +18 -0
  88. package/dist/client/{chunk-SYIJ5JO2.mjs → chunk-6DVPO44G.mjs} +1 -1
  89. package/dist/client/{chunk-3C2VTPWI.mjs → chunk-BAWHZ5GM.mjs} +176 -13
  90. package/dist/client/{chunk-52CGCQ7B.mjs → chunk-BL66UWGD.mjs} +10 -80
  91. package/dist/client/{chunk-VGDBVNOO.mjs → chunk-DIRW2LNG.mjs} +241 -210
  92. package/dist/client/{chunk-UDNSI5PY.mjs → chunk-GOFO7HRH.mjs} +1 -2
  93. package/dist/client/{chunk-ZKUO52W3.mjs → chunk-H4MHEXYS.mjs} +1 -1
  94. package/dist/client/{chunk-ZE5G642V.mjs → chunk-LI2C6M5O.mjs} +75 -1
  95. package/dist/client/{chunk-3DTWLTXM.mjs → chunk-MHBEWDT7.mjs} +117 -3
  96. package/dist/client/{chunk-4OXKTA3D.mjs → chunk-O5JNI3E4.mjs} +2 -2
  97. package/dist/client/{chunk-XSV6KW4D.mjs → chunk-S4G65LGR.mjs} +1 -1
  98. package/dist/client/{chunk-DVNUDUVT.mjs → chunk-WBQG7VJA.mjs} +4 -1
  99. package/dist/client/{chunk-F5VRX5Y6.mjs → chunk-WCVK4MBJ.mjs} +1 -1
  100. package/dist/client/{chunk-7UCLJ5SP.mjs → chunk-X7GVFB7Y.mjs} +4 -7
  101. package/dist/client/client.mjs +2125 -1403
  102. package/dist/client/{courseRegistration-TMKU6ABO.mjs → courseRegistration-H3AZBUEG.mjs} +7 -7
  103. package/dist/client/{eventCalendar-G6TI32X6.mjs → eventCalendar-FPKJGLGS.mjs} +10 -11
  104. package/dist/client/{eventCombined-SCKEMNAR.mjs → eventCombined-QCGIZBUY.mjs} +10 -11
  105. package/dist/client/{eventDetails-XPIFXXPK.mjs → eventDetails-HIT3BJWU.mjs} +10 -11
  106. package/dist/client/{eventListing-7QFMEMGT.mjs → eventListing-R4HNWJDN.mjs} +10 -11
  107. package/dist/client/{eventRegistration-TOODSZUI.mjs → eventRegistration-Q7BYY5HF.mjs} +10 -11
  108. package/dist/client/{form-MTCMVCZT.mjs → form-NI6YOG6S.mjs} +3 -3
  109. package/dist/client/{headerSection-Y5TMR3TW.mjs → headerSection-SDYGII36.mjs} +4 -4
  110. package/dist/client/hooks.mjs +1682 -1412
  111. package/dist/client/{locationMap-RH2LG7FZ.mjs → locationMap-BDETEUQD.mjs} +3 -4
  112. package/dist/client/{newsletterForm-PCAIPFMA.mjs → newsletterForm-EKYIU67X.mjs} +70 -22
  113. package/dist/client/{productDetail-OIGDR4YE.mjs → productDetail-5UTGNN76.mjs} +8 -9
  114. package/dist/client/{productList-4MA5S2CX.mjs → productList-7YA5KXZQ.mjs} +8 -9
  115. package/dist/client/rendering/client.mjs +753 -329
  116. package/dist/client/rendering/islands.mjs +19 -19
  117. package/dist/client/rendering.mjs +3786 -3034
  118. package/dist/client/shop-AIMUMZYC.mjs +20 -0
  119. package/dist/preview-next/before-render.mjs +58 -14
  120. package/dist/preview-next/client/runtime.mjs +5 -5
  121. package/dist/preview-next/editor-chrome.css +56 -9
  122. package/dist/preview-next/middleware.mjs +58 -14
  123. package/dist/{sdk-runtime-QLOCYKVU.mjs → sdk-runtime-NW472WNT.mjs} +6 -6
  124. package/dist/server/components.mjs +1518 -1015
  125. package/dist/server/config-validation.mjs +1719 -1461
  126. package/dist/server/config.mjs +1719 -1461
  127. package/dist/server/data.mjs +1683 -1413
  128. package/dist/server/index.mjs +79 -17
  129. package/dist/server/next.mjs +1902 -1311
  130. package/dist/server/page-converter.mjs +2193 -1169
  131. package/dist/server/prebuild.mjs +1 -1
  132. package/dist/server/rendering/server.mjs +1709 -1209
  133. package/dist/server/rendering.mjs +1894 -1347
  134. package/dist/server/routing.mjs +1872 -1499
  135. package/dist/server/server.mjs +1571 -1264
  136. package/dist/server/theme-bridge.mjs +234 -0
  137. package/dist/styles/index.css +232 -0
  138. package/package.json +1 -1
  139. package/dist/SdkPreviewModeRuntime-4FGSVUYI.mjs +0 -8
  140. package/dist/client/cart-X4YK4FTW.mjs +0 -19
  141. package/dist/client/checkout-OM2BEPWD.mjs +0 -19
  142. package/dist/client/chunk-I2MMZO53.mjs +0 -6
  143. package/dist/client/shop-WXSYV5QO.mjs +0 -21
@@ -2,7 +2,7 @@
2
2
  import z42, { z, ZodError } from 'zod';
3
3
  import 'react/jsx-runtime';
4
4
  import { createJiti } from 'jiti';
5
- import * as fs10 from 'fs';
5
+ import * as fs11 from 'fs';
6
6
  import { existsSync, readFileSync } from 'fs';
7
7
  import * as path5 from 'path';
8
8
  import { dirname, resolve, isAbsolute } from 'path';
@@ -109,6 +109,57 @@ var init_collections = __esm({
109
109
  }
110
110
  });
111
111
 
112
+ // ../core/src/assert-never.ts
113
+ function assertNever(value, message = "Unexpected variant") {
114
+ throw new Error(`${message}: ${String(value)}`);
115
+ }
116
+ var init_assert_never = __esm({
117
+ "../core/src/assert-never.ts"() {
118
+ }
119
+ });
120
+
121
+ // ../core/src/currency-format.ts
122
+ function resolveCurrencyLocale(currencyCode, override) {
123
+ return CURRENCY_LOCALE_BY_CODE[currencyCode] ?? "en";
124
+ }
125
+ function formatCurrencyAmount(amountCents, currency, options) {
126
+ const currencyCode = currency.toUpperCase();
127
+ const locale = resolveCurrencyLocale(currencyCode);
128
+ try {
129
+ const exactFormatter = new Intl.NumberFormat(locale, {
130
+ style: "currency",
131
+ currency: currencyCode
132
+ });
133
+ const fractionDigits = options?.decimals === "auto" ? {
134
+ minimumFractionDigits: 0,
135
+ maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
136
+ } : {};
137
+ return new Intl.NumberFormat(locale, {
138
+ style: "currency",
139
+ currency: currencyCode,
140
+ ...fractionDigits
141
+ }).format(amountCents / 100);
142
+ } catch {
143
+ return `${(amountCents / 100).toFixed(2)} ${currencyCode}`;
144
+ }
145
+ }
146
+ var CURRENCY_LOCALE_BY_CODE;
147
+ var init_currency_format = __esm({
148
+ "../core/src/currency-format.ts"() {
149
+ CURRENCY_LOCALE_BY_CODE = {
150
+ USD: "en-US",
151
+ GBP: "en-GB",
152
+ EUR: "de-DE",
153
+ AUD: "en-AU",
154
+ CAD: "en-CA",
155
+ NZD: "en-NZ",
156
+ JPY: "ja-JP",
157
+ CNY: "zh-CN",
158
+ CHF: "de-CH"
159
+ };
160
+ }
161
+ });
162
+
112
163
  // ../core/src/event-pricing.ts
113
164
  function publicEventPricingType(pricing) {
114
165
  switch (pricing.kind) {
@@ -129,6 +180,7 @@ function isFreePublicEventPriceDisplay(display) {
129
180
  return display.display.kind === "free";
130
181
  case "exact":
131
182
  case "from":
183
+ case "range":
132
184
  case "mixed":
133
185
  case "unavailable":
134
186
  return false;
@@ -343,15 +395,6 @@ var init_business_address = __esm({
343
395
  }
344
396
  });
345
397
 
346
- // ../core/src/assert-never.ts
347
- function assertNever(value, message = "Unexpected variant") {
348
- throw new Error(`${message}: ${String(value)}`);
349
- }
350
- var init_assert_never = __esm({
351
- "../core/src/assert-never.ts"() {
352
- }
353
- });
354
-
355
398
  // ../core/src/narrow-result.ts
356
399
  var init_narrow_result = __esm({
357
400
  "../core/src/narrow-result.ts"() {
@@ -454,12 +497,6 @@ var init_csv_types = __esm({
454
497
  }
455
498
  });
456
499
 
457
- // ../core/src/currency-format.ts
458
- var init_currency_format = __esm({
459
- "../core/src/currency-format.ts"() {
460
- }
461
- });
462
-
463
500
  // ../core/src/email-format.ts
464
501
  var init_email_format = __esm({
465
502
  "../core/src/email-format.ts"() {
@@ -12490,8 +12527,8 @@ var init_generatedDesignPipeline = __esm({
12490
12527
  }
12491
12528
  });
12492
12529
  function validateBlockSequence(snapshots, ctx) {
12493
- for (const issue4 of collectBlockSequenceIssues(snapshots)) {
12494
- ctx.addIssue(issue4);
12530
+ for (const issue5 of collectBlockSequenceIssues(snapshots)) {
12531
+ ctx.addIssue(issue5);
12495
12532
  }
12496
12533
  }
12497
12534
  function collectBlockSequenceIssues(snapshots) {
@@ -13344,11 +13381,11 @@ function bind(from, options) {
13344
13381
  }
13345
13382
  });
13346
13383
  }
13347
- function when(path25, options) {
13384
+ function when(path27, options) {
13348
13385
  return (node) => ({
13349
13386
  ...node,
13350
13387
  $when: {
13351
- when: { from: path25 },
13388
+ when: { from: path27 },
13352
13389
  ...options?.equals !== void 0 ? { equals: options.equals } : {},
13353
13390
  ...options?.not ? { not: true } : {}
13354
13391
  }
@@ -13455,7 +13492,7 @@ var init_builder2 = __esm({
13455
13492
  });
13456
13493
 
13457
13494
  // ../blocks/src/system/node/fragments/backgroundLayer.ts
13458
- function backgroundLayer(path25, options = {}) {
13495
+ function backgroundLayer(path27, options = {}) {
13459
13496
  const {
13460
13497
  styleClassName = "background-style rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full rb-w-full rb-pointer-events-none",
13461
13498
  imageClassName,
@@ -13469,7 +13506,7 @@ function backgroundLayer(path25, options = {}) {
13469
13506
  className: styleClassName,
13470
13507
  style: {
13471
13508
  $bind: {
13472
- from: path25,
13509
+ from: path27,
13473
13510
  transforms: [
13474
13511
  {
13475
13512
  id: "background.resolveStyle",
@@ -13479,20 +13516,20 @@ function backgroundLayer(path25, options = {}) {
13479
13516
  }
13480
13517
  }
13481
13518
  });
13482
- const imageLayer = createBackgroundImageNode(path25, imageClassName, {
13519
+ const imageLayer = createBackgroundImageNode(path27, imageClassName, {
13483
13520
  loading: imageLoading,
13484
13521
  fetchPriority: imageFetchPriority
13485
13522
  });
13486
- const overlayLayer = createBackgroundOverlayNode(path25, overlayClassName);
13523
+ const overlayLayer = createBackgroundOverlayNode(path27, overlayClassName);
13487
13524
  return omitImageLayer ? [styleLayer, overlayLayer] : [styleLayer, imageLayer, overlayLayer];
13488
13525
  }
13489
- function createBackgroundImageNode(path25, baseClassName = "rb-absolute rb-z-neg-10", options = {}) {
13490
- const imagePath = `${path25}.image`;
13526
+ function createBackgroundImageNode(path27, baseClassName = "rb-absolute rb-z-neg-10", options = {}) {
13527
+ const imagePath = `${path27}.image`;
13491
13528
  return media(
13492
13529
  {
13493
13530
  className: {
13494
13531
  $bind: {
13495
- from: path25,
13532
+ from: path27,
13496
13533
  transforms: [
13497
13534
  {
13498
13535
  id: "background.resolveImageClassName",
@@ -13503,7 +13540,7 @@ function createBackgroundImageNode(path25, baseClassName = "rb-absolute rb-z-neg
13503
13540
  },
13504
13541
  style: {
13505
13542
  $bind: {
13506
- from: path25,
13543
+ from: path27,
13507
13544
  transforms: [{ id: "background.resolveImageStyle" }]
13508
13545
  }
13509
13546
  },
@@ -13515,8 +13552,8 @@ function createBackgroundImageNode(path25, baseClassName = "rb-absolute rb-z-neg
13515
13552
  bind(imagePath)
13516
13553
  );
13517
13554
  }
13518
- function createBackgroundOverlayNode(path25, className = "background-overlay rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full rb-w-full rb-pointer-events-none") {
13519
- const overlayPath = `${path25}.overlay`;
13555
+ function createBackgroundOverlayNode(path27, className = "background-overlay rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full rb-w-full rb-pointer-events-none") {
13556
+ const overlayPath = `${path27}.overlay`;
13520
13557
  return el("div", {
13521
13558
  className,
13522
13559
  style: {
@@ -14356,10 +14393,10 @@ var init_sectionForegroundStyles = __esm({
14356
14393
  });
14357
14394
 
14358
14395
  // ../blocks/src/system/transforms/registry/boxStyles.ts
14359
- function readPath(source, path25) {
14360
- if (!source || !path25) return void 0;
14361
- if (!path25.includes(".")) return source[path25];
14362
- return path25.split(".").reduce((acc, segment) => {
14396
+ function readPath(source, path27) {
14397
+ if (!source || !path27) return void 0;
14398
+ if (!path27.includes(".")) return source[path27];
14399
+ return path27.split(".").reduce((acc, segment) => {
14363
14400
  if (acc && typeof acc === "object" && segment in acc) {
14364
14401
  return acc[segment];
14365
14402
  }
@@ -15351,27 +15388,27 @@ function scopePropValue(value, scope) {
15351
15388
  }
15352
15389
  return value;
15353
15390
  }
15354
- function scopeContentPath(path25, scope) {
15391
+ function scopeContentPath(path27, scope) {
15355
15392
  if (!scope || scope.length === 0) {
15356
- return path25;
15393
+ return path27;
15357
15394
  }
15358
- if (path25 === "content") {
15395
+ if (path27 === "content") {
15359
15396
  return `content.${scope}`;
15360
15397
  }
15361
- if (path25.startsWith("content.")) {
15362
- const remainder = path25.slice("content.".length);
15398
+ if (path27.startsWith("content.")) {
15399
+ const remainder = path27.slice("content.".length);
15363
15400
  return remainder.length > 0 ? `content.${scope}.${remainder}` : `content.${scope}`;
15364
15401
  }
15365
- if (path25.startsWith("content[")) {
15366
- return path25.replace(/^content/, `content.${scope}`);
15402
+ if (path27.startsWith("content[")) {
15403
+ return path27.replace(/^content/, `content.${scope}`);
15367
15404
  }
15368
- if (path25.startsWith("$root.")) {
15369
- return path25;
15405
+ if (path27.startsWith("$root.")) {
15406
+ return path27;
15370
15407
  }
15371
- if (path25.includes(".")) {
15372
- return path25;
15408
+ if (path27.includes(".")) {
15409
+ return path27;
15373
15410
  }
15374
- return `content.${scope}.${path25}`;
15411
+ return `content.${scope}.${path27}`;
15375
15412
  }
15376
15413
  var FRAGMENT_ID_PATTERN, FIELD_ID_PATTERN, dataLoaderSchema, fragmentDataSchema, fragmentConfigSchema, FragmentConfigError;
15377
15414
  var init_types14 = __esm({
@@ -17955,15 +17992,53 @@ var init_newsletterForm = __esm({
17955
17992
  title: "Newsletter Form",
17956
17993
  description: "Newsletter subscription form with preset field configurations.",
17957
17994
  fields: [
17995
+ {
17996
+ id: "destinationProvider",
17997
+ type: "select",
17998
+ label: "Send signups to",
17999
+ description: "Choose where new subscribers from this form should go.",
18000
+ defaultValue: "riverbank",
18001
+ required: true,
18002
+ ui: { intent: "behavior" },
18003
+ options: [
18004
+ { value: "riverbank", label: "Riverbank newsletter" }
18005
+ ]
18006
+ },
17958
18007
  {
17959
18008
  id: "listId",
17960
18009
  type: "reference",
17961
18010
  label: "Newsletter list",
17962
18011
  description: "Select the list new subscribers should be added to.",
17963
- required: true,
18012
+ required: false,
17964
18013
  referenceKind: "newsletterList",
17965
18014
  allowManualEntry: false,
17966
- ui: { intent: "behavior" }
18015
+ ui: {
18016
+ intent: "behavior",
18017
+ visibleWhen: { field: "destinationProvider", equals: "riverbank" }
18018
+ }
18019
+ },
18020
+ {
18021
+ id: "mailchimpAudienceId",
18022
+ type: "reference",
18023
+ label: "Mailchimp audience",
18024
+ description: "Choose the Mailchimp audience for new subscribers.",
18025
+ required: false,
18026
+ referenceKind: "mailchimpAudience",
18027
+ allowManualEntry: false,
18028
+ ui: {
18029
+ intent: "behavior",
18030
+ visibleWhen: { field: "destinationProvider", equals: "mailchimp" }
18031
+ }
18032
+ },
18033
+ {
18034
+ id: "mailchimpTags",
18035
+ type: "text",
18036
+ label: "Mailchimp tags",
18037
+ description: "Optional tags to apply in Mailchimp, separated by commas or semicolons.",
18038
+ ui: {
18039
+ intent: "behavior",
18040
+ visibleWhen: { field: "destinationProvider", equals: "mailchimp" }
18041
+ }
17967
18042
  },
17968
18043
  {
17969
18044
  id: "preset",
@@ -18010,13 +18085,18 @@ var init_newsletterForm = __esm({
18010
18085
  id: "tags",
18011
18086
  type: "text",
18012
18087
  label: "Tags (optional)",
18013
- description: "Optional tags to apply on subscribe (comma or semicolon separated)."
18088
+ description: "Optional tags to apply on subscribe (comma or semicolon separated).",
18089
+ ui: {
18090
+ intent: "behavior",
18091
+ visibleWhen: { field: "destinationProvider", equals: "riverbank" }
18092
+ }
18014
18093
  }
18015
18094
  ],
18016
18095
  layout: [
18017
18096
  el(
18018
18097
  "newsletter-form",
18019
18098
  withApiBindings({
18099
+ destinationProvider: { $bind: { from: "destinationProvider" } },
18020
18100
  listId: { $bind: { from: "listId" } },
18021
18101
  preset: { $bind: { from: "preset" } },
18022
18102
  includePhone: { $bind: { from: "includePhone" } },
@@ -18247,8 +18327,8 @@ function decodeSuccess(value) {
18247
18327
  function decodeFailure(issues) {
18248
18328
  return { ok: false, issues };
18249
18329
  }
18250
- function zodIssuePath(path25) {
18251
- return path25.flatMap((segment) => {
18330
+ function zodIssuePath(path27) {
18331
+ return path27.flatMap((segment) => {
18252
18332
  if (typeof segment === "string" || typeof segment === "number") {
18253
18333
  return [segment];
18254
18334
  }
@@ -18267,9 +18347,9 @@ function createZodCodec(schema) {
18267
18347
  return decodeSuccess(parsed.data);
18268
18348
  }
18269
18349
  return decodeFailure(
18270
- parsed.error.issues.map((issue4) => ({
18271
- path: zodIssuePath(issue4.path),
18272
- message: issue4.message
18350
+ parsed.error.issues.map((issue5) => ({
18351
+ path: zodIssuePath(issue5.path),
18352
+ message: issue5.message
18273
18353
  }))
18274
18354
  );
18275
18355
  }
@@ -18522,6 +18602,83 @@ var init_media2 = __esm({
18522
18602
  ]);
18523
18603
  }
18524
18604
  });
18605
+ function createHardBreakNode() {
18606
+ return { type: "hardBreak" };
18607
+ }
18608
+ function parseRichTextInlineMarkdown(text2) {
18609
+ const out = [];
18610
+ const pushText = (value, marks) => {
18611
+ if (!value) return;
18612
+ out.push(
18613
+ marks && marks.length > 0 ? { type: "text", text: value, marks } : { type: "text", text: value }
18614
+ );
18615
+ };
18616
+ let rest = text2;
18617
+ while (rest.length > 0) {
18618
+ const start = rest.indexOf("**");
18619
+ if (start === -1) {
18620
+ pushText(rest);
18621
+ break;
18622
+ }
18623
+ const end = rest.indexOf("**", start + 2);
18624
+ if (end === -1) {
18625
+ pushText(rest);
18626
+ break;
18627
+ }
18628
+ pushText(rest.slice(0, start));
18629
+ pushText(rest.slice(start + 2, end), [{ type: "bold" }]);
18630
+ rest = rest.slice(end + 2);
18631
+ }
18632
+ return out;
18633
+ }
18634
+ function parseRichTextParagraphInlineMarkdown(text2) {
18635
+ return text2.split("\n").flatMap((line, index) => {
18636
+ const lineNodes = parseRichTextInlineMarkdown(line.trim());
18637
+ return index === 0 ? lineNodes : [createHardBreakNode(), ...lineNodes];
18638
+ });
18639
+ }
18640
+ function createRichTextDocFromMarkdown(markdown) {
18641
+ const normalized = markdown.replace(/\r\n/g, "\n").trim();
18642
+ if (!normalized) return { type: "doc", content: [] };
18643
+ const paragraphs = normalized.split(/\n{2,}/).map((paragraph) => paragraph.trim()).filter(Boolean);
18644
+ return {
18645
+ type: "doc",
18646
+ content: paragraphs.map((paragraph) => {
18647
+ const inline2 = parseRichTextParagraphInlineMarkdown(paragraph);
18648
+ return inline2.length > 0 ? { type: "paragraph", content: inline2 } : { type: "paragraph" };
18649
+ })
18650
+ };
18651
+ }
18652
+ var TipTapMarkSchema, TipTapNodeSchema, RichTextDocSchema;
18653
+ var init_richTextSchema = __esm({
18654
+ "../blocks/src/system/manifest/richTextSchema.ts"() {
18655
+ TipTapMarkSchema = z.object({
18656
+ type: z.string(),
18657
+ attrs: z.record(z.string(), z.unknown()).optional()
18658
+ });
18659
+ TipTapNodeSchema = z.lazy(
18660
+ () => z.object({
18661
+ type: z.string(),
18662
+ content: z.array(TipTapNodeSchema).optional(),
18663
+ text: z.string().optional(),
18664
+ attrs: z.record(z.string(), z.unknown()).optional(),
18665
+ marks: z.array(TipTapMarkSchema).optional()
18666
+ })
18667
+ );
18668
+ z.union([
18669
+ // Canonical: TipTap document directly
18670
+ TipTapNodeSchema,
18671
+ // Legacy (read-tolerance only): wrapped in { doc: {...} }
18672
+ z.object({
18673
+ doc: TipTapNodeSchema
18674
+ })
18675
+ ]);
18676
+ RichTextDocSchema = z.object({
18677
+ type: z.literal("doc"),
18678
+ content: z.array(TipTapNodeSchema)
18679
+ });
18680
+ }
18681
+ });
18525
18682
  var bookingDepositRefundPolicySchema, bookingInstalmentPlanSchema, bookingFlexibleBalanceDueDateRuleSchema, bookingFlexibleBalanceConfigSchema, blockBookingPaymentCollectionOptionSchema, blockBookingPaymentTermsSchema;
18526
18683
  var init_bookingPaymentTerms = __esm({
18527
18684
  "../blocks/src/system/blocks/shared/bookingPaymentTerms.ts"() {
@@ -18660,6 +18817,7 @@ var eventPresetSchema, eventScheduleScopeSchema, eventDestinationModeSchema, eve
18660
18817
  var init_schemas2 = __esm({
18661
18818
  "../blocks/src/system/blocks/events/shared/schemas.ts"() {
18662
18819
  init_media2();
18820
+ init_richTextSchema();
18663
18821
  init_bookingPaymentTerms();
18664
18822
  init_schemas();
18665
18823
  eventPresetSchema = z.enum(["event", "class", "workshop", "retreat", "performance"]);
@@ -18692,7 +18850,13 @@ var init_schemas2 = __esm({
18692
18850
  z.object({ kind: z.literal("free"), currency: z.string() }),
18693
18851
  z.object({ kind: z.literal("exact"), amount: z.number(), currency: z.string() }),
18694
18852
  z.object({ kind: z.literal("from"), amount: z.number(), currency: z.string() }),
18695
- z.object({ kind: z.literal("mixed"), paidFromAmount: z.number(), currency: z.string() }),
18853
+ z.object({ kind: z.literal("range"), minAmount: z.number(), maxAmount: z.number(), currency: z.string() }),
18854
+ z.object({
18855
+ kind: z.literal("mixed"),
18856
+ paidFromAmount: z.number(),
18857
+ paidToAmount: z.number(),
18858
+ currency: z.string()
18859
+ }),
18696
18860
  z.object({ kind: z.literal("unavailable"), currency: z.string() }),
18697
18861
  z.object({ kind: z.literal("course"), display: publicCoursePriceDisplaySchema })
18698
18862
  ]);
@@ -18700,7 +18864,13 @@ var init_schemas2 = __esm({
18700
18864
  z.object({ kind: z.literal("free"), currency: z.string() }),
18701
18865
  z.object({ kind: z.literal("exact"), amount: z.number(), currency: z.string() }),
18702
18866
  z.object({ kind: z.literal("from"), amount: z.number(), currency: z.string() }),
18703
- z.object({ kind: z.literal("mixed"), paidFromAmount: z.number(), currency: z.string() }),
18867
+ z.object({ kind: z.literal("range"), minAmount: z.number(), maxAmount: z.number(), currency: z.string() }),
18868
+ z.object({
18869
+ kind: z.literal("mixed"),
18870
+ paidFromAmount: z.number(),
18871
+ paidToAmount: z.number(),
18872
+ currency: z.string()
18873
+ }),
18704
18874
  z.object({ kind: z.literal("unavailable"), currency: z.string() })
18705
18875
  ]);
18706
18876
  publicEventAttendanceModeSchema = z.enum(["in_person", "online"]);
@@ -18785,6 +18955,9 @@ var init_schemas2 = __esm({
18785
18955
  seriesId: z.string(),
18786
18956
  title: z.string(),
18787
18957
  description: z.string().nullable(),
18958
+ content: z.object({
18959
+ body: RichTextDocSchema.nullable().optional()
18960
+ }).optional(),
18788
18961
  presentation: z.object({
18789
18962
  cardTitleOverride: z.string().nullable().optional(),
18790
18963
  summary: z.string().nullable().optional(),
@@ -19167,10 +19340,21 @@ function readLegacyPriceDisplay(value, currency) {
19167
19340
  amount: readAmount(value.amount) ?? 0,
19168
19341
  currency: displayCurrency
19169
19342
  } : { kind: "unavailable", currency };
19343
+ case "range": {
19344
+ const minAmount = readAmount(value.minAmount);
19345
+ const maxAmount = readAmount(value.maxAmount);
19346
+ return minAmount !== null && maxAmount !== null ? {
19347
+ kind: "range",
19348
+ minAmount,
19349
+ maxAmount,
19350
+ currency: displayCurrency
19351
+ } : { kind: "unavailable", currency };
19352
+ }
19170
19353
  case "mixed":
19171
19354
  return readAmount(value.paidFromAmount) !== null ? {
19172
19355
  kind: "mixed",
19173
19356
  paidFromAmount: readAmount(value.paidFromAmount) ?? 0,
19357
+ paidToAmount: readAmount(value.paidToAmount) ?? readAmount(value.paidFromAmount) ?? 0,
19174
19358
  currency: displayCurrency
19175
19359
  } : { kind: "unavailable", currency };
19176
19360
  case "unavailable":
@@ -19425,6 +19609,7 @@ var init_event_registration_interactive = __esm({
19425
19609
  successMessage: z.string().optional(),
19426
19610
  waitlistMessage: z.string().optional(),
19427
19611
  buttonVariant: registrationButtonVariantSchema.optional(),
19612
+ overlayEnabled: z.boolean().optional(),
19428
19613
  spamProtectionEnabled: z.boolean().optional(),
19429
19614
  stage: previewStageSchema.optional(),
19430
19615
  supportEmail: z.string().optional()
@@ -19448,6 +19633,7 @@ var init_event_registration_interactive = __esm({
19448
19633
  successMessage: z.string().optional(),
19449
19634
  waitlistMessage: z.string().optional(),
19450
19635
  buttonVariant: registrationButtonVariantSchema.optional(),
19636
+ overlayEnabled: z.boolean().optional(),
19451
19637
  spamProtectionEnabled: z.boolean().optional(),
19452
19638
  supportEmail: z.string().optional()
19453
19639
  });
@@ -19480,6 +19666,7 @@ var init_event_registration_interactive = __esm({
19480
19666
  successMessage: source.successMessage,
19481
19667
  waitlistMessage: source.waitlistMessage,
19482
19668
  buttonVariant: source.buttonVariant,
19669
+ overlayEnabled: source.overlayEnabled,
19483
19670
  spamProtectionEnabled: source.spamProtectionEnabled,
19484
19671
  supportEmail: source.supportEmail
19485
19672
  }
@@ -20503,10 +20690,7 @@ var init_shop_commerce_shared = __esm({
20503
20690
 
20504
20691
  // ../blocks/src/system/runtime/nodes/commerce/shared/display.ts
20505
20692
  function formatCommercePrice(cents, currency) {
20506
- return new Intl.NumberFormat("en-US", {
20507
- style: "currency",
20508
- currency: currency.toUpperCase()
20509
- }).format(cents / 100);
20693
+ return formatCurrencyAmount(cents, currency);
20510
20694
  }
20511
20695
  function getPassesHeading(passes, explicitHeading) {
20512
20696
  if (explicitHeading) return explicitHeading;
@@ -20700,6 +20884,7 @@ function formatValidity(days) {
20700
20884
  }
20701
20885
  var init_display = __esm({
20702
20886
  "../blocks/src/system/runtime/nodes/commerce/shared/display.ts"() {
20887
+ init_src();
20703
20888
  init_creditProducts();
20704
20889
  init_shop_commerce_shared();
20705
20890
  }
@@ -21162,6 +21347,65 @@ var init_gifting_interactive = __esm({
21162
21347
  }
21163
21348
  });
21164
21349
 
21350
+ // ../blocks/src/system/blocks/newsletter-signup-destination.ts
21351
+ function parseNewsletterSignupBlockId(value) {
21352
+ const trimmed = parseTrimmedString(value);
21353
+ return trimmed && BLOCK_ID_PATTERN.test(trimmed) ? trimmed : null;
21354
+ }
21355
+ function parseSignedNewsletterDestinationRef(value) {
21356
+ const trimmed = parseTrimmedString(value);
21357
+ return trimmed && SIGNED_DESTINATION_REF_PATTERN.test(trimmed) ? trimmed : null;
21358
+ }
21359
+ function parseNewsletterSignupDestinationProvider(value) {
21360
+ return value === "riverbank" || value === "mailchimp" ? value : null;
21361
+ }
21362
+ function buildNewsletterSignupBlockRef(blockId) {
21363
+ const parsed = parseNewsletterSignupBlockId(blockId);
21364
+ return parsed ? { tag: "block_ref", blockId: parsed } : null;
21365
+ }
21366
+ function normalizeNewsletterSignupEditorValuesForDestination(values) {
21367
+ const destinationProvider = parseNewsletterSignupDestinationProvider(values.destinationProvider) ?? "riverbank";
21368
+ if (destinationProvider === "mailchimp") {
21369
+ return {
21370
+ destinationProvider,
21371
+ mailchimpAudienceId: values.mailchimpAudienceId,
21372
+ mailchimpTags: values.mailchimpTags
21373
+ };
21374
+ }
21375
+ return {
21376
+ destinationProvider,
21377
+ listId: values.listId,
21378
+ tags: values.tags
21379
+ };
21380
+ }
21381
+ function deriveNewsletterSignupRuntimeSource(values) {
21382
+ const normalized = normalizeNewsletterSignupEditorValuesForDestination(values);
21383
+ if (normalized.destinationProvider === "mailchimp") {
21384
+ return {
21385
+ destinationProvider: "mailchimp",
21386
+ listId: null,
21387
+ tags: null
21388
+ };
21389
+ }
21390
+ return {
21391
+ destinationProvider: "riverbank",
21392
+ listId: parseTrimmedString(normalized.listId),
21393
+ tags: parseTrimmedString(normalized.tags)
21394
+ };
21395
+ }
21396
+ function parseTrimmedString(value) {
21397
+ if (typeof value !== "string") return null;
21398
+ const trimmed = value.trim();
21399
+ return trimmed.length > 0 ? trimmed : null;
21400
+ }
21401
+ var BLOCK_ID_PATTERN, SIGNED_DESTINATION_REF_PATTERN;
21402
+ var init_newsletter_signup_destination = __esm({
21403
+ "../blocks/src/system/blocks/newsletter-signup-destination.ts"() {
21404
+ BLOCK_ID_PATTERN = /^[A-Za-z0-9._:-]{1,200}$/;
21405
+ SIGNED_DESTINATION_REF_PATTERN = /^[A-Za-z0-9._~-]{16,1000}$/;
21406
+ }
21407
+ });
21408
+
21165
21409
  // ../blocks/src/system/runtime/nodes/newsletter-form.types.ts
21166
21410
  function getPresetFields(preset2, options) {
21167
21411
  const includePhone = Boolean(options?.includePhone);
@@ -21227,13 +21471,29 @@ function buildNewsletterDisplay(source) {
21227
21471
  fields: getPresetFields(preset2, { includePhone })
21228
21472
  };
21229
21473
  }
21230
- var newsletterPresetSchema, newsletterFieldSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterFormBlockRuntime;
21474
+ function parseRequiredNewsletterSignupBlockId(value) {
21475
+ const parsed = parseNewsletterSignupBlockId(value);
21476
+ if (!parsed) {
21477
+ throw new Error("Newsletter signup block destination ref requires blockId");
21478
+ }
21479
+ return parsed;
21480
+ }
21481
+ function parseRequiredSignedNewsletterDestinationRef(value) {
21482
+ const parsed = parseSignedNewsletterDestinationRef(value);
21483
+ if (!parsed) {
21484
+ throw new Error("Newsletter signup signed destination ref requires token");
21485
+ }
21486
+ return parsed;
21487
+ }
21488
+ var newsletterPresetSchema, newsletterDestinationProviderSchema, newsletterFieldSchema, newsletterSignupBlockIdSchema, signedNewsletterDestinationRefSchema, newsletterPublicDestinationRefSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterFormBlockRuntime;
21231
21489
  var init_newsletter_form_interactive = __esm({
21232
21490
  "../blocks/src/system/runtime/nodes/newsletter-form.interactive.ts"() {
21233
21491
  init_islands();
21234
21492
  init_runtime();
21493
+ init_newsletter_signup_destination();
21235
21494
  init_newsletter_form_types();
21236
21495
  newsletterPresetSchema = z.enum(["emailOnly", "emailName", "emailFirstLast", "emailNameCompany"]);
21496
+ newsletterDestinationProviderSchema = z.enum(["riverbank", "mailchimp"]);
21237
21497
  newsletterFieldSchema = z.object({
21238
21498
  id: z.string(),
21239
21499
  type: z.enum(["email", "text"]),
@@ -21241,10 +21501,24 @@ var init_newsletter_form_interactive = __esm({
21241
21501
  required: z.boolean(),
21242
21502
  placeholder: z.string().optional()
21243
21503
  });
21504
+ newsletterSignupBlockIdSchema = z.string().trim().min(1).transform(parseRequiredNewsletterSignupBlockId);
21505
+ signedNewsletterDestinationRefSchema = z.string().trim().min(1).transform(parseRequiredSignedNewsletterDestinationRef);
21506
+ newsletterPublicDestinationRefSchema = z.discriminatedUnion("tag", [
21507
+ z.object({
21508
+ tag: z.literal("block_ref"),
21509
+ blockId: newsletterSignupBlockIdSchema
21510
+ }),
21511
+ z.object({
21512
+ tag: z.literal("signed_destination_ref"),
21513
+ token: signedNewsletterDestinationRefSchema
21514
+ })
21515
+ ]);
21244
21516
  newsletterSourceSchema = z.object({
21517
+ blockId: z.string().nullable().optional(),
21245
21518
  siteId: z.string().optional(),
21246
21519
  apiBaseUrl: z.string().optional(),
21247
21520
  listId: z.string().nullable().optional(),
21521
+ destinationProvider: newsletterDestinationProviderSchema.nullable().optional(),
21248
21522
  preset: newsletterPresetSchema.optional(),
21249
21523
  includePhone: z.boolean().optional(),
21250
21524
  buttonLabel: z.string().nullable().optional(),
@@ -21263,6 +21537,7 @@ var init_newsletter_form_interactive = __esm({
21263
21537
  fields: z.array(newsletterFieldSchema)
21264
21538
  });
21265
21539
  newsletterHydrationSchema = z.object({
21540
+ destinationRef: newsletterPublicDestinationRefSchema.nullable().optional(),
21266
21541
  listId: z.string().nullable().optional(),
21267
21542
  preset: newsletterPresetSchema,
21268
21543
  includePhone: z.boolean(),
@@ -21283,16 +21558,20 @@ var init_newsletter_form_interactive = __esm({
21283
21558
  source: createZodCodec(newsletterSourceSchema),
21284
21559
  render: createZodCodec(newsletterRenderSchema)
21285
21560
  },
21286
- buildRender: (source) => ({
21287
- display: buildNewsletterDisplay(source),
21288
- hydration: {
21289
- listId: source.listId,
21290
- preset: source.preset ?? "emailOnly",
21291
- includePhone: source.includePhone ?? false,
21292
- tags: source.tags ?? null,
21293
- spamProtectionEnabled: source.spamProtectionEnabled
21294
- }
21295
- })
21561
+ buildRender: (source) => {
21562
+ const runtimeSource = deriveNewsletterSignupRuntimeSource(source);
21563
+ return {
21564
+ display: buildNewsletterDisplay(source),
21565
+ hydration: {
21566
+ destinationRef: buildNewsletterSignupBlockRef(source.blockId),
21567
+ listId: runtimeSource.listId,
21568
+ preset: source.preset ?? "emailOnly",
21569
+ includePhone: source.includePhone ?? false,
21570
+ tags: runtimeSource.tags,
21571
+ spamProtectionEnabled: source.spamProtectionEnabled
21572
+ }
21573
+ };
21574
+ }
21296
21575
  });
21297
21576
  }
21298
21577
  });
@@ -22309,6 +22588,64 @@ var ENDPOINT_DEFINITIONS = {
22309
22588
  auth: "user",
22310
22589
  responseKind: "json"
22311
22590
  },
22591
+ listMailchimpAudiences: {
22592
+ path: "/sites/{siteId}/integrations/mailchimp/audiences",
22593
+ method: "GET",
22594
+ tags: [TAG_TEMPLATES.site],
22595
+ auth: "user",
22596
+ responseKind: "json",
22597
+ errors: ["auth:forbidden", "server:internal_error"]
22598
+ },
22599
+ getMailchimpSignupSyncHealth: {
22600
+ path: "/sites/{siteId}/integrations/mailchimp/signup-sync-health",
22601
+ method: "GET",
22602
+ tags: [TAG_TEMPLATES.site],
22603
+ auth: "user",
22604
+ responseKind: "json",
22605
+ errors: ["auth:forbidden", "server:internal_error"]
22606
+ },
22607
+ getMailchimpConnection: {
22608
+ path: "/sites/{siteId}/integrations/mailchimp/connection",
22609
+ method: "GET",
22610
+ tags: [TAG_TEMPLATES.site],
22611
+ auth: "user",
22612
+ responseKind: "json",
22613
+ errors: ["auth:forbidden", "server:internal_error"]
22614
+ },
22615
+ startMailchimpOAuth: {
22616
+ path: "/sites/{siteId}/integrations/mailchimp/oauth/start",
22617
+ method: "POST",
22618
+ tags: [TAG_TEMPLATES.site],
22619
+ auth: "user",
22620
+ responseKind: "json",
22621
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
22622
+ errors: ["auth:forbidden", "validation:invalid_input", "server:internal_error"]
22623
+ },
22624
+ refreshMailchimpAudiences: {
22625
+ path: "/sites/{siteId}/integrations/mailchimp/audiences/refresh",
22626
+ method: "POST",
22627
+ tags: [TAG_TEMPLATES.site],
22628
+ auth: "user",
22629
+ responseKind: "json",
22630
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
22631
+ errors: ["auth:forbidden", "server:internal_error"]
22632
+ },
22633
+ disconnectMailchimp: {
22634
+ path: "/sites/{siteId}/integrations/mailchimp/disconnect",
22635
+ method: "POST",
22636
+ tags: [TAG_TEMPLATES.site],
22637
+ auth: "user",
22638
+ responseKind: "json",
22639
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
22640
+ errors: ["auth:forbidden", "server:internal_error"]
22641
+ },
22642
+ mailchimpOAuthCallback: {
22643
+ path: "/auth/mailchimp/callback",
22644
+ method: "GET",
22645
+ auth: "public",
22646
+ responseKind: "void",
22647
+ errors: []
22648
+ },
22312
22649
  createNewsletterList: {
22313
22650
  path: "/sites/{siteId}/newsletter/lists",
22314
22651
  method: "POST",
@@ -24533,20 +24870,6 @@ var ENDPOINT_DEFINITIONS = {
24533
24870
  auth: "user",
24534
24871
  responseKind: "json"
24535
24872
  },
24536
- instagramUploadZip: {
24537
- path: "/instagram/upload-zip",
24538
- method: "POST",
24539
- tags: ["instagram-import"],
24540
- auth: "user",
24541
- responseKind: "json"
24542
- },
24543
- createInstagramZipUploadUrl: {
24544
- path: "/instagram/upload-zip-url",
24545
- method: "POST",
24546
- tags: ["instagram-import"],
24547
- auth: "user",
24548
- responseKind: "json"
24549
- },
24550
24873
  getAnalyticsReport: {
24551
24874
  path: "/sites/{siteId}/analytics/report",
24552
24875
  method: "GET",
@@ -28589,20 +28912,20 @@ function validationContext(options = {}) {
28589
28912
  allowIncomplete: isDraft || (options.allowIncomplete ?? false)
28590
28913
  };
28591
28914
  }
28592
- function formatFieldPath(path25) {
28593
- return path25.map((segment) => String(segment)).join(".");
28915
+ function formatFieldPath(path27) {
28916
+ return path27.map((segment) => String(segment)).join(".");
28594
28917
  }
28595
- function toZodIssuePath(path25) {
28596
- return [...path25];
28918
+ function toZodIssuePath(path27) {
28919
+ return [...path27];
28597
28920
  }
28598
- function fieldIssueToMessage(issue4) {
28599
- switch (issue4.kind) {
28921
+ function fieldIssueToMessage(issue5) {
28922
+ switch (issue5.kind) {
28600
28923
  case "required":
28601
28924
  return "This field is required";
28602
28925
  case "wrongType":
28603
- return `${issue4.label} needs ${issue4.expected}`;
28926
+ return `${issue5.label} needs ${issue5.expected}`;
28604
28927
  case "tooLong":
28605
- return `Use ${issue4.maximum} characters or fewer`;
28928
+ return `Use ${issue5.maximum} characters or fewer`;
28606
28929
  case "invalidEmail":
28607
28930
  return "Enter a valid email address";
28608
28931
  case "invalidPhone":
@@ -28618,36 +28941,36 @@ function fieldIssueToMessage(issue4) {
28618
28941
  case "invalidDateTime":
28619
28942
  return "Choose a valid date and time";
28620
28943
  case "invalidNumber":
28621
- return `${issue4.label} needs a number`;
28944
+ return `${issue5.label} needs a number`;
28622
28945
  case "tooSmall":
28623
- return `${issue4.label} must be ${issue4.minimum} or more`;
28946
+ return `${issue5.label} must be ${issue5.minimum} or more`;
28624
28947
  case "tooLarge":
28625
- return `${issue4.label} must be ${issue4.maximum} or less`;
28948
+ return `${issue5.label} must be ${issue5.maximum} or less`;
28626
28949
  case "invalidSlug":
28627
- return `${issue4.label} can only use lowercase letters, numbers, and dashes`;
28950
+ return `${issue5.label} can only use lowercase letters, numbers, and dashes`;
28628
28951
  case "invalidOption":
28629
- return `Choose one of the available options for ${issue4.label}`;
28952
+ return `Choose one of the available options for ${issue5.label}`;
28630
28953
  case "tooFewItems":
28631
- return `${issue4.label} must have at least ${issue4.minimum} ${pluralize(issue4.itemLabel, issue4.minimum)}`;
28954
+ return `${issue5.label} must have at least ${issue5.minimum} ${pluralize(issue5.itemLabel, issue5.minimum)}`;
28632
28955
  case "tooManyItems":
28633
- return `${issue4.label} must have at most ${issue4.maximum} ${pluralize(issue4.itemLabel, issue4.maximum)}`;
28956
+ return `${issue5.label} must have at most ${issue5.maximum} ${pluralize(issue5.itemLabel, issue5.maximum)}`;
28634
28957
  case "invalidRichText":
28635
- return `${issue4.label} must be valid rich text`;
28958
+ return `${issue5.label} must be valid rich text`;
28636
28959
  case "invalidMedia":
28637
- return `${issue4.label} must be a valid media item`;
28960
+ return `${issue5.label} must be a valid media item`;
28638
28961
  case "invalidLink":
28639
- return `${issue4.label} must be a valid link`;
28962
+ return `${issue5.label} must be a valid link`;
28640
28963
  case "invalidReference":
28641
- return `${issue4.label} must reference a valid item`;
28964
+ return `${issue5.label} must reference a valid item`;
28642
28965
  default:
28643
- return assertNever2(issue4);
28966
+ return assertNever2(issue5);
28644
28967
  }
28645
28968
  }
28646
28969
  function pluralize(label, count) {
28647
28970
  if (count === 1) return label;
28648
28971
  return label.endsWith("s") ? label : `${label}s`;
28649
28972
  }
28650
- function deriveFieldValidationPlan(field, path25 = [field.id]) {
28973
+ function deriveFieldValidationPlan(field, path27 = [field.id]) {
28651
28974
  const required = Boolean(field.required);
28652
28975
  switch (field.type) {
28653
28976
  case "text": {
@@ -28658,7 +28981,7 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28658
28981
  });
28659
28982
  if (typeof field.ui?.min === "number") constraints2.push({ kind: "numberMin", minimum: field.ui.min });
28660
28983
  if (typeof field.ui?.max === "number") constraints2.push({ kind: "numberMax", maximum: field.ui.max });
28661
- return makePlan("number", "number", field, path25, required, constraints2);
28984
+ return makePlan("number", "number", field, path27, required, constraints2);
28662
28985
  }
28663
28986
  const constraints = commonConstraints(required, {
28664
28987
  kind: field.ui?.widget === "iconPicker" ? "blockIconValue" : "textType"
@@ -28667,7 +28990,7 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28667
28990
  if (inputType === "tel") constraints.push({ kind: "phoneFormat" });
28668
28991
  if (field.ui?.pattern) constraints.push({ kind: "patternFormat", pattern: field.ui.pattern });
28669
28992
  if (typeof field.maxLength === "number") constraints.push({ kind: "maxLength", maximum: field.maxLength });
28670
- return makePlan("string", "string", field, path25, required, constraints);
28993
+ return makePlan("string", "string", field, path27, required, constraints);
28671
28994
  }
28672
28995
  case "number": {
28673
28996
  const constraints = commonConstraints(required, {
@@ -28675,34 +28998,34 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28675
28998
  });
28676
28999
  if (typeof field.min === "number") constraints.push({ kind: "numberMin", minimum: field.min });
28677
29000
  if (typeof field.max === "number") constraints.push({ kind: "numberMax", maximum: field.max });
28678
- return makePlan("number", "number", field, path25, required, constraints);
29001
+ return makePlan("number", "number", field, path27, required, constraints);
28679
29002
  }
28680
29003
  case "slug": {
28681
29004
  const constraints = commonConstraints(required, { kind: "textType" }, { kind: "slugFormat" });
28682
29005
  if (typeof field.maxLength === "number") constraints.push({ kind: "maxLength", maximum: field.maxLength });
28683
- return makePlan("string", "string", field, path25, required, constraints);
29006
+ return makePlan("string", "string", field, path27, required, constraints);
28684
29007
  }
28685
29008
  case "url":
28686
29009
  return makePlan(
28687
29010
  "string",
28688
29011
  "string",
28689
29012
  field,
28690
- path25,
29013
+ path27,
28691
29014
  required,
28692
29015
  commonConstraints(required, { kind: "textType" }, { kind: "urlFormat", allowRelative: Boolean(field.allowRelative) })
28693
29016
  );
28694
29017
  case "reference":
28695
- return makePlan("string", "string", field, path25, required, commonConstraints(required, { kind: "referenceText" }));
29018
+ return makePlan("string", "string", field, path27, required, commonConstraints(required, { kind: "referenceText" }));
28696
29019
  case "date":
28697
- return makePlan("string", "string", field, path25, required, commonConstraints(required, { kind: "textType" }, { kind: "dateFormat" }));
29020
+ return makePlan("string", "string", field, path27, required, commonConstraints(required, { kind: "textType" }, { kind: "dateFormat" }));
28698
29021
  case "time":
28699
- return makePlan("string", "string", field, path25, required, commonConstraints(required, { kind: "textType" }, { kind: "timeFormat" }));
29022
+ return makePlan("string", "string", field, path27, required, commonConstraints(required, { kind: "textType" }, { kind: "timeFormat" }));
28700
29023
  case "datetime":
28701
29024
  return makePlan(
28702
29025
  "string",
28703
29026
  "string",
28704
29027
  field,
28705
- path25,
29028
+ path27,
28706
29029
  required,
28707
29030
  commonConstraints(required, { kind: "textType" }, { kind: "datetimeFormat" })
28708
29031
  );
@@ -28711,7 +29034,7 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28711
29034
  "select",
28712
29035
  "select",
28713
29036
  field,
28714
- path25,
29037
+ path27,
28715
29038
  required,
28716
29039
  commonConstraints(required, {
28717
29040
  kind: "selectOption",
@@ -28720,40 +29043,40 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28720
29043
  })
28721
29044
  );
28722
29045
  case "richText":
28723
- return makePlan("richText", "object", field, path25, required, commonConstraints(required, { kind: "richTextDoc" }));
29046
+ return makePlan("richText", "object", field, path27, required, commonConstraints(required, { kind: "richTextDoc" }));
28724
29047
  case "media":
28725
29048
  case "file":
28726
- return makePlan("media", "object", field, path25, required, commonConstraints(required, { kind: "mediaObject" }));
29049
+ return makePlan("media", "object", field, path27, required, commonConstraints(required, { kind: "mediaObject" }));
28727
29050
  case "link":
28728
- return makePlan("link", "object", field, path25, required, commonConstraints(required, { kind: "linkObject" }));
29051
+ return makePlan("link", "object", field, path27, required, commonConstraints(required, { kind: "linkObject" }));
28729
29052
  case "boolean":
28730
- return makePlan("boolean", "boolean", field, path25, required, requiredConstraints(required));
29053
+ return makePlan("boolean", "boolean", field, path27, required, requiredConstraints(required));
28731
29054
  case "repeater":
28732
29055
  return {
28733
- ...makePlan("repeater", "array", field, path25, required, commonConstraints(required, { kind: "arrayType" })),
29056
+ ...makePlan("repeater", "array", field, path27, required, commonConstraints(required, { kind: "arrayType" })),
28734
29057
  ...field.polymorphic && field.itemTypes ? {
28735
- repeatedItemVariants: deriveRepeatedItemVariants(field, [...path25, 0])
29058
+ repeatedItemVariants: deriveRepeatedItemVariants(field, [...path27, 0])
28736
29059
  } : {
28737
- repeatedItemPlan: deriveNestedFieldPlans(getRepeaterFields(field), [...path25, 0])
29060
+ repeatedItemPlan: deriveNestedFieldPlans(getRepeaterFields(field), [...path27, 0])
28738
29061
  },
28739
29062
  constraints: withRepeaterItemConstraints(field, commonConstraints(required, { kind: "arrayType" }))
28740
29063
  };
28741
29064
  case "group":
28742
29065
  case "modal":
28743
29066
  return {
28744
- ...makePlan("group", "object", field, path25, required, requiredConstraints(required)),
28745
- children: deriveNestedFieldPlans(field.schema?.fields ?? [], path25),
29067
+ ...makePlan("group", "object", field, path27, required, requiredConstraints(required)),
29068
+ children: deriveNestedFieldPlans(field.schema?.fields ?? [], path27),
28746
29069
  allowNullChildren: field.type === "group" && field.ui?.widget === "locationPicker"
28747
29070
  };
28748
29071
  case "tabGroup":
28749
29072
  return {
28750
- ...makePlan("group", "object", field, path25, required, requiredConstraints(required)),
28751
- children: field.tabs.flatMap((tab) => deriveNestedFieldPlans(tab.fields, path25))
29073
+ ...makePlan("group", "object", field, path27, required, requiredConstraints(required)),
29074
+ children: field.tabs.flatMap((tab) => deriveNestedFieldPlans(tab.fields, path27))
28752
29075
  };
28753
29076
  case "presetOrCustom":
28754
29077
  case "contentTypeSelect":
28755
29078
  case "entryPicker":
28756
- return makePlan("passthrough", "unknown", field, path25, false, []);
29079
+ return makePlan("passthrough", "unknown", field, path27, false, []);
28757
29080
  default:
28758
29081
  return assertNever2(field);
28759
29082
  }
@@ -28767,14 +29090,14 @@ function commonConstraints(required, ...specific) {
28767
29090
  function requiredConstraints(required) {
28768
29091
  return required ? [{ kind: "required" }] : [];
28769
29092
  }
28770
- function makePlan(kind, valueKind2, field, path25, required, constraints) {
29093
+ function makePlan(kind, valueKind2, field, path27, required, constraints) {
28771
29094
  return {
28772
29095
  kind,
28773
29096
  valueKind: valueKind2,
28774
29097
  fieldId: field.id,
28775
29098
  label: field.label,
28776
29099
  fieldType: field.type,
28777
- path: path25,
29100
+ path: path27,
28778
29101
  required,
28779
29102
  visibility: fieldVisibility(field),
28780
29103
  constraints
@@ -29111,18 +29434,18 @@ function materializeRepeaterItemPlan(plan, parentPath, index) {
29111
29434
  return rebaseFieldPlanPath(plan, [...parentPath, 0], [...parentPath, index]);
29112
29435
  }
29113
29436
  function rebaseFieldPlanPath(plan, fromPrefix, toPrefix) {
29114
- const path25 = rebaseFieldPath(plan.path, fromPrefix, toPrefix);
29437
+ const path27 = rebaseFieldPath(plan.path, fromPrefix, toPrefix);
29115
29438
  switch (plan.kind) {
29116
29439
  case "group":
29117
29440
  return {
29118
29441
  ...plan,
29119
- path: path25,
29442
+ path: path27,
29120
29443
  children: plan.children.map((childPlan) => rebaseFieldPlanPath(childPlan, fromPrefix, toPrefix))
29121
29444
  };
29122
29445
  case "repeater":
29123
29446
  return {
29124
29447
  ...plan,
29125
- path: path25,
29448
+ path: path27,
29126
29449
  ...plan.repeatedItemVariants ? {
29127
29450
  repeatedItemVariants: plan.repeatedItemVariants.map((variant) => ({
29128
29451
  ...variant,
@@ -29143,20 +29466,20 @@ function rebaseFieldPlanPath(plan, fromPrefix, toPrefix) {
29143
29466
  case "passthrough":
29144
29467
  return {
29145
29468
  ...plan,
29146
- path: path25
29469
+ path: path27
29147
29470
  };
29148
29471
  default:
29149
29472
  return assertNever2(plan);
29150
29473
  }
29151
29474
  }
29152
- function rebaseFieldPath(path25, fromPrefix, toPrefix) {
29153
- if (!startsWithFieldPath(path25, fromPrefix)) {
29154
- throw new Error(`Cannot rebase field path ${formatFieldPath(path25)} from ${formatFieldPath(fromPrefix)}`);
29475
+ function rebaseFieldPath(path27, fromPrefix, toPrefix) {
29476
+ if (!startsWithFieldPath(path27, fromPrefix)) {
29477
+ throw new Error(`Cannot rebase field path ${formatFieldPath(path27)} from ${formatFieldPath(fromPrefix)}`);
29155
29478
  }
29156
- return [...toPrefix, ...path25.slice(fromPrefix.length)];
29479
+ return [...toPrefix, ...path27.slice(fromPrefix.length)];
29157
29480
  }
29158
- function startsWithFieldPath(path25, prefix) {
29159
- return prefix.every((segment, index) => path25[index] === segment);
29481
+ function startsWithFieldPath(path27, prefix) {
29482
+ return prefix.every((segment, index) => path27[index] === segment);
29160
29483
  }
29161
29484
  function issue(plan, kind, extra) {
29162
29485
  return {
@@ -29182,8 +29505,8 @@ function fieldPlanToZod(plan, options = {}) {
29182
29505
  }
29183
29506
  function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
29184
29507
  const message = fieldIssueToMessage(validationIssue);
29185
- const path25 = relativeZodIssuePath(validationIssue.path, rootPath);
29186
- const issuePath = path25.length > 0 ? { path: toZodIssuePath(path25) } : {};
29508
+ const path27 = relativeZodIssuePath(validationIssue.path, rootPath);
29509
+ const issuePath = path27.length > 0 ? { path: toZodIssuePath(path27) } : {};
29187
29510
  switch (validationIssue.kind) {
29188
29511
  case "required":
29189
29512
  if (validationIssue.emptyOrigin) {
@@ -29236,8 +29559,8 @@ function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
29236
29559
  assertNever2(validationIssue);
29237
29560
  }
29238
29561
  }
29239
- function relativeZodIssuePath(path25, rootPath) {
29240
- return startsWithFieldPath(path25, rootPath) ? path25.slice(rootPath.length) : path25;
29562
+ function relativeZodIssuePath(path27, rootPath) {
29563
+ return startsWithFieldPath(path27, rootPath) ? path27.slice(rootPath.length) : path27;
29241
29564
  }
29242
29565
  function compilePattern(pattern) {
29243
29566
  try {
@@ -32395,9 +32718,9 @@ function maybeBuildSupabaseTransformUrl(inputUrl, options) {
32395
32718
  const remainder = url.pathname.slice(idx + marker.length);
32396
32719
  const parts = remainder.split("/").filter(Boolean);
32397
32720
  const bucket = parts[0];
32398
- const path25 = parts.slice(1).join("/");
32399
- if (!bucket || !path25) return inputUrl;
32400
- url.pathname = `/storage/v1/render/image/public/${bucket}/${path25}`;
32721
+ const path27 = parts.slice(1).join("/");
32722
+ if (!bucket || !path27) return inputUrl;
32723
+ url.pathname = `/storage/v1/render/image/public/${bucket}/${path27}`;
32401
32724
  url.search = "";
32402
32725
  if (width) url.searchParams.set("width", String(width));
32403
32726
  if (height) url.searchParams.set("height", String(height));
@@ -35102,6 +35425,12 @@ var eventRegistrationManifest = createBlockManifest({
35102
35425
  buttonVariant: {
35103
35426
  $bind: { from: "content.buttonVariant", fallback: "primary" }
35104
35427
  },
35428
+ overlayEnabled: {
35429
+ $bind: {
35430
+ from: "$root.eventRegistrationOverlayEnabled",
35431
+ fallback: false
35432
+ }
35433
+ },
35105
35434
  // Event data from loader
35106
35435
  events: { $bind: { from: "data.events" } },
35107
35436
  // Stage for preview mode (allows registering for draft events)
@@ -41872,6 +42201,7 @@ var SUPPORTED_LOADER_ENDPOINTS = [
41872
42201
  ];
41873
42202
 
41874
42203
  // ../blocks/src/index.ts
42204
+ init_richTextSchema();
41875
42205
  init_booking_form_reserved_fields();
41876
42206
  init_colorStyles();
41877
42207
 
@@ -43007,11 +43337,11 @@ siteBannerSettingsSchema.superRefine((value, ctx) => {
43007
43337
  return;
43008
43338
  }
43009
43339
  const analysis = analyzeSiteBannerBody(value.body);
43010
- for (const issue4 of analysis.issues) {
43340
+ for (const issue5 of analysis.issues) {
43011
43341
  ctx.addIssue({
43012
43342
  code: z.ZodIssueCode.custom,
43013
43343
  path: ["body"],
43014
- message: siteBannerBodyIssueMessage(issue4)
43344
+ message: siteBannerBodyIssueMessage(issue5)
43015
43345
  });
43016
43346
  }
43017
43347
  });
@@ -43045,8 +43375,8 @@ function analyzeSiteBannerBody(body) {
43045
43375
  issues
43046
43376
  };
43047
43377
  }
43048
- function siteBannerBodyIssueMessage(issue4) {
43049
- switch (issue4) {
43378
+ function siteBannerBodyIssueMessage(issue5) {
43379
+ switch (issue5) {
43050
43380
  case "empty":
43051
43381
  return "Banner message is required when the banner is enabled.";
43052
43382
  case "too-many-paragraphs":
@@ -43554,8 +43884,8 @@ var TEMPLATE_BINDING_META_PATHS = [
43554
43884
  "createdAt",
43555
43885
  "updatedAt"
43556
43886
  ];
43557
- function describeInvalidTemplateBindingMetaPath(path25) {
43558
- return `Meta path "${path25}" is not valid. Allowed: ${TEMPLATE_BINDING_META_PATHS.join(", ")}`;
43887
+ function describeInvalidTemplateBindingMetaPath(path27) {
43888
+ return `Meta path "${path27}" is not valid. Allowed: ${TEMPLATE_BINDING_META_PATHS.join(", ")}`;
43559
43889
  }
43560
43890
 
43561
43891
  // ../content-model/src/routeTemplate.ts
@@ -43729,7 +44059,7 @@ var fieldBindingSchema = z.object({
43729
44059
  var metaBindingSchema = z.object({
43730
44060
  source: z.literal("meta"),
43731
44061
  path: z.enum(TEMPLATE_BINDING_META_PATHS, {
43732
- error: (issue4) => describeInvalidTemplateBindingMetaPath(String(issue4.input))
44062
+ error: (issue5) => describeInvalidTemplateBindingMetaPath(String(issue5.input))
43733
44063
  })
43734
44064
  });
43735
44065
  var literalBindingSchema = z.object({
@@ -43740,7 +44070,7 @@ var transformBindingSchema = z.object({
43740
44070
  source: z.literal("transform"),
43741
44071
  path: z.string().min(1, "Transform path is required"),
43742
44072
  transform: z.enum(BINDING_TRANSFORM_VALUES, {
43743
- error: (issue4) => describeInvalidBindingTransform(String(issue4.input))
44073
+ error: (issue5) => describeInvalidBindingTransform(String(issue5.input))
43744
44074
  })
43745
44075
  });
43746
44076
  var baseBindingSchema = z.discriminatedUnion("source", [
@@ -43944,7 +44274,7 @@ var contentConfigSchema = contentConfigBaseSchema.superRefine((data, ctx) => {
43944
44274
  });
43945
44275
  }
43946
44276
  const paths = data.pages.map((p) => p.path);
43947
- const duplicatePaths = paths.filter((path25, i) => paths.indexOf(path25) !== i);
44277
+ const duplicatePaths = paths.filter((path27, i) => paths.indexOf(path27) !== i);
43948
44278
  if (duplicatePaths.length > 0) {
43949
44279
  ctx.addIssue({
43950
44280
  code: z.ZodIssueCode.custom,
@@ -44001,18 +44331,18 @@ function validateLayoutNodeTypes(layout) {
44001
44331
  errors
44002
44332
  };
44003
44333
  }
44004
- function validateNodeTypesRecursive(node, path25, errors) {
44334
+ function validateNodeTypesRecursive(node, path27, errors) {
44005
44335
  if (!ALLOWED_NODE_TYPES_SET.has(node.type)) {
44006
44336
  errors.push({
44007
- path: `${path25}.type`,
44337
+ path: `${path27}.type`,
44008
44338
  type: "invalid_node_type",
44009
44339
  value: node.type,
44010
- message: `Unknown node type "${node.type}" at ${path25}. Valid types: section, stack, text, etc.`
44340
+ message: `Unknown node type "${node.type}" at ${path27}. Valid types: section, stack, text, etc.`
44011
44341
  });
44012
44342
  }
44013
44343
  if (node.children && Array.isArray(node.children)) {
44014
44344
  node.children.forEach((child, index) => {
44015
- validateNodeTypesRecursive(child, `${path25}.children[${index}]`, errors);
44345
+ validateNodeTypesRecursive(child, `${path27}.children[${index}]`, errors);
44016
44346
  });
44017
44347
  }
44018
44348
  }
@@ -44024,45 +44354,45 @@ function validateTransformIds(layout) {
44024
44354
  errors
44025
44355
  };
44026
44356
  }
44027
- function validateTransformIdsRecursive(node, path25, errors) {
44357
+ function validateTransformIdsRecursive(node, path27, errors) {
44028
44358
  if (node.$bind?.transforms && Array.isArray(node.$bind.transforms)) {
44029
- validateTransformList(node.$bind.transforms, `${path25}.$bind.transforms`, errors);
44359
+ validateTransformList(node.$bind.transforms, `${path27}.$bind.transforms`, errors);
44030
44360
  }
44031
44361
  if (node.$repeat?.collection?.transforms && Array.isArray(node.$repeat.collection.transforms)) {
44032
- validateTransformList(node.$repeat.collection.transforms, `${path25}.$repeat.collection.transforms`, errors);
44362
+ validateTransformList(node.$repeat.collection.transforms, `${path27}.$repeat.collection.transforms`, errors);
44033
44363
  }
44034
44364
  if (node.$when?.when?.transforms && Array.isArray(node.$when.when.transforms)) {
44035
- validateTransformList(node.$when.when.transforms, `${path25}.$when.when.transforms`, errors);
44365
+ validateTransformList(node.$when.when.transforms, `${path27}.$when.when.transforms`, errors);
44036
44366
  }
44037
44367
  if (node.$scopes && Array.isArray(node.$scopes)) {
44038
44368
  node.$scopes.forEach((scope, index) => {
44039
44369
  if (scope.from?.transforms && Array.isArray(scope.from.transforms)) {
44040
- validateTransformList(scope.from.transforms, `${path25}.$scopes[${index}].from.transforms`, errors);
44370
+ validateTransformList(scope.from.transforms, `${path27}.$scopes[${index}].from.transforms`, errors);
44041
44371
  }
44042
44372
  });
44043
44373
  }
44044
44374
  if (node.props) {
44045
- validatePropsTransforms(node.props, `${path25}.props`, errors);
44375
+ validatePropsTransforms(node.props, `${path27}.props`, errors);
44046
44376
  }
44047
44377
  if (node.children && Array.isArray(node.children)) {
44048
44378
  node.children.forEach((child, index) => {
44049
- validateTransformIdsRecursive(child, `${path25}.children[${index}]`, errors);
44379
+ validateTransformIdsRecursive(child, `${path27}.children[${index}]`, errors);
44050
44380
  });
44051
44381
  }
44052
44382
  }
44053
- function validateTransformList(transforms, path25, errors) {
44383
+ function validateTransformList(transforms, path27, errors) {
44054
44384
  transforms.forEach((transform, index) => {
44055
44385
  if (!ALLOWED_TRANSFORM_IDS_SET.has(transform.id)) {
44056
44386
  errors.push({
44057
- path: `${path25}[${index}].id`,
44387
+ path: `${path27}[${index}].id`,
44058
44388
  type: "invalid_transform_id",
44059
44389
  value: transform.id,
44060
- message: `Unknown transform "${transform.id}" at ${path25}. Valid transforms: string.uppercase, value.fallback, etc.`
44390
+ message: `Unknown transform "${transform.id}" at ${path27}. Valid transforms: string.uppercase, value.fallback, etc.`
44061
44391
  });
44062
44392
  }
44063
44393
  });
44064
44394
  }
44065
- function validatePropsTransforms(props2, path25, errors) {
44395
+ function validatePropsTransforms(props2, path27, errors) {
44066
44396
  for (const [key, value] of Object.entries(props2)) {
44067
44397
  if (isBindingObject(value)) {
44068
44398
  const binding = value;
@@ -44070,16 +44400,16 @@ function validatePropsTransforms(props2, path25, errors) {
44070
44400
  binding.$bind.transforms.forEach((transform, index) => {
44071
44401
  if (!ALLOWED_TRANSFORM_IDS_SET.has(transform.id)) {
44072
44402
  errors.push({
44073
- path: `${path25}.${key}.$bind.transforms[${index}].id`,
44403
+ path: `${path27}.${key}.$bind.transforms[${index}].id`,
44074
44404
  type: "invalid_transform_id",
44075
44405
  value: transform.id,
44076
- message: `Unknown transform "${transform.id}" at ${path25}.${key}. Valid transforms: string.uppercase, value.fallback, etc.`
44406
+ message: `Unknown transform "${transform.id}" at ${path27}.${key}. Valid transforms: string.uppercase, value.fallback, etc.`
44077
44407
  });
44078
44408
  }
44079
44409
  });
44080
44410
  }
44081
44411
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
44082
- validatePropsTransforms(value, `${path25}.${key}`, errors);
44412
+ validatePropsTransforms(value, `${path27}.${key}`, errors);
44083
44413
  }
44084
44414
  }
44085
44415
  }
@@ -44125,21 +44455,6 @@ var titleSourceValueSchema = z.union([
44125
44455
  z.array(z.string().min(1)).min(1)
44126
44456
  ]);
44127
44457
 
44128
- // src/data/prefetchBlockData.ts
44129
- var SUPPORTED_LOADER_ENDPOINTS2 = [
44130
- "listPublishedEntries",
44131
- "getPublishedEntryPreview",
44132
- "listPublicEvents",
44133
- "listPublicCourses",
44134
- "listPublicTeamMembers",
44135
- "listPublicProducts",
44136
- "listPublicPasses",
44137
- "listPublicMemberships",
44138
- "getPublicFormById",
44139
- "getPublicBookingServices",
44140
- "getPublicEventDetails"
44141
- ];
44142
-
44143
44458
  // src/config/validation.ts
44144
44459
  var sdkThemePaletteSchema2 = z.record(z.string(), z.string());
44145
44460
  var sdkThemeConfigSchema2 = z.object({
@@ -44188,7 +44503,7 @@ var siteStyleConfigSchema = z.object({
44188
44503
  sectionOptions: sectionOptionsSchema,
44189
44504
  containerOptions: containerOptionsSchema
44190
44505
  }).optional();
44191
- var sdkLoaderEndpointSchema2 = z.enum(SUPPORTED_LOADER_ENDPOINTS2);
44506
+ var sdkLoaderEndpointSchema2 = z.enum(SUPPORTED_LOADER_ENDPOINTS);
44192
44507
  var allowedTransformIds = new Set(builtinTransformDefinitions.map((transform) => transform.id));
44193
44508
  var loaderTransformStepSchema = z.object({
44194
44509
  id: z.string().refine((id) => allowedTransformIds.has(id), {
@@ -44624,8 +44939,8 @@ async function readApiResponse(response, requestInfo, options = {}) {
44624
44939
  function createHttpClient(config2) {
44625
44940
  const baseUrl = `${config2.dashboardUrl}/api/sdk/${config2.siteId}`;
44626
44941
  const timeout = config2.timeout ?? 3e4;
44627
- async function request(method, path25, options) {
44628
- let url = `${baseUrl}${path25}`;
44942
+ async function request(method, path27, options) {
44943
+ let url = `${baseUrl}${path27}`;
44629
44944
  if (options?.params && Object.keys(options.params).length > 0) {
44630
44945
  const searchParams = new URLSearchParams(options.params);
44631
44946
  url = `${url}?${searchParams.toString()}`;
@@ -44648,7 +44963,7 @@ function createHttpClient(config2) {
44648
44963
  } catch (error) {
44649
44964
  const requestInfo2 = buildRequestInfo({
44650
44965
  method,
44651
- path: path25,
44966
+ path: path27,
44652
44967
  url,
44653
44968
  baseUrl,
44654
44969
  dashboardUrl: config2.dashboardUrl,
@@ -44673,7 +44988,7 @@ function createHttpClient(config2) {
44673
44988
  }
44674
44989
  const requestInfo = buildRequestInfo({
44675
44990
  method,
44676
- path: path25,
44991
+ path: path27,
44677
44992
  url,
44678
44993
  baseUrl,
44679
44994
  dashboardUrl: config2.dashboardUrl,
@@ -44703,17 +45018,17 @@ function createHttpClient(config2) {
44703
45018
  return json.data;
44704
45019
  }
44705
45020
  return {
44706
- async get(path25, params) {
44707
- return request("GET", path25, { params });
45021
+ async get(path27, params) {
45022
+ return request("GET", path27, { params });
44708
45023
  },
44709
- async post(path25, body) {
44710
- return request("POST", path25, { body });
45024
+ async post(path27, body) {
45025
+ return request("POST", path27, { body });
44711
45026
  },
44712
- async patch(path25, body) {
44713
- return request("PATCH", path25, { body });
45027
+ async patch(path27, body) {
45028
+ return request("PATCH", path27, { body });
44714
45029
  },
44715
- async delete(path25, body) {
44716
- await request("DELETE", path25, { body });
45030
+ async delete(path27, body) {
45031
+ await request("DELETE", path27, { body });
44717
45032
  }
44718
45033
  };
44719
45034
  }
@@ -46158,12 +46473,12 @@ function collectPushConfigSyncWarnings(sync) {
46158
46473
  async function pushToDashboard(output, dashboardUrl, siteId, apiKey, config2, options) {
46159
46474
  const normalizedDashboardUrl = dashboardUrl.replace(/\/+$/, "");
46160
46475
  const baseUrl = `${normalizedDashboardUrl}/api`;
46161
- const path25 = `/sites/${siteId}/sdk-config`;
46162
- const pushUrl = `${baseUrl}${path25}`;
46476
+ const path27 = `/sites/${siteId}/sdk-config`;
46477
+ const pushUrl = `${baseUrl}${path27}`;
46163
46478
  output.info(`Pushing config to ${pushUrl}...`);
46164
46479
  const requestInfo = {
46165
46480
  method: "POST",
46166
- path: path25,
46481
+ path: path27,
46167
46482
  url: pushUrl,
46168
46483
  baseUrl,
46169
46484
  dashboardUrl: normalizedDashboardUrl,
@@ -46233,9 +46548,9 @@ async function pushConfigAction(output, options) {
46233
46548
  const parseResult = riverbankSiteConfigSchema.safeParse(rawConfig);
46234
46549
  if (!parseResult.success) {
46235
46550
  output.error("Invalid config", {
46236
- issues: parseResult.error.issues.map((issue4) => ({
46237
- path: issue4.path.join("."),
46238
- message: issue4.message
46551
+ issues: parseResult.error.issues.map((issue5) => ({
46552
+ path: issue5.path.join("."),
46553
+ message: issue5.message
46239
46554
  }))
46240
46555
  });
46241
46556
  }
@@ -46942,23 +47257,7 @@ async function writeEvents(contentDir, pulledEvents, options) {
46942
47257
  const eventsMeta = {};
46943
47258
  for (const event of pulledEvents.events) {
46944
47259
  const filePath = path5.join(eventsDir, `${event.identifier}.json`);
46945
- const eventPayload = {
46946
- identifier: event.identifier,
46947
- title: event.title,
46948
- slug: event.slug,
46949
- status: event.status,
46950
- visibility: event.visibility,
46951
- schedule: event.schedule,
46952
- capacity: event.capacity,
46953
- pricing: event.pricing,
46954
- venueRef: event.venueRef,
46955
- categoryRef: event.categoryRef,
46956
- content: event.content,
46957
- formRef: event.formRef,
46958
- settings: event.settings,
46959
- presentation: event.presentation,
46960
- tags: event.tags
46961
- };
47260
+ const eventPayload = toWritableLocalEvent(event);
46962
47261
  stripEnvSpecificMediaFieldsInPlace(eventPayload);
46963
47262
  await writeJsonFile(filePath, eventPayload);
46964
47263
  filePaths.push(filePath);
@@ -46978,6 +47277,26 @@ async function writeEvents(contentDir, pulledEvents, options) {
46978
47277
  }
46979
47278
  return { filePaths, metaPath };
46980
47279
  }
47280
+ function toWritableLocalEvent(event) {
47281
+ return {
47282
+ identifier: event.identifier,
47283
+ title: event.title,
47284
+ slug: event.slug,
47285
+ status: event.status,
47286
+ visibility: event.visibility,
47287
+ schedule: event.schedule,
47288
+ capacity: event.capacity,
47289
+ pricing: event.pricing,
47290
+ paymentTerms: event.paymentTerms,
47291
+ venueRef: event.venueRef,
47292
+ categoryRef: event.categoryRef,
47293
+ content: event.content,
47294
+ formRef: event.formRef,
47295
+ settings: event.settings,
47296
+ presentation: event.presentation,
47297
+ tags: event.tags
47298
+ };
47299
+ }
46981
47300
  async function writeCourses(contentDir, pulledCourses, options) {
46982
47301
  const coursesDir = path5.join(contentDir, "courses");
46983
47302
  const metaDir = path5.join(contentDir, ".meta");
@@ -47315,7 +47634,7 @@ async function readSettings(contentDir) {
47315
47634
  throw new Error(
47316
47635
  `${filePath}: invalid settings.json
47317
47636
  ` + parsed.error.issues.map(
47318
- (issue4) => ` - ${issue4.path.join(".") || "(root)"}: ${issue4.message}`
47637
+ (issue5) => ` - ${issue5.path.join(".") || "(root)"}: ${issue5.message}`
47319
47638
  ).join("\n")
47320
47639
  );
47321
47640
  }
@@ -49033,11 +49352,11 @@ function findChangedFields(local, remote, prefix = "") {
49033
49352
  const changes = [];
49034
49353
  const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(remote)]);
49035
49354
  for (const key of allKeys) {
49036
- const path25 = prefix ? `${prefix}.${key}` : key;
49355
+ const path27 = prefix ? `${prefix}.${key}` : key;
49037
49356
  const localVal = local[key];
49038
49357
  const remoteVal = remote[key];
49039
49358
  if (!equal(localVal, remoteVal)) {
49040
- changes.push(path25);
49359
+ changes.push(path27);
49041
49360
  }
49042
49361
  }
49043
49362
  return changes;
@@ -50107,11 +50426,11 @@ function findChangedFieldsWithValues(local, remote, prefix = "") {
50107
50426
  const changes = [];
50108
50427
  const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(remote)]);
50109
50428
  for (const key of allKeys) {
50110
- const path25 = prefix ? `${prefix}.${key}` : key;
50429
+ const path27 = prefix ? `${prefix}.${key}` : key;
50111
50430
  const localVal = local[key];
50112
50431
  const remoteVal = remote[key];
50113
50432
  if (!equal(localVal, remoteVal)) {
50114
- changes.push({ path: path25, before: remoteVal, after: localVal });
50433
+ changes.push({ path: path27, before: remoteVal, after: localVal });
50115
50434
  }
50116
50435
  }
50117
50436
  return changes;
@@ -50528,6 +50847,117 @@ function maskPullDiffForScope(diff, pullScope) {
50528
50847
  }
50529
50848
  return diff;
50530
50849
  }
50850
+ var CANONICAL_EVENT_ENTRY_TYPE = "event";
50851
+ var EVENT_MIGRATION_COMMAND = "riverbankcms migrate events";
50852
+ var EVENT_PUSH_COMMAND = "riverbankcms push events";
50853
+ var EVENT_PULL_COMMAND = "riverbankcms pull events";
50854
+ var CANONICAL_ENTRY_POLICIES = [{
50855
+ contentType: CANONICAL_EVENT_ENTRY_TYPE,
50856
+ migrationCommand: EVENT_MIGRATION_COMMAND,
50857
+ commands: {
50858
+ push: EVENT_PUSH_COMMAND,
50859
+ pull: EVENT_PULL_COMMAND
50860
+ }
50861
+ }];
50862
+ function getCanonicalEntryPolicy(contentType) {
50863
+ const normalizedType = contentType?.trim().toLowerCase();
50864
+ return CANONICAL_ENTRY_POLICIES.find((policy) => policy.contentType === normalizedType) ?? null;
50865
+ }
50866
+ function buildScopeViolation(input) {
50867
+ const command = input.policy.commands[input.operation];
50868
+ return {
50869
+ contentType: input.policy.contentType,
50870
+ message: "`event` entries are managed through the canonical events surface.",
50871
+ suggestion: `Use "${command}" for event sync. If you still have content/entries/event/*.json files, run "${input.policy.migrationCommand}" to fold legacy event copy into content/events/*.json.`
50872
+ };
50873
+ }
50874
+ function getCanonicalEntrySyncDecision(input) {
50875
+ const normalizedScope = input.scope.toLowerCase();
50876
+ if (normalizedScope === "entries") {
50877
+ const scopedPolicy = getCanonicalEntryPolicy(input.contentType);
50878
+ if (scopedPolicy) {
50879
+ return {
50880
+ tag: "reject",
50881
+ violation: buildScopeViolation({ policy: scopedPolicy, operation: input.operation })
50882
+ };
50883
+ }
50884
+ if (!input.contentType) {
50885
+ return {
50886
+ tag: "allow-with-canonical-exclusions",
50887
+ policies: CANONICAL_ENTRY_POLICIES
50888
+ };
50889
+ }
50890
+ }
50891
+ if (normalizedScope === "all") {
50892
+ return {
50893
+ tag: "allow-with-canonical-exclusions",
50894
+ policies: CANONICAL_ENTRY_POLICIES
50895
+ };
50896
+ }
50897
+ return { tag: "allow" };
50898
+ }
50899
+ function shouldExcludeCanonicalEntries(decision) {
50900
+ return decision.tag === "allow-with-canonical-exclusions";
50901
+ }
50902
+ function filterGenericEntryContentTypes(contentTypes) {
50903
+ return contentTypes.filter((contentType) => !getCanonicalEntryPolicy(contentType));
50904
+ }
50905
+ function stripCanonicalEventEntriesFromLocalContent(content) {
50906
+ const eventEntries = content.entries.get(CANONICAL_EVENT_ENTRY_TYPE);
50907
+ if (!eventEntries) {
50908
+ return { content, removedEntryCount: 0, removedContentTypes: [] };
50909
+ }
50910
+ const entries = new Map(content.entries);
50911
+ entries.delete(CANONICAL_EVENT_ENTRY_TYPE);
50912
+ return {
50913
+ content: { ...content, entries },
50914
+ removedEntryCount: eventEntries.length,
50915
+ removedContentTypes: [CANONICAL_EVENT_ENTRY_TYPE]
50916
+ };
50917
+ }
50918
+ function stripCanonicalEventEntriesFromPulledContent(content) {
50919
+ const eventEntries = content.entries[CANONICAL_EVENT_ENTRY_TYPE];
50920
+ if (!eventEntries) {
50921
+ return { content, removedEntryCount: 0, removedContentTypes: [] };
50922
+ }
50923
+ const { [CANONICAL_EVENT_ENTRY_TYPE]: _removed, ...entries } = content.entries;
50924
+ const filteredMetaEntries = Object.fromEntries(
50925
+ Object.entries(content.meta.entries ?? {}).filter(([key]) => {
50926
+ const [contentType] = key.split(":");
50927
+ return contentType !== CANONICAL_EVENT_ENTRY_TYPE;
50928
+ })
50929
+ );
50930
+ return {
50931
+ content: {
50932
+ ...content,
50933
+ entries,
50934
+ meta: {
50935
+ ...content.meta,
50936
+ ...content.meta.entries ? { entries: filteredMetaEntries } : {}
50937
+ }
50938
+ },
50939
+ removedEntryCount: eventEntries.length,
50940
+ removedContentTypes: [CANONICAL_EVENT_ENTRY_TYPE]
50941
+ };
50942
+ }
50943
+ async function findLegacyEventEntryFiles(contentDir) {
50944
+ const eventEntriesDir = path5.join(contentDir, "entries", CANONICAL_EVENT_ENTRY_TYPE);
50945
+ try {
50946
+ const items = await fs5.readdir(eventEntriesDir, { withFileTypes: true });
50947
+ return items.filter((item) => item.isFile() && item.name.endsWith(".json")).map((item) => path5.join(eventEntriesDir, item.name)).sort();
50948
+ } catch (error) {
50949
+ if (error.code === "ENOENT") {
50950
+ return [];
50951
+ }
50952
+ throw error;
50953
+ }
50954
+ }
50955
+ function formatLegacyEventEntryWarning(files) {
50956
+ return {
50957
+ files: files.map((file) => path5.relative(process.cwd(), file)),
50958
+ suggestion: `Generic event entry files are ignored by broad sync. Run "${EVENT_MIGRATION_COMMAND}" to fold legacy event copy into content/events/*.json.`
50959
+ };
50960
+ }
50531
50961
  function findChangedTopLevelKeys(a, b) {
50532
50962
  const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
50533
50963
  const changed = [];
@@ -50879,6 +51309,17 @@ async function fetchAllContentPaginated(client, contentTypes, output, baseConten
50879
51309
  }
50880
51310
  };
50881
51311
  }
51312
+ async function pullAllContentWithCanonicalEntryPolicy(client, output) {
51313
+ const result = await client.pull.all();
51314
+ if (!result.meta.truncated) {
51315
+ return stripCanonicalEventEntriesFromPulledContent(result).content;
51316
+ }
51317
+ output.warn("Content was truncated due to size limits.");
51318
+ output.info("Fetching complete data via pagination...");
51319
+ const contentTypes = filterGenericEntryContentTypes(Object.keys(result.entries));
51320
+ const paginatedResult = await fetchAllContentPaginated(client, contentTypes, output, result);
51321
+ return stripCanonicalEventEntriesFromPulledContent(paginatedResult).content;
51322
+ }
50882
51323
  function createScopedPullContent(meta, overrides) {
50883
51324
  return {
50884
51325
  entries: {},
@@ -51011,6 +51452,30 @@ function shouldPromptForOverwrite(opts) {
51011
51452
  if (opts.force || opts.yes) return false;
51012
51453
  return true;
51013
51454
  }
51455
+ function emitCanonicalEntryScopeRejection(output, decision) {
51456
+ if (decision.tag !== "reject") {
51457
+ return false;
51458
+ }
51459
+ process.exitCode = 1;
51460
+ output.result(false, decision.violation.message, {
51461
+ contentType: decision.violation.contentType,
51462
+ suggestion: decision.violation.suggestion
51463
+ });
51464
+ return true;
51465
+ }
51466
+ async function warnForLocalLegacyEventEntries(input) {
51467
+ if (!shouldExcludeCanonicalEntries(input.decision) || !input.dirExists) {
51468
+ return;
51469
+ }
51470
+ const legacyEventEntryFiles = await findLegacyEventEntryFiles(input.contentDir);
51471
+ if (legacyEventEntryFiles.length === 0) {
51472
+ return;
51473
+ }
51474
+ input.output.warn(
51475
+ "Legacy event entry files detected and ignored by generic entry sync.",
51476
+ formatLegacyEventEntryWarning(legacyEventEntryFiles)
51477
+ );
51478
+ }
51014
51479
  var pullCommand = new Command("pull").description("Pull content from CMS").argument("[scope]", "What to pull: entries, pages, navigation, settings, forms, theme, footer, venues, event-categories, events, courses, or all (default)").argument("[type]", "Content type (entries) or page identifier (pages)").argument("[identifier]", 'Entry identifier (when scope is "entries" and type is set)').option("--output <dir>", "Output directory", "./content").option("--force", "Overwrite existing files without prompting").option("--yes", "Skip confirmation prompt (same as --force)").option("--sync-media", "Sync media files from source to target environment").option("--overwrite-media", "When using --sync-media, overwrite target media on checksum mismatch").option("--local-media", "Download media referenced by identifiers to content/media").option("--dry-run", "Show what would be pulled without writing files").option("--json-diff [mode]", "Output diff as JSON (summary or full)", "summary").option("--with-theme", "Also pull theme when pulling all content").option("--name <name>", "Theme name for theme pull / --with-theme (default: current)").option("--no-meta", "Skip writing .meta/ and media manifest files (content files still written)").option("--diff", "Show human-readable field-level diff with before/after values (requires --dry-run)").addHelpText("after", `
51015
51480
  Examples:
51016
51481
  $ riverbankcms pull # Pull all content
@@ -51102,6 +51567,20 @@ Media Sync:
51102
51567
  });
51103
51568
  return;
51104
51569
  }
51570
+ const canonicalEntrySyncDecision2 = getCanonicalEntrySyncDecision({
51571
+ scope: pullScope2,
51572
+ contentType: type,
51573
+ operation: "pull"
51574
+ });
51575
+ if (emitCanonicalEntryScopeRejection(output, canonicalEntrySyncDecision2)) {
51576
+ return;
51577
+ }
51578
+ await warnForLocalLegacyEventEntries({
51579
+ output,
51580
+ contentDir,
51581
+ decision: canonicalEntrySyncDecision2,
51582
+ dirExists: await contentDirExists(contentDir)
51583
+ });
51105
51584
  output.info(`[DRY RUN] Fetching content from ${envLabel}...`);
51106
51585
  if (options.withTheme && pullScope2 !== "all") {
51107
51586
  output.warn('--with-theme only applies when pulling all content (use "riverbankcms pull theme" instead)');
@@ -51308,13 +51787,7 @@ Media Sync:
51308
51787
  { entries: { [type]: pulled.entries } }
51309
51788
  );
51310
51789
  } else {
51311
- let result = await client.pull.all();
51312
- if (result.meta.truncated) {
51313
- output.warn("Content was truncated due to size limits.");
51314
- output.info("Fetching complete data via pagination...");
51315
- const contentTypes = Object.keys(result.entries);
51316
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51317
- }
51790
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51318
51791
  remoteContent = createScopedPullContent(result.meta, { entries: result.entries });
51319
51792
  }
51320
51793
  break;
@@ -51353,13 +51826,7 @@ Media Sync:
51353
51826
  `[DRY RUN] Would also pull theme to ${path5.join(path5.basename(contentDir), "themes", `${themeName}.json`)}`
51354
51827
  );
51355
51828
  }
51356
- let result = await client.pull.all();
51357
- if (result.meta.truncated) {
51358
- output.warn("Content was truncated due to size limits.");
51359
- output.info("Fetching complete data via pagination...");
51360
- const contentTypes = Object.keys(result.entries);
51361
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51362
- }
51829
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51363
51830
  remoteContent = result;
51364
51831
  break;
51365
51832
  }
@@ -51468,6 +51935,20 @@ Media Sync:
51468
51935
  });
51469
51936
  return;
51470
51937
  }
51938
+ const canonicalEntrySyncDecision = getCanonicalEntrySyncDecision({
51939
+ scope: pullScope,
51940
+ contentType: type,
51941
+ operation: "pull"
51942
+ });
51943
+ if (emitCanonicalEntryScopeRejection(output, canonicalEntrySyncDecision)) {
51944
+ return;
51945
+ }
51946
+ await warnForLocalLegacyEventEntries({
51947
+ output,
51948
+ contentDir,
51949
+ decision: canonicalEntrySyncDecision,
51950
+ dirExists
51951
+ });
51471
51952
  if (shouldPromptForOverwrite({
51472
51953
  pullScope,
51473
51954
  contentDirExists: dirExists,
@@ -51577,13 +52058,7 @@ Media Sync:
51577
52058
  });
51578
52059
  } else {
51579
52060
  output.info("Pulling all entries");
51580
- let result = await client.pull.all();
51581
- if (result.meta.truncated) {
51582
- output.warn("Content was truncated due to size limits.");
51583
- output.info("Fetching complete data via pagination...");
51584
- const contentTypes = Object.keys(result.entries);
51585
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51586
- }
52061
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51587
52062
  const mediaContent = createScopedPullContent(result.meta, { entries: result.entries });
51588
52063
  await applyMediaIdentifiers(mediaContent);
51589
52064
  await syncMediaIfRequested(mediaContent);
@@ -51730,13 +52205,7 @@ Media Sync:
51730
52205
  case "all":
51731
52206
  default: {
51732
52207
  output.info("Pulling all content");
51733
- let result = await client.pull.all();
51734
- if (result.meta.truncated) {
51735
- output.warn("Content was truncated due to size limits.");
51736
- output.info("Fetching complete data via pagination...");
51737
- const contentTypes = Object.keys(result.entries);
51738
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51739
- }
52208
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51740
52209
  result.settingsWarnings?.forEach((warning) => output.warn(warning));
51741
52210
  await applyMediaIdentifiers(result);
51742
52211
  await syncMediaIfRequested(result);
@@ -52118,8 +52587,8 @@ function normalizeLocalContentShape(content) {
52118
52587
  var identifierRegex = /^[a-z0-9][a-z0-9-]*$/;
52119
52588
  var currencyRegex = /^[A-Z]{3}$/;
52120
52589
  var isoDateTimeRegex = /^\d{4}-\d{2}-\d{2}T.+/;
52121
- function issue2(path25, message) {
52122
- return { path: path25, message };
52590
+ function issue2(path27, message) {
52591
+ return { path: path27, message };
52123
52592
  }
52124
52593
  function isRecord15(value) {
52125
52594
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -52136,27 +52605,27 @@ function isWholeMinuteIsoDateTime(value) {
52136
52605
  return Number.isFinite(epochMs) && epochMs % 6e4 === 0;
52137
52606
  }
52138
52607
  function validateTicketType(raw, index, currency) {
52139
- const path25 = ["ticketTypes", String(index)];
52140
- if (!isRecord15(raw)) return [issue2(path25, "Ticket type must be an object")];
52608
+ const path27 = ["ticketTypes", String(index)];
52609
+ if (!isRecord15(raw)) return [issue2(path27, "Ticket type must be an object")];
52141
52610
  const issues = [];
52142
52611
  const identifier = raw.identifier;
52143
52612
  if (typeof identifier !== "string" || !identifierRegex.test(identifier)) {
52144
52613
  issues.push(
52145
52614
  issue2(
52146
- [...path25, "identifier"],
52615
+ [...path27, "identifier"],
52147
52616
  "Ticket identifier must use lowercase letters, numbers, and hyphens"
52148
52617
  )
52149
52618
  );
52150
52619
  }
52151
52620
  const name = raw.name;
52152
52621
  if (typeof name !== "string" || name.trim().length === 0) {
52153
- issues.push(issue2([...path25, "name"], "Ticket name is required"));
52622
+ issues.push(issue2([...path27, "name"], "Ticket name is required"));
52154
52623
  }
52155
52624
  const priceAmount = raw.priceAmount;
52156
52625
  if (!isWholeNumber(priceAmount) || priceAmount < 0) {
52157
52626
  issues.push(
52158
52627
  issue2(
52159
- [...path25, "priceAmount"],
52628
+ [...path27, "priceAmount"],
52160
52629
  "Ticket priceAmount must be a non-negative integer"
52161
52630
  )
52162
52631
  );
@@ -52165,7 +52634,7 @@ function validateTicketType(raw, index, currency) {
52165
52634
  if (priceCurrency !== void 0 && priceCurrency !== null && priceCurrency !== currency) {
52166
52635
  issues.push(
52167
52636
  issue2(
52168
- [...path25, "priceCurrency"],
52637
+ [...path27, "priceCurrency"],
52169
52638
  "Ticket priceCurrency must match pricing.priceCurrency"
52170
52639
  )
52171
52640
  );
@@ -52174,7 +52643,7 @@ function validateTicketType(raw, index, currency) {
52174
52643
  if (sortOrder !== void 0 && (!isWholeNumber(sortOrder) || sortOrder < 0)) {
52175
52644
  issues.push(
52176
52645
  issue2(
52177
- [...path25, "sortOrder"],
52646
+ [...path27, "sortOrder"],
52178
52647
  "Ticket sortOrder must be a non-negative integer"
52179
52648
  )
52180
52649
  );
@@ -52183,7 +52652,7 @@ function validateTicketType(raw, index, currency) {
52183
52652
  if (capacityLimit2 !== void 0 && capacityLimit2 !== null && (!isWholeNumber(capacityLimit2) || capacityLimit2 < 1)) {
52184
52653
  issues.push(
52185
52654
  issue2(
52186
- [...path25, "capacityLimit"],
52655
+ [...path27, "capacityLimit"],
52187
52656
  "Ticket capacityLimit must be a positive integer"
52188
52657
  )
52189
52658
  );
@@ -52192,7 +52661,7 @@ function validateTicketType(raw, index, currency) {
52192
52661
  if (attendanceScope !== void 0 && attendanceScope !== "in_person" && attendanceScope !== "online" && attendanceScope !== "both") {
52193
52662
  issues.push(
52194
52663
  issue2(
52195
- [...path25, "attendanceScope"],
52664
+ [...path27, "attendanceScope"],
52196
52665
  "Ticket attendanceScope must be in_person, online, or both"
52197
52666
  )
52198
52667
  );
@@ -52201,7 +52670,7 @@ function validateTicketType(raw, index, currency) {
52201
52670
  if (saleStartsAt !== void 0 && saleStartsAt !== null && (typeof saleStartsAt !== "string" || !isWholeMinuteIsoDateTime(saleStartsAt))) {
52202
52671
  issues.push(
52203
52672
  issue2(
52204
- [...path25, "saleStartsAt"],
52673
+ [...path27, "saleStartsAt"],
52205
52674
  "Ticket saleStartsAt must be an ISO datetime aligned to a whole minute"
52206
52675
  )
52207
52676
  );
@@ -52210,7 +52679,7 @@ function validateTicketType(raw, index, currency) {
52210
52679
  if (saleEndsAt !== void 0 && saleEndsAt !== null && (typeof saleEndsAt !== "string" || !isWholeMinuteIsoDateTime(saleEndsAt))) {
52211
52680
  issues.push(
52212
52681
  issue2(
52213
- [...path25, "saleEndsAt"],
52682
+ [...path27, "saleEndsAt"],
52214
52683
  "Ticket saleEndsAt must be an ISO datetime aligned to a whole minute"
52215
52684
  )
52216
52685
  );
@@ -52218,7 +52687,7 @@ function validateTicketType(raw, index, currency) {
52218
52687
  if (typeof saleStartsAt === "string" && typeof saleEndsAt === "string" && Date.parse(saleEndsAt) <= Date.parse(saleStartsAt)) {
52219
52688
  issues.push(
52220
52689
  issue2(
52221
- [...path25, "saleEndsAt"],
52690
+ [...path27, "saleEndsAt"],
52222
52691
  "Ticket saleEndsAt must be after saleStartsAt"
52223
52692
  )
52224
52693
  );
@@ -52227,7 +52696,7 @@ function validateTicketType(raw, index, currency) {
52227
52696
  if (cmsTicketTypeId !== void 0 && cmsTicketTypeId !== null && (typeof cmsTicketTypeId !== "string" || cmsTicketTypeId.length === 0)) {
52228
52697
  issues.push(
52229
52698
  issue2(
52230
- [...path25, "cmsTicketTypeId"],
52699
+ [...path27, "cmsTicketTypeId"],
52231
52700
  "Ticket cmsTicketTypeId must be a non-empty string"
52232
52701
  )
52233
52702
  );
@@ -52405,11 +52874,239 @@ function classifySdkEventPricing(rawInput) {
52405
52874
  }
52406
52875
  }
52407
52876
 
52877
+ // ../api/src/sdk-event-payment-terms.ts
52878
+ var supportedKinds = /* @__PURE__ */ new Set([
52879
+ "upfront",
52880
+ "deferred_manual",
52881
+ "flexible_balance"
52882
+ ]);
52883
+ function issue3(path27, message) {
52884
+ return { path: path27, message };
52885
+ }
52886
+ function isRecord16(value) {
52887
+ return typeof value === "object" && value !== null && !Array.isArray(value);
52888
+ }
52889
+ function isWholeNumber2(value) {
52890
+ return typeof value === "number" && Number.isInteger(value);
52891
+ }
52892
+ function isPositiveWholeNumber(value) {
52893
+ return isWholeNumber2(value) && value > 0;
52894
+ }
52895
+ function isDepositRefundability(value) {
52896
+ return value === "refundable" || value === "non_refundable";
52897
+ }
52898
+ function isSupportedOptionKind(value) {
52899
+ return typeof value === "string" && supportedKinds.has(value);
52900
+ }
52901
+ function validateFlexibleBalanceDueDateRule(raw, path27) {
52902
+ if (!isRecord16(raw)) {
52903
+ return [issue3(path27, "Flexible balance dueDateRule must be an object")];
52904
+ }
52905
+ if (raw.kind === "relative_to_start_date") {
52906
+ if (!isPositiveWholeNumber(raw.daysBeforeStart)) {
52907
+ return [
52908
+ issue3(
52909
+ [...path27, "daysBeforeStart"],
52910
+ "Flexible balance daysBeforeStart must be a positive integer"
52911
+ )
52912
+ ];
52913
+ }
52914
+ return {
52915
+ kind: "relative_to_start_date",
52916
+ daysBeforeStart: raw.daysBeforeStart
52917
+ };
52918
+ }
52919
+ if (raw.kind === "fixed_calendar_date") {
52920
+ if (typeof raw.dueAt !== "string" || !Number.isFinite(Date.parse(raw.dueAt))) {
52921
+ return [
52922
+ issue3(
52923
+ [...path27, "dueAt"],
52924
+ "Flexible balance fixed dueAt must be an ISO datetime"
52925
+ )
52926
+ ];
52927
+ }
52928
+ return {
52929
+ kind: "fixed_calendar_date",
52930
+ dueAt: raw.dueAt
52931
+ };
52932
+ }
52933
+ return [
52934
+ issue3(
52935
+ [...path27, "kind"],
52936
+ "Flexible balance dueDateRule kind must be relative_to_start_date or fixed_calendar_date"
52937
+ )
52938
+ ];
52939
+ }
52940
+ function validateFlexibleBalanceConfig(raw, path27) {
52941
+ if (!isRecord16(raw)) {
52942
+ return [issue3(path27, "Flexible balance config must be an object")];
52943
+ }
52944
+ const issues = [];
52945
+ const upfrontAmountCents = raw.upfrontAmountCents;
52946
+ const depositRefundability = raw.depositRefundability;
52947
+ let validatedUpfrontAmountCents = null;
52948
+ let validatedDepositRefundability = null;
52949
+ if (!isWholeNumber2(upfrontAmountCents) || upfrontAmountCents < 0) {
52950
+ issues.push(
52951
+ issue3(
52952
+ [...path27, "upfrontAmountCents"],
52953
+ "Flexible balance upfrontAmountCents must be a non-negative integer"
52954
+ )
52955
+ );
52956
+ } else {
52957
+ validatedUpfrontAmountCents = upfrontAmountCents;
52958
+ }
52959
+ if (!isDepositRefundability(depositRefundability)) {
52960
+ issues.push(
52961
+ issue3(
52962
+ [...path27, "depositRefundability"],
52963
+ "Flexible balance depositRefundability must be refundable or non_refundable"
52964
+ )
52965
+ );
52966
+ } else {
52967
+ validatedDepositRefundability = depositRefundability;
52968
+ }
52969
+ const dueDateRule = validateFlexibleBalanceDueDateRule(
52970
+ raw.dueDateRule,
52971
+ [...path27, "dueDateRule"]
52972
+ );
52973
+ if (Array.isArray(dueDateRule)) {
52974
+ issues.push(...dueDateRule);
52975
+ }
52976
+ if (issues.length > 0 || Array.isArray(dueDateRule) || validatedUpfrontAmountCents === null || validatedDepositRefundability === null) {
52977
+ return issues;
52978
+ }
52979
+ return {
52980
+ upfrontAmountCents: validatedUpfrontAmountCents,
52981
+ depositRefundability: validatedDepositRefundability,
52982
+ dueDateRule
52983
+ };
52984
+ }
52985
+ function validateCollectionOption(raw, index) {
52986
+ const path27 = ["allowedOptions", String(index)];
52987
+ if (!isRecord16(raw)) {
52988
+ return [issue3(path27, "Payment option must be an object")];
52989
+ }
52990
+ if (raw.kind === "instalment_plan") {
52991
+ return [
52992
+ issue3(
52993
+ [...path27, "kind"],
52994
+ "Event instalment plans are not supported yet. Use upfront, deferred_manual, or flexible_balance."
52995
+ )
52996
+ ];
52997
+ }
52998
+ if (!isSupportedOptionKind(raw.kind)) {
52999
+ return [
53000
+ issue3(
53001
+ [...path27, "kind"],
53002
+ "Payment option kind must be upfront, deferred_manual, or flexible_balance"
53003
+ )
53004
+ ];
53005
+ }
53006
+ switch (raw.kind) {
53007
+ case "upfront":
53008
+ case "deferred_manual":
53009
+ return { kind: raw.kind };
53010
+ case "flexible_balance": {
53011
+ const config2 = validateFlexibleBalanceConfig(raw.config, [
53012
+ ...path27,
53013
+ "config"
53014
+ ]);
53015
+ if (Array.isArray(config2)) {
53016
+ return config2;
53017
+ }
53018
+ return { kind: "flexible_balance", config: config2 };
53019
+ }
53020
+ }
53021
+ }
53022
+ function optionCombinationIssues(options) {
53023
+ const issues = [];
53024
+ const seenKinds = /* @__PURE__ */ new Set();
53025
+ options.forEach((option, index) => {
53026
+ if (seenKinds.has(option.kind)) {
53027
+ issues.push(
53028
+ issue3(
53029
+ ["allowedOptions", String(index), "kind"],
53030
+ `Duplicate payment option kind "${option.kind}"`
53031
+ )
53032
+ );
53033
+ }
53034
+ seenKinds.add(option.kind);
53035
+ });
53036
+ if (options.length > 2) {
53037
+ issues.push(
53038
+ issue3(
53039
+ ["allowedOptions"],
53040
+ "Event payment terms can offer one option, or a choice between upfront and one alternative option"
53041
+ )
53042
+ );
53043
+ }
53044
+ if (options.length === 2 && (!seenKinds.has("upfront") || !seenKinds.has("deferred_manual") && !seenKinds.has("flexible_balance"))) {
53045
+ issues.push(
53046
+ issue3(
53047
+ ["allowedOptions"],
53048
+ "Event payment terms with two options must combine upfront with deferred_manual or flexible_balance"
53049
+ )
53050
+ );
53051
+ }
53052
+ return issues;
53053
+ }
53054
+ function classifySdkEventPaymentTerms(rawInput) {
53055
+ if (rawInput === void 0 || rawInput === null) {
53056
+ return { ok: true, paymentTerms: void 0 };
53057
+ }
53058
+ if (!isRecord16(rawInput)) {
53059
+ return {
53060
+ ok: false,
53061
+ issues: [issue3([], "Event paymentTerms must be an object")]
53062
+ };
53063
+ }
53064
+ if (!Array.isArray(rawInput.allowedOptions)) {
53065
+ return {
53066
+ ok: false,
53067
+ issues: [
53068
+ issue3(["allowedOptions"], "Event paymentTerms.allowedOptions is required")
53069
+ ]
53070
+ };
53071
+ }
53072
+ if (rawInput.allowedOptions.length === 0) {
53073
+ return {
53074
+ ok: false,
53075
+ issues: [
53076
+ issue3(
53077
+ ["allowedOptions"],
53078
+ "Event paymentTerms.allowedOptions must include at least one option"
53079
+ )
53080
+ ]
53081
+ };
53082
+ }
53083
+ const options = [];
53084
+ const issues = [];
53085
+ rawInput.allowedOptions.forEach((option, index) => {
53086
+ const validated = validateCollectionOption(option, index);
53087
+ if (Array.isArray(validated)) {
53088
+ issues.push(...validated);
53089
+ return;
53090
+ }
53091
+ options.push(validated);
53092
+ });
53093
+ issues.push(...optionCombinationIssues(options));
53094
+ if (issues.length > 0) {
53095
+ return { ok: false, issues };
53096
+ }
53097
+ return {
53098
+ ok: true,
53099
+ paymentTerms: {
53100
+ allowedOptions: options
53101
+ }
53102
+ };
53103
+ }
53104
+
52408
53105
  // src/cli/commands/push/pushAllExtras.ts
52409
53106
  function nullishToNull(value) {
52410
53107
  return value == null ? null : value;
52411
53108
  }
52412
- function isRecord16(value) {
53109
+ function isRecord17(value) {
52413
53110
  return typeof value === "object" && value !== null && !Array.isArray(value);
52414
53111
  }
52415
53112
  function stringValue(value, fallback) {
@@ -52424,8 +53121,13 @@ function normalizeEventPricingForCompare(pricing) {
52424
53121
  if (result.ok) return result.pricing;
52425
53122
  return { kind: "free" };
52426
53123
  }
53124
+ function normalizeEventPaymentTermsForCompare(paymentTerms) {
53125
+ const result = classifySdkEventPaymentTerms(paymentTerms);
53126
+ if (result.ok) return result.paymentTerms;
53127
+ return void 0;
53128
+ }
52427
53129
  function normalizeVenueAddress(value) {
52428
- const obj = isRecord16(value) ? value : {};
53130
+ const obj = isRecord17(value) ? value : {};
52429
53131
  return {
52430
53132
  line1: nullishToNull(typeof obj.line1 === "string" ? obj.line1 : void 0),
52431
53133
  line2: nullishToNull(typeof obj.line2 === "string" ? obj.line2 : void 0),
@@ -52442,7 +53144,7 @@ function normalizeVenueAddress(value) {
52442
53144
  };
52443
53145
  }
52444
53146
  function normalizeVenueLocation(value) {
52445
- if (!isRecord16(value)) return null;
53147
+ if (!isRecord17(value)) return null;
52446
53148
  const obj = value;
52447
53149
  const lat = typeof obj.lat === "number" ? obj.lat : null;
52448
53150
  const lng = typeof obj.lng === "number" ? obj.lng : null;
@@ -52450,7 +53152,7 @@ function normalizeVenueLocation(value) {
52450
53152
  return { lat, lng };
52451
53153
  }
52452
53154
  function normalizeVenueForCompare(venue) {
52453
- const obj = isRecord16(venue) ? venue : {};
53155
+ const obj = isRecord17(venue) ? venue : {};
52454
53156
  return {
52455
53157
  slug: String(obj.slug),
52456
53158
  title: String(obj.title),
@@ -52471,7 +53173,7 @@ function normalizeVenueForCompare(venue) {
52471
53173
  };
52472
53174
  }
52473
53175
  function normalizeEventCategoryForCompare(category) {
52474
- const obj = isRecord16(category) ? category : {};
53176
+ const obj = isRecord17(category) ? category : {};
52475
53177
  return {
52476
53178
  identifier: String(obj.identifier),
52477
53179
  name: String(obj.name),
@@ -52483,8 +53185,8 @@ function normalizeEventCategoryForCompare(category) {
52483
53185
  };
52484
53186
  }
52485
53187
  function normalizeRemoteEventForCompare(event) {
52486
- const obj = isRecord16(event) ? event : {};
52487
- const schedule = isRecord16(obj.schedule) ? obj.schedule : {};
53188
+ const obj = isRecord17(event) ? event : {};
53189
+ const schedule = isRecord17(obj.schedule) ? obj.schedule : {};
52488
53190
  return {
52489
53191
  identifier: String(obj.identifier),
52490
53192
  title: String(obj.title),
@@ -52503,6 +53205,7 @@ function normalizeRemoteEventForCompare(event) {
52503
53205
  typeof obj.capacity === "number" ? obj.capacity : void 0
52504
53206
  ),
52505
53207
  pricing: normalizeEventPricingForCompare(obj.pricing),
53208
+ paymentTerms: normalizeEventPaymentTermsForCompare(obj.paymentTerms),
52506
53209
  venueRef: nullishToNull(
52507
53210
  typeof obj.venueRef === "string" ? obj.venueRef : void 0
52508
53211
  ),
@@ -52512,14 +53215,14 @@ function normalizeRemoteEventForCompare(event) {
52512
53215
  formRef: nullishToNull(
52513
53216
  typeof obj.formRef === "string" ? obj.formRef : void 0
52514
53217
  ),
52515
- content: isRecord16(obj.content) ? obj.content : {},
52516
- settings: isRecord16(obj.settings) ? obj.settings : {},
52517
- presentation: isRecord16(obj.presentation) ? obj.presentation : null,
53218
+ content: isRecord17(obj.content) ? obj.content : {},
53219
+ settings: isRecord17(obj.settings) ? obj.settings : {},
53220
+ presentation: isRecord17(obj.presentation) ? obj.presentation : null,
52518
53221
  tags: Array.isArray(obj.tags) ? obj.tags : []
52519
53222
  };
52520
53223
  }
52521
53224
  function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52522
- const local = isRecord16(localEvent) ? localEvent : {};
53225
+ const local = isRecord17(localEvent) ? localEvent : {};
52523
53226
  const base = remoteEvent ? normalizeRemoteEventForCompare(remoteEvent) : normalizeRemoteEventForCompare({
52524
53227
  identifier: local.identifier,
52525
53228
  title: local.title,
@@ -52528,6 +53231,7 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52528
53231
  visibility: local.visibility ?? "private",
52529
53232
  schedule: local.schedule ?? {},
52530
53233
  pricing: local.pricing ?? {},
53234
+ paymentTerms: local.paymentTerms,
52531
53235
  capacity: local.capacity ?? null,
52532
53236
  venueRef: local.venueRef ?? null,
52533
53237
  categoryRef: local.categoryRef ?? null,
@@ -52537,7 +53241,7 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52537
53241
  presentation: local.presentation ?? null,
52538
53242
  tags: local.tags ?? []
52539
53243
  });
52540
- const schedule = isRecord16(local.schedule) ? local.schedule : {};
53244
+ const schedule = isRecord17(local.schedule) ? local.schedule : {};
52541
53245
  return {
52542
53246
  ...base,
52543
53247
  identifier: stringValue(local.identifier, base.identifier),
@@ -52558,6 +53262,7 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52558
53262
  typeof local.capacity === "number" ? local.capacity : void 0
52559
53263
  ),
52560
53264
  pricing: local.pricing === void 0 ? base.pricing : normalizeEventPricingForCompare(local.pricing),
53265
+ paymentTerms: local.paymentTerms === void 0 ? base.paymentTerms : normalizeEventPaymentTermsForCompare(local.paymentTerms),
52561
53266
  venueRef: local.venueRef === void 0 ? base.venueRef : nullishToNull(
52562
53267
  typeof local.venueRef === "string" ? local.venueRef : void 0
52563
53268
  ),
@@ -52567,9 +53272,9 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52567
53272
  formRef: local.formRef === void 0 ? base.formRef : nullishToNull(
52568
53273
  typeof local.formRef === "string" ? local.formRef : void 0
52569
53274
  ),
52570
- content: local.content === void 0 ? base.content : isRecord16(local.content) ? local.content : {},
52571
- settings: local.settings === void 0 ? base.settings : isRecord16(local.settings) ? local.settings : {},
52572
- presentation: local.presentation === void 0 ? base.presentation : isRecord16(local.presentation) ? local.presentation : null,
53275
+ content: local.content === void 0 ? base.content : isRecord17(local.content) ? local.content : {},
53276
+ settings: local.settings === void 0 ? base.settings : isRecord17(local.settings) ? local.settings : {},
53277
+ presentation: local.presentation === void 0 ? base.presentation : isRecord17(local.presentation) ? local.presentation : null,
52573
53278
  tags: local.tags === void 0 ? base.tags : Array.isArray(local.tags) ? local.tags : []
52574
53279
  };
52575
53280
  }
@@ -52581,7 +53286,7 @@ function toIsoStringOrOriginal(value) {
52581
53286
  function normalizeCourseSessions(value) {
52582
53287
  if (!Array.isArray(value)) return [];
52583
53288
  return value.map((session) => {
52584
- const obj = isRecord16(session) ? session : {};
53289
+ const obj = isRecord17(session) ? session : {};
52585
53290
  return {
52586
53291
  startsAt: toIsoStringOrOriginal(obj.startsAt),
52587
53292
  endsAt: toIsoStringOrOriginal(obj.endsAt)
@@ -52593,18 +53298,18 @@ function normalizeCourseSessions(value) {
52593
53298
  }
52594
53299
  function normalizeCourseProgram(value) {
52595
53300
  if (value == null) return null;
52596
- if (!isRecord16(value)) {
53301
+ if (!isRecord17(value)) {
52597
53302
  return { identifier: null, data: {} };
52598
53303
  }
52599
53304
  return {
52600
53305
  identifier: nullishToNull(
52601
53306
  typeof value.identifier === "string" ? value.identifier : void 0
52602
53307
  ),
52603
- data: isRecord16(value.data) ? value.data : {}
53308
+ data: isRecord17(value.data) ? value.data : {}
52604
53309
  };
52605
53310
  }
52606
53311
  function normalizeRemoteCourseForCompare(course) {
52607
- const obj = isRecord16(course) ? course : {};
53312
+ const obj = isRecord17(course) ? course : {};
52608
53313
  return {
52609
53314
  identifier: String(obj.identifier),
52610
53315
  title: String(obj.title),
@@ -52639,7 +53344,7 @@ function normalizeRemoteCourseForCompare(course) {
52639
53344
  };
52640
53345
  }
52641
53346
  function normalizeLocalCourseAgainstRemoteForCompare(localCourse, remoteCourse) {
52642
- const local = isRecord16(localCourse) ? localCourse : {};
53347
+ const local = isRecord17(localCourse) ? localCourse : {};
52643
53348
  const base = remoteCourse ? normalizeRemoteCourseForCompare(remoteCourse) : normalizeRemoteCourseForCompare({
52644
53349
  identifier: local.identifier,
52645
53350
  title: local.title,
@@ -52660,11 +53365,11 @@ function normalizeLocalCourseAgainstRemoteForCompare(localCourse, remoteCourse)
52660
53365
  });
52661
53366
  const status = local.status === void 0 ? base.status : local.status === "active" || local.status === "cancelled" || local.status === "completed" ? local.status : "draft";
52662
53367
  const visibility = local.visibility === void 0 ? base.visibility : local.visibility === "public" || local.visibility === "private" || local.visibility === "unlisted" ? local.visibility : "public";
52663
- const program2 = local.program === void 0 ? base.program : local.program === null ? null : isRecord16(local.program) ? {
53368
+ const program2 = local.program === void 0 ? base.program : local.program === null ? null : isRecord17(local.program) ? {
52664
53369
  identifier: local.program.identifier === void 0 ? base.program?.identifier ?? null : nullishToNull(
52665
53370
  typeof local.program.identifier === "string" ? local.program.identifier : void 0
52666
53371
  ),
52667
- data: isRecord16(local.program.data) ? local.program.data : base.program?.data ?? {}
53372
+ data: isRecord17(local.program.data) ? local.program.data : base.program?.data ?? {}
52668
53373
  } : base.program;
52669
53374
  return {
52670
53375
  ...base,
@@ -53333,9 +54038,24 @@ var fixedPriceIntentSchema = z.object({
53333
54038
  kind: z.literal("fixed_price"),
53334
54039
  price: moneyAmountSchema
53335
54040
  }).strict();
54041
+ var inlineEventTicketTypeSchema = z.object({
54042
+ identifier: recipeIdentifierSchema,
54043
+ cmsTicketTypeId: z.string().min(1).nullable().optional(),
54044
+ name: z.string().min(1),
54045
+ description: z.string().nullable().optional(),
54046
+ priceAmount: nonNegativeIntegerSchema,
54047
+ priceCurrency: currencySchema.optional(),
54048
+ isActive: z.boolean().optional(),
54049
+ sortOrder: nonNegativeIntegerSchema.optional(),
54050
+ capacityLimit: positiveIntegerSchema.nullable().optional(),
54051
+ attendanceScope: z.enum(["in_person", "online", "both"]).optional(),
54052
+ saleStartsAt: isoDateTimeSchema.nullable().optional(),
54053
+ saleEndsAt: isoDateTimeSchema.nullable().optional()
54054
+ }).strict();
53336
54055
  var ticketTypesPricingIntentSchema = z.object({
53337
54056
  kind: z.literal("ticket_types"),
53338
- currency: currencySchema.optional()
54057
+ currency: currencySchema.optional(),
54058
+ ticketTypes: z.array(inlineEventTicketTypeSchema).readonly().optional()
53339
54059
  }).strict();
53340
54060
  var manualPaymentPricingIntentSchema = z.object({
53341
54061
  kind: z.literal("manual_payment"),
@@ -53780,6 +54500,7 @@ var upsertEventSeriesCommandSchema = z.object({
53780
54500
  occurrences: z.array(eventOccurrenceSchema).min(1).readonly(),
53781
54501
  content: contentSummarySchema.optional(),
53782
54502
  settings: unknownRecordSchema.optional(),
54503
+ paymentTerms: z.unknown().optional(),
53783
54504
  presentation: unknownRecordSchema.nullable().optional(),
53784
54505
  tags: z.array(z.string()).readonly().optional(),
53785
54506
  staffRefs: z.array(staffRefSchema).readonly().optional()
@@ -54899,7 +55620,7 @@ function getSiteCommandLifecycleIntent(command) {
54899
55620
  init_src();
54900
55621
 
54901
55622
  // ../site-commands/src/guards.ts
54902
- function isRecord17(value) {
55623
+ function isRecord18(value) {
54903
55624
  return typeof value === "object" && value !== null;
54904
55625
  }
54905
55626
 
@@ -55159,13 +55880,13 @@ function collectOfferingRequires(input, intervals, intervalPath) {
55159
55880
  function optionalRef(ref, field) {
55160
55881
  return ref ? [{ ref, field }] : [];
55161
55882
  }
55162
- function collectVenueRefsFromIntervals(intervals, path25) {
55163
- return intervals.flatMap((interval, index) => optionalRef(interval.venueRef, `${path25}[${index}].venueRef`));
55883
+ function collectVenueRefsFromIntervals(intervals, path27) {
55884
+ return intervals.flatMap((interval, index) => optionalRef(interval.venueRef, `${path27}[${index}].venueRef`));
55164
55885
  }
55165
- function collectNavigationRefs(items, path25) {
55886
+ function collectNavigationRefs(items, path27) {
55166
55887
  return items.flatMap((item, index) => {
55167
- if (!isRecord17(item)) return [];
55168
- const itemPath = `${path25}[${index}]`;
55888
+ if (!isRecord18(item)) return [];
55889
+ const itemPath = `${path27}[${index}]`;
55169
55890
  const refs = [];
55170
55891
  if (typeof item.pageRef === "string") {
55171
55892
  refs.push({ ref: item.pageRef, field: `${itemPath}.pageRef` });
@@ -55179,26 +55900,26 @@ function collectNavigationRefs(items, path25) {
55179
55900
  return refs;
55180
55901
  });
55181
55902
  }
55182
- function collectBlockRefs(blocks, path25) {
55903
+ function collectBlockRefs(blocks, path27) {
55183
55904
  return blocks.flatMap((block, index) => {
55184
- if (!isRecord17(block)) return [];
55185
- const blockPath = `${path25}[${index}]`;
55905
+ if (!isRecord18(block)) return [];
55906
+ const blockPath = `${path27}[${index}]`;
55186
55907
  return [
55187
55908
  ...collectNestedRefs(block.props, `${blockPath}.props`),
55188
55909
  ...collectNestedRefs(block.children, `${blockPath}.children`)
55189
55910
  ];
55190
55911
  });
55191
55912
  }
55192
- function collectNestedRefs(value, path25) {
55913
+ function collectNestedRefs(value, path27) {
55193
55914
  if (typeof value === "string") {
55194
55915
  const parsed = parseResourceRef(value);
55195
- return parsed.ok ? [{ ref: value, field: path25 }] : [];
55916
+ return parsed.ok ? [{ ref: value, field: path27 }] : [];
55196
55917
  }
55197
55918
  if (Array.isArray(value)) {
55198
- return value.flatMap((item, index) => collectNestedRefs(item, `${path25}[${index}]`));
55919
+ return value.flatMap((item, index) => collectNestedRefs(item, `${path27}[${index}]`));
55199
55920
  }
55200
- if (!isRecord17(value)) return [];
55201
- return Object.entries(value).flatMap(([key, child]) => collectNestedRefs(child, `${path25}.${key}`));
55921
+ if (!isRecord18(value)) return [];
55922
+ return Object.entries(value).flatMap(([key, child]) => collectNestedRefs(child, `${path27}.${key}`));
55202
55923
  }
55203
55924
 
55204
55925
  // ../site-commands/src/staticExecutionGaps.ts
@@ -55281,7 +56002,7 @@ function parseCommandBatch(input) {
55281
56002
  if (unknownTypeErrors.length > 0) return err(unknownTypeErrors);
55282
56003
  const parsed = siteCommandBatchSchema.safeParse(input);
55283
56004
  if (!parsed.success) {
55284
- return err(parsed.error.issues.map((issue4) => invalidPayloadError(input, issue4)));
56005
+ return err(parsed.error.issues.map((issue5) => invalidPayloadError(input, issue5)));
55285
56006
  }
55286
56007
  return ok(parsed.data);
55287
56008
  }
@@ -55453,9 +56174,9 @@ function deriveIdempotencyKey(input) {
55453
56174
  ].join("|"));
55454
56175
  }
55455
56176
  function findUnknownCommandTypes(input) {
55456
- if (!isRecord17(input) || !Array.isArray(input.commands)) return [];
56177
+ if (!isRecord18(input) || !Array.isArray(input.commands)) return [];
55457
56178
  return input.commands.flatMap((command, commandIndex) => {
55458
- if (!isRecord17(command) || typeof command.type !== "string") return [];
56179
+ if (!isRecord18(command) || typeof command.type !== "string") return [];
55459
56180
  if (commandTypeSet.has(command.type)) return [];
55460
56181
  return [{
55461
56182
  code: "unknown_command_type",
@@ -55465,32 +56186,32 @@ function findUnknownCommandTypes(input) {
55465
56186
  }];
55466
56187
  });
55467
56188
  }
55468
- function invalidPayloadError(input, issue4) {
55469
- const commandIndex = commandIndexForIssuePath(issue4.path);
56189
+ function invalidPayloadError(input, issue5) {
56190
+ const commandIndex = commandIndexForIssuePath(issue5.path);
55470
56191
  const commandType = commandTypeForIssue(input, commandIndex);
55471
- const field = formatIssuePath(issue4.path);
56192
+ const field = formatIssuePath(issue5.path);
55472
56193
  return {
55473
56194
  code: "invalid_command_payload",
55474
56195
  commandIndex,
55475
56196
  commandType,
55476
56197
  field,
55477
- message: `${field}: ${issue4.message}`
56198
+ message: `${field}: ${issue5.message}`
55478
56199
  };
55479
56200
  }
55480
- function commandIndexForIssuePath(path25) {
55481
- return path25[0] === "commands" && typeof path25[1] === "number" ? path25[1] : -1;
56201
+ function commandIndexForIssuePath(path27) {
56202
+ return path27[0] === "commands" && typeof path27[1] === "number" ? path27[1] : -1;
55482
56203
  }
55483
56204
  function commandTypeForIssue(input, commandIndex) {
55484
- if (!isRecord17(input) || !isUnknownArray3(input.commands)) return null;
56205
+ if (!isRecord18(input) || !isUnknownArray3(input.commands)) return null;
55485
56206
  const command = input.commands[commandIndex];
55486
- return isRecord17(command) && typeof command.type === "string" ? command.type : null;
56207
+ return isRecord18(command) && typeof command.type === "string" ? command.type : null;
55487
56208
  }
55488
56209
  function isUnknownArray3(value) {
55489
56210
  return Array.isArray(value);
55490
56211
  }
55491
- function formatIssuePath(path25) {
55492
- if (path25.length === 0) return "<root>";
55493
- return path25.reduce((formatted, segment) => {
56212
+ function formatIssuePath(path27) {
56213
+ if (path27.length === 0) return "<root>";
56214
+ return path27.reduce((formatted, segment) => {
55494
56215
  if (typeof segment === "number") return `${formatted}[${segment}]`;
55495
56216
  if (formatted.length === 0) return String(segment);
55496
56217
  return `${formatted}.${String(segment)}`;
@@ -55728,11 +56449,12 @@ function indexOfferingCommands(batch) {
55728
56449
  function checkTicketPricedEventsHaveTickets(indexes) {
55729
56450
  return indexes.events.flatMap((event) => {
55730
56451
  const tickets = indexes.ticketsByEventRef.get(event.ref) ?? [];
55731
- if (event.input.pricing.kind !== "ticket_types" || tickets.length > 0) return [];
56452
+ const inlineTickets = event.input.pricing.kind === "ticket_types" ? event.input.pricing.ticketTypes ?? [] : [];
56453
+ if (event.input.pricing.kind !== "ticket_types" || tickets.length + inlineTickets.length > 0) return [];
55732
56454
  return [commandInvariantViolation(
55733
56455
  event.ref,
55734
56456
  "input.pricing",
55735
- "Events using ticket_types pricing require at least one upsertEventTicketType command."
56457
+ "Events using ticket_types pricing require at least one inline ticket type or upsertEventTicketType command."
55736
56458
  )];
55737
56459
  });
55738
56460
  }
@@ -55740,7 +56462,10 @@ function checkTicketQuantitiesWithinCapacity(indexes) {
55740
56462
  return indexes.events.flatMap((event) => {
55741
56463
  const capacity2 = limitedCapacityQuantity(event.input.capacity);
55742
56464
  if (capacity2 === void 0) return [];
55743
- const ticketQuantityTotal = (indexes.ticketsByEventRef.get(event.ref) ?? []).reduce((total, ticket) => total + (ticket.input.quantity ?? 0), 0);
56465
+ const ticketQuantityTotal = (indexes.ticketsByEventRef.get(event.ref) ?? []).reduce((total, ticket) => total + (ticket.input.quantity ?? 0), 0) + (event.input.pricing.kind === "ticket_types" ? (event.input.pricing.ticketTypes ?? []).reduce(
56466
+ (total, ticket) => total + (ticket.capacityLimit ?? 0),
56467
+ 0
56468
+ ) : 0);
55744
56469
  if (ticketQuantityTotal <= capacity2) return [];
55745
56470
  return [commandInvariantViolation(
55746
56471
  event.ref,
@@ -56155,8 +56880,8 @@ init_src();
56155
56880
  var timeRegex = /^([01]\d|2[0-3]):([0-5]\d)(:([0-5]\d))?$/;
56156
56881
  var explicitOffsetDateTimeRegex = /^(\d{4})-(\d{2})-(\d{2})T([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?(\.\d{1,3})?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)$/;
56157
56882
  var localDateTimeRegex = /^(\d{4})-(\d{2})-(\d{2})T([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?(\.\d{1,3})?$/;
56158
- function issue3(path25, message) {
56159
- return { path: path25, message };
56883
+ function issue4(path27, message) {
56884
+ return { path: path27, message };
56160
56885
  }
56161
56886
  function isValidDateParts(year, month, day) {
56162
56887
  const date = new Date(Date.UTC(year, month - 1, day));
@@ -56220,22 +56945,22 @@ function maxDurationMessage(options) {
56220
56945
  function classifyCanonicalSchedule(input, options) {
56221
56946
  const issues = [];
56222
56947
  if (options.requireCanonicalFields && input.recurrenceRule === void 0) {
56223
- issues.push(issue3(["recurrenceRule"], "recurrenceRule is required"));
56948
+ issues.push(issue4(["recurrenceRule"], "recurrenceRule is required"));
56224
56949
  }
56225
56950
  if (input.defaultStartTime !== void 0 && input.defaultStartTime !== null && !timeRegex.test(input.defaultStartTime)) {
56226
- issues.push(issue3(["defaultStartTime"], "Invalid time format (HH:MM or HH:MM:SS)"));
56951
+ issues.push(issue4(["defaultStartTime"], "Invalid time format (HH:MM or HH:MM:SS)"));
56227
56952
  }
56228
56953
  if (options.requireCanonicalFields && !input.defaultStartTime) {
56229
- issues.push(issue3(["defaultStartTime"], "defaultStartTime is required"));
56954
+ issues.push(issue4(["defaultStartTime"], "defaultStartTime is required"));
56230
56955
  }
56231
56956
  if (options.requireCanonicalFields && input.durationMinutes === void 0) {
56232
- issues.push(issue3(["durationMinutes"], "durationMinutes is required"));
56957
+ issues.push(issue4(["durationMinutes"], "durationMinutes is required"));
56233
56958
  }
56234
56959
  if (input.durationMinutes !== void 0 && input.durationMinutes !== null) {
56235
56960
  if (input.durationMinutes < 1) {
56236
- issues.push(issue3(["durationMinutes"], "durationMinutes must be at least 1"));
56961
+ issues.push(issue4(["durationMinutes"], "durationMinutes must be at least 1"));
56237
56962
  } else if (exceedsMaxDuration(input.durationMinutes, options)) {
56238
- issues.push(issue3(["durationMinutes"], maxDurationMessage(options)));
56963
+ issues.push(issue4(["durationMinutes"], maxDurationMessage(options)));
56239
56964
  }
56240
56965
  }
56241
56966
  if (issues.length > 0) return { ok: false, issues };
@@ -56260,34 +56985,34 @@ function classifySdkEventSchedule(input, options = {}) {
56260
56985
  return classifyCanonicalSchedule(input, options);
56261
56986
  }
56262
56987
  if (hasStartsAt && hasCanonicalStart) {
56263
- issues.push(issue3(["startsAt"], "Use either startsAt or startDate/defaultStartTime, not both"));
56988
+ issues.push(issue4(["startsAt"], "Use either startsAt or startDate/defaultStartTime, not both"));
56264
56989
  }
56265
56990
  if (input.recurrenceRule) {
56266
- issues.push(issue3(["recurrenceRule"], "startsAt schedules are only supported for one-off events"));
56991
+ issues.push(issue4(["recurrenceRule"], "startsAt schedules are only supported for one-off events"));
56267
56992
  }
56268
56993
  if (!hasStartsAt) {
56269
- issues.push(issue3(["startsAt"], "startsAt is required when endsAt is provided"));
56994
+ issues.push(issue4(["startsAt"], "startsAt is required when endsAt is provided"));
56270
56995
  }
56271
56996
  if (!hasEndsAt && !hasDateTimeDuration) {
56272
- issues.push(issue3(["endsAt"], "Provide either endsAt or durationMinutes with startsAt"));
56997
+ issues.push(issue4(["endsAt"], "Provide either endsAt or durationMinutes with startsAt"));
56273
56998
  }
56274
56999
  if (hasEndsAt && hasDateTimeDuration) {
56275
- issues.push(issue3(["endsAt"], "Use either endsAt or durationMinutes with startsAt, not both"));
57000
+ issues.push(issue4(["endsAt"], "Use either endsAt or durationMinutes with startsAt, not both"));
56276
57001
  }
56277
57002
  const startsAt = typeof input.startsAt === "string" ? parseSdkEventDateTime(input.startsAt) : null;
56278
57003
  const endsAt = typeof input.endsAt === "string" ? parseSdkEventDateTime(input.endsAt) : null;
56279
57004
  if (hasStartsAt && !startsAt) {
56280
- issues.push(issue3(["startsAt"], "Invalid datetime format. Use ISO datetime format, e.g. 2026-06-01T10:00:00Z"));
57005
+ issues.push(issue4(["startsAt"], "Invalid datetime format. Use ISO datetime format, e.g. 2026-06-01T10:00:00Z"));
56281
57006
  }
56282
57007
  if (hasEndsAt && !endsAt) {
56283
- issues.push(issue3(["endsAt"], "Invalid datetime format. Use ISO datetime format, e.g. 2026-06-07T10:00:00Z"));
57008
+ issues.push(issue4(["endsAt"], "Invalid datetime format. Use ISO datetime format, e.g. 2026-06-07T10:00:00Z"));
56284
57009
  }
56285
57010
  if (startsAt && endsAt) {
56286
57011
  const durationMinutes = durationMinutesBetween(startsAt, endsAt);
56287
57012
  if (durationMinutes === null) {
56288
- issues.push(issue3(["endsAt"], "endsAt must be after startsAt and align to a whole minute"));
57013
+ issues.push(issue4(["endsAt"], "endsAt must be after startsAt and align to a whole minute"));
56289
57014
  } else if (exceedsMaxDuration(durationMinutes, options)) {
56290
- issues.push(issue3(["endsAt"], maxDurationMessage(options)));
57015
+ issues.push(issue4(["endsAt"], maxDurationMessage(options)));
56291
57016
  }
56292
57017
  if (issues.length === 0 && durationMinutes !== null) {
56293
57018
  return {
@@ -56306,9 +57031,9 @@ function classifySdkEventSchedule(input, options = {}) {
56306
57031
  }
56307
57032
  if (startsAt && hasDateTimeDuration && input.durationMinutes !== void 0 && input.durationMinutes !== null) {
56308
57033
  if (input.durationMinutes < 1) {
56309
- issues.push(issue3(["durationMinutes"], "durationMinutes must be at least 1"));
57034
+ issues.push(issue4(["durationMinutes"], "durationMinutes must be at least 1"));
56310
57035
  } else if (exceedsMaxDuration(input.durationMinutes, options)) {
56311
- issues.push(issue3(["durationMinutes"], maxDurationMessage(options)));
57036
+ issues.push(issue4(["durationMinutes"], maxDurationMessage(options)));
56312
57037
  }
56313
57038
  if (issues.length === 0) {
56314
57039
  const endsAtMs = startsAt.epochMs + input.durationMinutes * 6e4;
@@ -56591,10 +57316,10 @@ function eventSeriesCommand(event) {
56591
57316
  categoryIdentifier: event.categoryRef ?? void 0,
56592
57317
  formIdentifier: event.formRef ?? void 0,
56593
57318
  capacity: capacity(event.capacity),
56594
- pricing: pricing.value,
56595
- priceDisplay: event.pricing?.priceDisplay ?? void 0,
56596
- acceptsPasses: event.pricing?.acceptsPasses ?? void 0,
56597
- acceptsMemberships: event.pricing?.acceptsMemberships ?? void 0,
57319
+ pricing: pricing.value.pricing,
57320
+ priceDisplay: pricing.value.priceDisplay ?? void 0,
57321
+ acceptsPasses: pricing.value.acceptsPasses,
57322
+ acceptsMemberships: pricing.value.acceptsMemberships,
56598
57323
  occurrences: [occurrence.value],
56599
57324
  content: event.content ? {
56600
57325
  summary: event.content.summary ?? void 0,
@@ -56602,6 +57327,7 @@ function eventSeriesCommand(event) {
56602
57327
  image: event.content.image ?? void 0
56603
57328
  } : void 0,
56604
57329
  settings: event.settings,
57330
+ paymentTerms: event.paymentTerms,
56605
57331
  presentation: event.presentation,
56606
57332
  tags: event.tags
56607
57333
  }
@@ -56685,20 +57411,36 @@ function eventPricing(event) {
56685
57411
  }
56686
57412
  switch (pricing.pricing.kind) {
56687
57413
  case "free":
56688
- return ok({ kind: "free" });
57414
+ return ok({
57415
+ pricing: { kind: "free" },
57416
+ priceDisplay: pricing.pricing.priceDisplay,
57417
+ acceptsPasses: pricing.pricing.acceptsPasses,
57418
+ acceptsMemberships: pricing.pricing.acceptsMemberships
57419
+ });
56689
57420
  case "fixed_price":
56690
57421
  return ok({
56691
- kind: "fixed_price",
56692
- price: {
56693
- amountCents: pricing.pricing.priceAmount,
56694
- currency: pricing.pricing.priceCurrency
56695
- }
57422
+ pricing: {
57423
+ kind: "fixed_price",
57424
+ price: {
57425
+ amountCents: pricing.pricing.priceAmount,
57426
+ currency: pricing.pricing.priceCurrency
57427
+ }
57428
+ },
57429
+ priceDisplay: pricing.pricing.priceDisplay,
57430
+ acceptsPasses: pricing.pricing.acceptsPasses,
57431
+ acceptsMemberships: pricing.pricing.acceptsMemberships
56696
57432
  });
56697
57433
  case "ticket_types":
56698
- return unsupported(
56699
- event.identifier,
56700
- `Event ${event.identifier} uses ticket-type pricing; command-backed event pushes do not support ticket types yet.`
56701
- );
57434
+ return ok({
57435
+ pricing: {
57436
+ kind: "ticket_types",
57437
+ currency: pricing.pricing.priceCurrency,
57438
+ ticketTypes: pricing.pricing.ticketTypes
57439
+ },
57440
+ priceDisplay: pricing.pricing.priceDisplay,
57441
+ acceptsPasses: pricing.pricing.acceptsPasses,
57442
+ acceptsMemberships: pricing.pricing.acceptsMemberships
57443
+ });
56702
57444
  default:
56703
57445
  return assertNever(pricing.pricing);
56704
57446
  }
@@ -56756,6 +57498,9 @@ function eventSeriesUpsertInput(command) {
56756
57498
  schedule: scheduleFromOccurrence(occurrence),
56757
57499
  capacity: capacityLimit(command.input.capacity),
56758
57500
  pricing: eventPricingInput(command.input),
57501
+ ...command.input.paymentTerms === void 0 ? {} : {
57502
+ paymentTerms: command.input.paymentTerms
57503
+ },
56759
57504
  venueRef: command.input.venueIdentifier ?? (command.input.venueRef ? refSlug(command.input.venueRef) : null),
56760
57505
  categoryRef: command.input.categoryIdentifier ?? (command.input.categoryRef ? refSlug(command.input.categoryRef) : null),
56761
57506
  content: eventContentInput(command.input.content),
@@ -56769,8 +57514,8 @@ function eventContentInput(content) {
56769
57514
  if (!content) return void 0;
56770
57515
  return {
56771
57516
  ...content.summary ? { summary: content.summary } : {},
56772
- ...typeof content.body === "string" || isRecord18(content.body) ? { body: content.body } : {},
56773
- ...typeof content.image === "string" || isRecord18(content.image) ? { image: content.image } : {}
57517
+ ...typeof content.body === "string" || isRecord19(content.body) ? { body: content.body } : {},
57518
+ ...typeof content.image === "string" || isRecord19(content.image) ? { image: content.image } : {}
56774
57519
  };
56775
57520
  }
56776
57521
  function courseUpsertInput(command) {
@@ -56817,9 +57562,19 @@ function eventPricingInput(input) {
56817
57562
  acceptsMemberships: input.acceptsMemberships ?? false
56818
57563
  };
56819
57564
  case "ticket_types":
56820
- throw new Error(
56821
- "Unsupported ticket-type event command reached SDK mapper."
56822
- );
57565
+ if (!input.pricing.ticketTypes || input.pricing.ticketTypes.length === 0) {
57566
+ throw new Error(
57567
+ "Ticket-type event command is missing inline ticketTypes."
57568
+ );
57569
+ }
57570
+ return {
57571
+ kind: "ticket_types",
57572
+ priceCurrency: input.pricing.currency ?? "USD",
57573
+ priceDisplay: input.priceDisplay ?? null,
57574
+ acceptsPasses: input.acceptsPasses ?? false,
57575
+ acceptsMemberships: input.acceptsMemberships ?? false,
57576
+ ticketTypes: input.pricing.ticketTypes
57577
+ };
56823
57578
  case "manual_payment":
56824
57579
  case "external":
56825
57580
  throw new Error(
@@ -56941,7 +57696,7 @@ function toUtcIso(date, time) {
56941
57696
  const normalizedTime = time.length === 5 ? `${time}:00` : time;
56942
57697
  return (/* @__PURE__ */ new Date(`${date}T${normalizedTime}Z`)).toISOString();
56943
57698
  }
56944
- function isRecord18(value) {
57699
+ function isRecord19(value) {
56945
57700
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
56946
57701
  }
56947
57702
  function unsupported(identifier, message) {
@@ -57783,15 +58538,15 @@ function validateBlockContent(data, manifest, customFields) {
57783
58538
  validator.parse(data);
57784
58539
  } catch (error) {
57785
58540
  if (error instanceof ZodError) {
57786
- for (const issue4 of error.issues) {
57787
- const fieldPath = issue4.path.join(".");
57788
- if (issue4.code === "invalid_type" && issue4.received === "undefined") {
58541
+ for (const issue5 of error.issues) {
58542
+ const fieldPath = issue5.path.join(".");
58543
+ if (issue5.code === "invalid_type" && issue5.received === "undefined") {
57789
58544
  continue;
57790
58545
  }
57791
58546
  warnings.push({
57792
58547
  type: "invalid_content",
57793
58548
  field: fieldPath || "(root)",
57794
- message: `Invalid content${fieldPath ? ` in "${fieldPath}"` : ""}: ${issue4.message}`
58549
+ message: `Invalid content${fieldPath ? ` in "${fieldPath}"` : ""}: ${issue5.message}`
57795
58550
  });
57796
58551
  }
57797
58552
  }
@@ -59227,7 +59982,7 @@ async function handleThemePushForAllScope(params) {
59227
59982
  }
59228
59983
  const validation = themeSchema2.safeParse(localTheme.theme);
59229
59984
  if (!validation.success) {
59230
- const errors = validation.error.issues.map((issue4) => ` - ${issue4.path.join(".")}: ${issue4.message}`).join("\n");
59985
+ const errors = validation.error.issues.map((issue5) => ` - ${issue5.path.join(".")}: ${issue5.message}`).join("\n");
59231
59986
  output.warn(
59232
59987
  `Skipping theme push - invalid theme at content/themes/${themeName}.json:
59233
59988
  ${errors}`
@@ -59893,7 +60648,7 @@ function firstNestedContainerChange(localChanges, remoteChanges) {
59893
60648
  }
59894
60649
  function firstSameFieldConflictPath(localChanges, remoteChanges) {
59895
60650
  const remotePaths = new Set(remoteChanges.keys());
59896
- return [...localChanges.keys()].filter((path25) => remotePaths.has(path25)).sort()[0] ?? null;
60651
+ return [...localChanges.keys()].filter((path27) => remotePaths.has(path27)).sort()[0] ?? null;
59897
60652
  }
59898
60653
  function unsupportedNestedMerge(subject, fieldPath) {
59899
60654
  return {
@@ -59975,37 +60730,37 @@ function valueKind(value) {
59975
60730
  if (typeof value === "object") return "object";
59976
60731
  return "scalar";
59977
60732
  }
59978
- function entryChange(path25, value, containerKind) {
60733
+ function entryChange(path27, value, containerKind) {
59979
60734
  switch (containerKind) {
59980
60735
  case "array":
59981
- if (Array.isArray(value)) return { path: path25, value, containerKind };
60736
+ if (Array.isArray(value)) return { path: path27, value, containerKind };
59982
60737
  break;
59983
60738
  case "object":
59984
60739
  if (value && typeof value === "object" && !Array.isArray(value)) {
59985
- return { path: path25, value, containerKind };
60740
+ return { path: path27, value, containerKind };
59986
60741
  }
59987
60742
  break;
59988
60743
  case "null":
59989
- if (value === null || value === void 0) return { path: path25, value, containerKind };
60744
+ if (value === null || value === void 0) return { path: path27, value, containerKind };
59990
60745
  break;
59991
60746
  case "scalar":
59992
- if (isScalarEntryChangeValue(value)) return { path: path25, value, containerKind };
60747
+ if (isScalarEntryChangeValue(value)) return { path: path27, value, containerKind };
59993
60748
  break;
59994
60749
  default:
59995
60750
  assertNever(containerKind);
59996
60751
  }
59997
- throw new Error(`Invalid entry merge change at ${path25}.`);
60752
+ throw new Error(`Invalid entry merge change at ${path27}.`);
59998
60753
  }
59999
60754
  function isScalarEntryChangeValue(value) {
60000
60755
  return value === void 0 || value === null || ["boolean", "number", "string"].includes(typeof value);
60001
60756
  }
60002
- function expectStringValue(path25, value) {
60757
+ function expectStringValue(path27, value) {
60003
60758
  if (typeof value === "string") return value;
60004
- throw new Error(`Entry merge expected ${path25} to be a string.`);
60759
+ throw new Error(`Entry merge expected ${path27} to be a string.`);
60005
60760
  }
60006
- function expectBooleanValue(path25, value) {
60761
+ function expectBooleanValue(path27, value) {
60007
60762
  if (typeof value === "boolean") return value;
60008
- throw new Error(`Entry merge expected ${path25} to be a boolean.`);
60763
+ throw new Error(`Entry merge expected ${path27} to be a boolean.`);
60009
60764
  }
60010
60765
  function expectStatusValue(value) {
60011
60766
  if (value === "draft" || value === "published") return value;
@@ -60643,6 +61398,19 @@ async function executePushForEnv(output, target, scope, type, identifier, option
60643
61398
  }
60644
61399
  const pushScope = parsedPushScope;
60645
61400
  const jsonOutput = globalOpts.json ?? false;
61401
+ const canonicalEntrySyncDecision = getCanonicalEntrySyncDecision({
61402
+ scope: pushScope,
61403
+ contentType: type,
61404
+ operation: "push"
61405
+ });
61406
+ if (canonicalEntrySyncDecision.tag === "reject") {
61407
+ process.exitCode = 1;
61408
+ output.result(false, canonicalEntrySyncDecision.violation.message, {
61409
+ contentType: canonicalEntrySyncDecision.violation.contentType,
61410
+ suggestion: canonicalEntrySyncDecision.violation.suggestion
61411
+ });
61412
+ return { success: false };
61413
+ }
60646
61414
  const deleteOrphanedEnabled = options.deleteOrphaned ?? false;
60647
61415
  let deleteMissingEnabled = options.deleteMissing ?? false;
60648
61416
  if (deleteMissingEnabled) {
@@ -60713,7 +61481,7 @@ ${available.map((t) => ` - ${t.name} (content/themes/${t.name}.json)`).join("\n
60713
61481
  }
60714
61482
  const validation = themeSchema.safeParse(localTheme.theme);
60715
61483
  if (!validation.success) {
60716
- const errors = validation.error.issues.map((issue4) => ` - ${issue4.path.join(".")}: ${issue4.message}`).join("\n");
61484
+ const errors = validation.error.issues.map((issue5) => ` - ${issue5.path.join(".")}: ${issue5.message}`).join("\n");
60717
61485
  output.error(
60718
61486
  `Invalid theme file at content/themes/${themeName}.json:
60719
61487
  ${errors}`
@@ -60901,8 +61669,16 @@ ${errors}`
60901
61669
  });
60902
61670
  return { success: false };
60903
61671
  }
61672
+ const legacyEventEntryFiles = shouldExcludeCanonicalEntries(canonicalEntrySyncDecision) ? await findLegacyEventEntryFiles(contentDir) : [];
61673
+ if (legacyEventEntryFiles.length > 0) {
61674
+ output.warn(
61675
+ "Legacy event entry files detected and ignored by generic entry sync.",
61676
+ formatLegacyEventEntryWarning(legacyEventEntryFiles)
61677
+ );
61678
+ }
60904
61679
  output.info("Reading local content...");
60905
- const localContent = normalizeLocalContentShape(await readAllContent(contentDir));
61680
+ const rawLocalContent = normalizeLocalContentShape(await readAllContent(contentDir));
61681
+ const localContent = shouldExcludeCanonicalEntries(canonicalEntrySyncDecision) ? stripCanonicalEventEntriesFromLocalContent(rawLocalContent).content : rawLocalContent;
60906
61682
  if (options.mergeRemote) {
60907
61683
  return planAndReportRemoteEntryMerge({
60908
61684
  output,
@@ -60944,7 +61720,7 @@ ${errors}`
60944
61720
  return { success: true };
60945
61721
  }
60946
61722
  output.info("Fetching remote content for comparison...");
60947
- const remoteContent = await client.pull.all();
61723
+ const remoteContent = stripCanonicalEventEntriesFromPulledContent(await client.pull.all()).content;
60948
61724
  if (remoteContent.meta.truncated) {
60949
61725
  output.warn("Warning: Remote content was truncated due to size limits.");
60950
61726
  output.warn(
@@ -61227,7 +62003,7 @@ ${errors}`
61227
62003
  if (metadataFlags.shouldUpdateMetadata && !skipMeta) {
61228
62004
  try {
61229
62005
  output.info("Updating local metadata...");
61230
- const freshRemote = await client.pull.all();
62006
+ const freshRemote = stripCanonicalEventEntriesFromPulledContent(await client.pull.all()).content;
61231
62007
  const entriesForMeta = {};
61232
62008
  if (metadataFlags.willUpdateEntries && freshRemote.meta.entries) {
61233
62009
  for (const [key, meta] of Object.entries(freshRemote.meta.entries)) {
@@ -63006,7 +63782,7 @@ var THEME_FIELD_CATEGORY_MAP = {
63006
63782
  };
63007
63783
 
63008
63784
  // src/cli/init-docs/zod-to-markdown.ts
63009
- function isRecord19(value) {
63785
+ function isRecord20(value) {
63010
63786
  return typeof value === "object" && value !== null && !Array.isArray(value);
63011
63787
  }
63012
63788
  function isZodTypeAny(value) {
@@ -63134,7 +63910,7 @@ function extractLiteralValue(schema) {
63134
63910
  const typeName = getTypeName(schema);
63135
63911
  if (typeName !== ZodTypeName.ZodLiteral) return void 0;
63136
63912
  const def = schema._def;
63137
- if (!isRecord19(def)) return void 0;
63913
+ if (!isRecord20(def)) return void 0;
63138
63914
  return String(def.value);
63139
63915
  }
63140
63916
  function extractSchemaInfo(schema, skipFields = []) {
@@ -63204,7 +63980,7 @@ function extractFieldInfo(name, schema) {
63204
63980
  }
63205
63981
  if (typeName === ZodTypeName.ZodRecord) {
63206
63982
  const def = inner._def;
63207
- const valueSchema = isRecord19(def) ? def.valueType : void 0;
63983
+ const valueSchema = isRecord20(def) ? def.valueType : void 0;
63208
63984
  if (!isZodTypeAny(valueSchema)) {
63209
63985
  info.recordValueType = "unknown";
63210
63986
  return info;
@@ -63219,7 +63995,7 @@ function extractFieldInfo(name, schema) {
63219
63995
  }
63220
63996
  } else if (getTypeName(valueInner) === ZodTypeName.ZodRecord) {
63221
63997
  const nestedDef = valueInner._def;
63222
- const nestedValueSchema = isRecord19(nestedDef) ? nestedDef.valueType : void 0;
63998
+ const nestedValueSchema = isRecord20(nestedDef) ? nestedDef.valueType : void 0;
63223
63999
  if (!isZodTypeAny(nestedValueSchema)) {
63224
64000
  info.recordValueType = "record<string, unknown>";
63225
64001
  return info;
@@ -63230,7 +64006,7 @@ function extractFieldInfo(name, schema) {
63230
64006
  }
63231
64007
  if (typeName === ZodTypeName.ZodUnion || typeName === ZodTypeName.ZodDiscriminatedUnion) {
63232
64008
  const def = inner._def;
63233
- const optionsValue = isRecord19(def) ? def.options : void 0;
64009
+ const optionsValue = isRecord20(def) ? def.options : void 0;
63234
64010
  const options = Array.isArray(optionsValue) ? optionsValue.filter(isZodTypeAny) : [];
63235
64011
  const optionTypes = options.map((opt) => {
63236
64012
  const { inner: optInner } = unwrapSchema(opt);
@@ -64395,7 +65171,7 @@ var SimpleCache = class {
64395
65171
  };
64396
65172
 
64397
65173
  // src/version.ts
64398
- var SDK_VERSION = "0.84.2";
65174
+ var SDK_VERSION = "0.88.0";
64399
65175
 
64400
65176
  // src/client/error.ts
64401
65177
  var RiverbankApiError = class _RiverbankApiError extends Error {
@@ -65339,14 +66115,14 @@ function createRiverbankClient(config2) {
65339
66115
  );
65340
66116
  }
65341
66117
  async function getPageWithResilienceInternal(params) {
65342
- const { siteId, path: path25, preview = false, signal } = params;
65343
- const cacheKey = `page:${siteId}:${path25}:${preview}`;
66118
+ const { siteId, path: path27, preview = false, signal } = params;
66119
+ const cacheKey = `page:${siteId}:${path27}:${preview}`;
65344
66120
  return resilientFetch(
65345
66121
  cacheKey,
65346
66122
  async (sig) => {
65347
66123
  return await apiClient({
65348
66124
  endpoint: "getContentByPath",
65349
- params: { siteId, path: path25, preview: String(preview) },
66125
+ params: { siteId, path: path27, preview: String(preview) },
65350
66126
  options: { signal: sig }
65351
66127
  });
65352
66128
  },
@@ -65354,7 +66130,7 @@ function createRiverbankClient(config2) {
65354
66130
  preview,
65355
66131
  signal,
65356
66132
  // Prebuild fallback only for published pages (not preview)
65357
- prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadPage(siteId, path25) : void 0
66133
+ prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadPage(siteId, path27) : void 0
65358
66134
  }
65359
66135
  );
65360
66136
  }
@@ -65549,10 +66325,16 @@ function createRiverbankClient(config2) {
65549
66325
  limit,
65550
66326
  from,
65551
66327
  to,
66328
+ afterStartsAt,
66329
+ afterId,
65552
66330
  stage,
65553
66331
  categoryIds,
65554
66332
  venueId,
66333
+ staffMemberId,
65555
66334
  kind,
66335
+ eventSurface,
66336
+ eventPresets,
66337
+ scheduleScope,
65556
66338
  entryId,
65557
66339
  seriesId,
65558
66340
  includeOccurrenceId,
@@ -65561,7 +66343,7 @@ function createRiverbankClient(config2) {
65561
66343
  if (!siteId) {
65562
66344
  throw new Error("listPublicEvents() requires siteId");
65563
66345
  }
65564
- const cacheKey = `public-events:${siteId}:${limit ?? ""}:${from ?? ""}:${to ?? ""}:${stage ?? ""}:${categoryIds ?? ""}:${venueId ?? ""}:${kind ?? ""}:${entryId ?? ""}:${seriesId ?? ""}:${includeOccurrenceId ?? ""}`;
66346
+ const cacheKey = `public-events:${siteId}:${limit ?? ""}:${from ?? ""}:${to ?? ""}:${afterStartsAt ?? ""}:${afterId ?? ""}:${stage ?? ""}:${categoryIds ?? ""}:${venueId ?? ""}:${staffMemberId ?? ""}:${kind ?? ""}:${eventSurface ?? ""}:${eventPresets ?? ""}:${scheduleScope ?? ""}:${entryId ?? ""}:${seriesId ?? ""}:${includeOccurrenceId ?? ""}`;
65565
66347
  return resilientFetchData(
65566
66348
  cacheKey,
65567
66349
  async (sig) => {
@@ -65570,10 +66352,16 @@ function createRiverbankClient(config2) {
65570
66352
  ...typeof limit === "number" && { limit: String(limit) },
65571
66353
  ...from && { from },
65572
66354
  ...to && { to },
66355
+ ...afterStartsAt && { afterStartsAt },
66356
+ ...afterId && { afterId },
65573
66357
  ...stage && { stage },
65574
66358
  ...categoryIds && { categoryIds },
65575
66359
  ...venueId && { venueId },
66360
+ ...staffMemberId && { staffMemberId },
65576
66361
  ...kind && { kind },
66362
+ ...eventSurface && { eventSurface },
66363
+ ...eventPresets && { eventPresets },
66364
+ ...scheduleScope && { scheduleScope },
65577
66365
  ...entryId && { entryId },
65578
66366
  ...seriesId && { seriesId },
65579
66367
  ...includeOccurrenceId && { includeOccurrenceId }
@@ -65600,6 +66388,9 @@ function createRiverbankClient(config2) {
65600
66388
  venueId,
65601
66389
  staffMemberId,
65602
66390
  kind,
66391
+ eventSurface,
66392
+ eventPresets,
66393
+ scheduleScope,
65603
66394
  entryId,
65604
66395
  seriesId,
65605
66396
  includeOccurrenceId,
@@ -65608,7 +66399,7 @@ function createRiverbankClient(config2) {
65608
66399
  if (!siteId) {
65609
66400
  throw new Error("getPublicEventDetails() requires siteId");
65610
66401
  }
65611
- const cacheKey = `public-event-details:${siteId}:${limit ?? ""}:${from ?? ""}:${to ?? ""}:${afterStartsAt ?? ""}:${afterId ?? ""}:${stage ?? ""}:${categoryIds ?? ""}:${venueId ?? ""}:${staffMemberId ?? ""}:${kind ?? ""}:${entryId ?? ""}:${seriesId ?? ""}:${includeOccurrenceId ?? ""}`;
66402
+ const cacheKey = `public-event-details:${siteId}:${limit ?? ""}:${from ?? ""}:${to ?? ""}:${afterStartsAt ?? ""}:${afterId ?? ""}:${stage ?? ""}:${categoryIds ?? ""}:${venueId ?? ""}:${staffMemberId ?? ""}:${kind ?? ""}:${eventSurface ?? ""}:${eventPresets ?? ""}:${scheduleScope ?? ""}:${entryId ?? ""}:${seriesId ?? ""}:${includeOccurrenceId ?? ""}`;
65612
66403
  return resilientFetchData(
65613
66404
  cacheKey,
65614
66405
  async (sig) => {
@@ -65631,6 +66422,9 @@ function createRiverbankClient(config2) {
65631
66422
  ...venueId && { venueId },
65632
66423
  ...staffMemberId && { staffMemberId },
65633
66424
  ...kind && { kind },
66425
+ ...eventSurface && { eventSurface },
66426
+ ...eventPresets && { eventPresets },
66427
+ ...scheduleScope && { scheduleScope },
65634
66428
  ...entryId && { entryId },
65635
66429
  ...seriesId && { seriesId },
65636
66430
  ...includeOccurrenceId && { includeOccurrenceId }
@@ -65796,17 +66590,17 @@ function createRiverbankClient(config2) {
65796
66590
  };
65797
66591
  },
65798
66592
  async checkRedirect(params) {
65799
- const { siteId, path: path25, signal } = params;
65800
- if (!siteId || !path25) {
66593
+ const { siteId, path: path27, signal } = params;
66594
+ if (!siteId || !path27) {
65801
66595
  throw new Error("checkRedirect() requires siteId and path");
65802
66596
  }
65803
- const cacheKey = `redirect:${siteId}:${path25}`;
66597
+ const cacheKey = `redirect:${siteId}:${path27}`;
65804
66598
  return resilientFetchData(
65805
66599
  cacheKey,
65806
66600
  async (sig) => {
65807
66601
  return await apiClient({
65808
66602
  endpoint: "checkRedirect",
65809
- params: { site: siteId, path: path25 },
66603
+ params: { site: siteId, path: path27 },
65810
66604
  options: { signal: sig }
65811
66605
  });
65812
66606
  },
@@ -65883,13 +66677,13 @@ function pathToFilename(routePath) {
65883
66677
  return routePath.slice(1).replace(/[^a-zA-Z0-9\-\/]/g, "_").replace(/\//g, "-") + ".json";
65884
66678
  }
65885
66679
  function ensureDir4(dirPath) {
65886
- if (!fs10.existsSync(dirPath)) {
65887
- fs10.mkdirSync(dirPath, { recursive: true });
66680
+ if (!fs11.existsSync(dirPath)) {
66681
+ fs11.mkdirSync(dirPath, { recursive: true });
65888
66682
  }
65889
66683
  }
65890
66684
  function writeJsonFile3(filePath, data) {
65891
66685
  const content = JSON.stringify(data, null, 2);
65892
- fs10.writeFileSync(filePath, content, "utf-8");
66686
+ fs11.writeFileSync(filePath, content, "utf-8");
65893
66687
  return Buffer.byteLength(content, "utf-8");
65894
66688
  }
65895
66689
  function calculateChecksum(data) {
@@ -66216,7 +67010,7 @@ async function loadDeployConfig() {
66216
67010
  }
66217
67011
  async function checkWorkingDirectoryClean(git, prebuildOutput) {
66218
67012
  const status = await git.status();
66219
- const dirtyFiles = status.files.map((f) => f.path).filter((path25) => !path25.startsWith(prebuildOutput));
67013
+ const dirtyFiles = status.files.map((f) => f.path).filter((path27) => !path27.startsWith(prebuildOutput));
66220
67014
  return {
66221
67015
  clean: dirtyFiles.length === 0,
66222
67016
  dirtyFiles
@@ -66487,9 +67281,9 @@ Examples:
66487
67281
  const parseResult = verifyConfigSchema.safeParse(rawConfig);
66488
67282
  if (!parseResult.success) {
66489
67283
  return output.error("Invalid config format", {
66490
- issues: parseResult.error.issues.map((issue4) => ({
66491
- path: issue4.path.join("."),
66492
- message: issue4.message
67284
+ issues: parseResult.error.issues.map((issue5) => ({
67285
+ path: issue5.path.join("."),
67286
+ message: issue5.message
66493
67287
  })),
66494
67288
  suggestion: "Ensure your config exports a valid riverbank config object"
66495
67289
  });
@@ -66747,25 +67541,25 @@ function mapMediaGuardDiagnosticsToAuditIssues(diagnostics) {
66747
67541
  }
66748
67542
  }));
66749
67543
  }
66750
- function extractEmbedReferences(data, path25 = []) {
67544
+ function extractEmbedReferences(data, path27 = []) {
66751
67545
  const refs = [];
66752
67546
  if (!data || typeof data !== "object") return refs;
66753
67547
  if (Array.isArray(data)) {
66754
67548
  data.forEach((item, index) => {
66755
- refs.push(...extractEmbedReferences(item, [...path25, String(index)]));
67549
+ refs.push(...extractEmbedReferences(item, [...path27, String(index)]));
66756
67550
  });
66757
67551
  return refs;
66758
67552
  }
66759
67553
  const obj = data;
66760
67554
  if (obj.kind === "embed" && typeof obj.contentType === "string" && typeof obj.identifier === "string") {
66761
67555
  refs.push({
66762
- path: path25.join("."),
67556
+ path: path27.join("."),
66763
67557
  contentType: obj.contentType,
66764
67558
  identifier: obj.identifier
66765
67559
  });
66766
67560
  }
66767
67561
  for (const [key, value] of Object.entries(obj)) {
66768
- refs.push(...extractEmbedReferences(value, [...path25, key]));
67562
+ refs.push(...extractEmbedReferences(value, [...path27, key]));
66769
67563
  }
66770
67564
  return refs;
66771
67565
  }
@@ -67017,8 +67811,8 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
67017
67811
  client
67018
67812
  });
67019
67813
  const mediaIssues = mapMediaGuardDiagnosticsToAuditIssues(mediaGuardResult.diagnostics);
67020
- errors.push(...mediaIssues.filter((issue4) => issue4.severity === "error"));
67021
- warnings.push(...mediaIssues.filter((issue4) => issue4.severity === "warning"));
67814
+ errors.push(...mediaIssues.filter((issue5) => issue5.severity === "error"));
67815
+ warnings.push(...mediaIssues.filter((issue5) => issue5.severity === "warning"));
67022
67816
  }
67023
67817
  if (!isJsonOutput) {
67024
67818
  output.info("Checking for duplicate page paths...");
@@ -67042,8 +67836,8 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
67042
67836
  }
67043
67837
  errors.push(...auditEventReferences(localContent.events, auditCtx));
67044
67838
  const courseRefIssues = auditCourseReferences(localContent.courses, auditCtx);
67045
- errors.push(...courseRefIssues.filter((issue4) => issue4.severity === "error"));
67046
- warnings.push(...courseRefIssues.filter((issue4) => issue4.severity === "warning"));
67839
+ errors.push(...courseRefIssues.filter((issue5) => issue5.severity === "error"));
67840
+ warnings.push(...courseRefIssues.filter((issue5) => issue5.severity === "warning"));
67047
67841
  const success = errors.length === 0;
67048
67842
  const result = { success, errors, warnings };
67049
67843
  if (isJsonOutput) {
@@ -67058,14 +67852,14 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
67058
67852
  output.info("");
67059
67853
  if (errors.length > 0) {
67060
67854
  output.warn(`Found ${errors.length} error(s):`);
67061
- for (const issue4 of errors) {
67062
- output.info(` [ERROR] ${issue4.message}`);
67855
+ for (const issue5 of errors) {
67856
+ output.info(` [ERROR] ${issue5.message}`);
67063
67857
  }
67064
67858
  }
67065
67859
  if (warnings.length > 0) {
67066
67860
  output.warn(`Found ${warnings.length} warning(s):`);
67067
- for (const issue4 of warnings) {
67068
- output.info(` [WARN] ${issue4.message}`);
67861
+ for (const issue5 of warnings) {
67862
+ output.info(` [WARN] ${issue5.message}`);
67069
67863
  }
67070
67864
  }
67071
67865
  if (success && warnings.length === 0) {
@@ -67699,7 +68493,7 @@ function formatThemeSummaryForPrompt(summary) {
67699
68493
  }
67700
68494
 
67701
68495
  // src/manifest/validation/layout-utils.ts
67702
- function collectLayoutNodeInfos(node, path25 = "layout", out = []) {
68496
+ function collectLayoutNodeInfos(node, path27 = "layout", out = []) {
67703
68497
  if (!node || typeof node !== "object") return out;
67704
68498
  const n = node;
67705
68499
  const type = typeof n.type === "string" ? n.type : "unknown";
@@ -67708,10 +68502,10 @@ function collectLayoutNodeInfos(node, path25 = "layout", out = []) {
67708
68502
  const b = n.$bind;
67709
68503
  if (typeof b.from === "string") bindFrom = b.from;
67710
68504
  }
67711
- out.push({ path: path25, type, bindFrom });
68505
+ out.push({ path: path27, type, bindFrom });
67712
68506
  if (Array.isArray(n.children)) {
67713
68507
  for (let i = 0; i < n.children.length; i++) {
67714
- collectLayoutNodeInfos(n.children[i], `${path25}.children[${i}]`, out);
68508
+ collectLayoutNodeInfos(n.children[i], `${path27}.children[${i}]`, out);
67715
68509
  }
67716
68510
  }
67717
68511
  return out;
@@ -68133,7 +68927,7 @@ function extractNestedHrefBindFromProps(props2) {
68133
68927
  const bind2 = href.$bind;
68134
68928
  return bind2 && typeof bind2 === "object" ? bind2 : null;
68135
68929
  }
68136
- function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatStack = []) {
68930
+ function findMissingLinkHrefs(node, blockId, fields3, path27 = "layout", repeatStack = []) {
68137
68931
  const errors = [];
68138
68932
  if (!node || typeof node !== "object") return errors;
68139
68933
  const n = node;
@@ -68162,21 +68956,21 @@ function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatS
68162
68956
  if (isBoundToLinkField) {
68163
68957
  if (!hrefBind || !hrefFrom) {
68164
68958
  errors.push({
68165
- path: path25,
68166
- message: `Block "${blockId}": ${nodeType} node at ${path25} is bound to a link field but is missing props.href binding`,
68959
+ path: path27,
68960
+ message: `Block "${blockId}": ${nodeType} node at ${path27} is bound to a link field but is missing props.href binding`,
68167
68961
  suggestion: `Add props.href: { "$bind": { "from": "${bindFrom ?? "content.yourLinkField"}", "fallback": null, "transforms": [{ "id": "links.resolve" }] } }`
68168
68962
  });
68169
68963
  } else if (!bindingHasTransform(hrefBind, "links.resolve")) {
68170
68964
  errors.push({
68171
- path: path25,
68172
- message: `Block "${blockId}": ${nodeType} node at ${path25} has props.href binding but is missing transforms: [{id:"links.resolve"}]`,
68965
+ path: path27,
68966
+ message: `Block "${blockId}": ${nodeType} node at ${path27} has props.href binding but is missing transforms: [{id:"links.resolve"}]`,
68173
68967
  suggestion: `Set props.href.$bind.transforms to [{ "id": "links.resolve" }].`
68174
68968
  });
68175
68969
  }
68176
68970
  if (bindFrom && bindFieldType === "link" && !bindingHasTransform(bind2, "links.label")) {
68177
68971
  errors.push({
68178
- path: path25,
68179
- message: `Block "${blockId}": ${nodeType} node at ${path25} binds label from a link field but is missing links.label transform`,
68972
+ path: path27,
68973
+ message: `Block "${blockId}": ${nodeType} node at ${path27} binds label from a link field but is missing links.label transform`,
68180
68974
  suggestion: `Set node.$bind.transforms to [{ "id": "links.label" }] so the label renders as text.`
68181
68975
  });
68182
68976
  }
@@ -68189,7 +68983,7 @@ function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatS
68189
68983
  n.children[i],
68190
68984
  blockId,
68191
68985
  fields3,
68192
- `${path25}.children[${i}]`,
68986
+ `${path27}.children[${i}]`,
68193
68987
  nextRepeatStack
68194
68988
  )
68195
68989
  );
@@ -68197,7 +68991,7 @@ function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatS
68197
68991
  }
68198
68992
  return errors;
68199
68993
  }
68200
- function detectRedundantLinkLabels(node, blockId, fields3, path25 = "layout", repeatStack = []) {
68994
+ function detectRedundantLinkLabels(node, blockId, fields3, path27 = "layout", repeatStack = []) {
68201
68995
  const errors = [];
68202
68996
  if (!node || typeof node !== "object") return errors;
68203
68997
  const n = node;
@@ -68219,7 +69013,7 @@ function detectRedundantLinkLabels(node, blockId, fields3, path25 = "layout", re
68219
69013
  const redundancies = findRedundantLinkTextSiblings(
68220
69014
  children,
68221
69015
  nextRepeatStack,
68222
- path25
69016
+ path27
68223
69017
  );
68224
69018
  errors.push(
68225
69019
  ...redundancies.map((r) => ({
@@ -68236,7 +69030,7 @@ function detectRedundantLinkLabels(node, blockId, fields3, path25 = "layout", re
68236
69030
  n.children[i],
68237
69031
  blockId,
68238
69032
  fields3,
68239
- `${path25}.children[${i}]`,
69033
+ `${path27}.children[${i}]`,
68240
69034
  nextRepeatStack
68241
69035
  )
68242
69036
  );
@@ -68475,19 +69269,19 @@ function extractBlockIdFromSelector(selector) {
68475
69269
  const match = selector.match(/\[data-block=(["'])(custom\.[^"']+)\1\]/);
68476
69270
  return match?.[2] ?? null;
68477
69271
  }
68478
- function validateNodeType(nodeType, path25, ctx) {
69272
+ function validateNodeType(nodeType, path27, ctx) {
68479
69273
  if (!ALLOWED_NODE_TYPES.includes(
68480
69274
  nodeType
68481
69275
  )) {
68482
69276
  return {
68483
- path: `${path25}.type`,
68484
- message: `Block "${ctx.blockId}": Unknown node type "${nodeType}" at ${path25}`,
69277
+ path: `${path27}.type`,
69278
+ message: `Block "${ctx.blockId}": Unknown node type "${nodeType}" at ${path27}`,
68485
69279
  suggestion: `ALLOWED: ${ALLOWED_NODE_TYPES.slice(0, 10).join(", ")}... FIX: Replace "${nodeType}" with a valid node type.`
68486
69280
  };
68487
69281
  }
68488
69282
  return null;
68489
69283
  }
68490
- function validateTransforms(transforms, path25, ctx) {
69284
+ function validateTransforms(transforms, path27, ctx) {
68491
69285
  const errors = [];
68492
69286
  for (let i = 0; i < transforms.length; i++) {
68493
69287
  const transform = transforms[i];
@@ -68496,7 +69290,7 @@ function validateTransforms(transforms, path25, ctx) {
68496
69290
  transform.id
68497
69291
  )) {
68498
69292
  errors.push({
68499
- path: `${path25}.transforms[${i}].id`,
69293
+ path: `${path27}.transforms[${i}].id`,
68500
69294
  message: `Block "${ctx.blockId}": Unknown transform "${transform.id}"`,
68501
69295
  suggestion: `ALLOWED: ${ALLOWED_TRANSFORM_IDS.slice(0, 8).join(", ")}... FIX: Replace with a valid transform ID or remove.`
68502
69296
  });
@@ -68505,7 +69299,7 @@ function validateTransforms(transforms, path25, ctx) {
68505
69299
  }
68506
69300
  return errors;
68507
69301
  }
68508
- function validateBinding(bind2, path25, ctx) {
69302
+ function validateBinding(bind2, path27, ctx) {
68509
69303
  const errors = [];
68510
69304
  if ("from" in bind2 && typeof bind2.from === "string") {
68511
69305
  const bindPath = bind2.from;
@@ -68513,7 +69307,7 @@ function validateBinding(bind2, path25, ctx) {
68513
69307
  const fieldId = bindPath.replace("content.", "").split(".")[0] ?? "";
68514
69308
  if (fieldId && !ctx.fieldIds.has(fieldId)) {
68515
69309
  errors.push({
68516
- path: `${path25}.from`,
69310
+ path: `${path27}.from`,
68517
69311
  message: `Block "${ctx.blockId}": $bind references unknown field "${fieldId}"`,
68518
69312
  suggestion: `DEFINED FIELDS: ${Array.from(ctx.fieldIds).join(", ")}. FIX: Add field { id: '${fieldId}', type: '...' } or use existing field.`
68519
69313
  });
@@ -68521,31 +69315,31 @@ function validateBinding(bind2, path25, ctx) {
68521
69315
  }
68522
69316
  }
68523
69317
  if ("transforms" in bind2 && Array.isArray(bind2.transforms)) {
68524
- errors.push(...validateTransforms(bind2.transforms, path25, ctx));
69318
+ errors.push(...validateTransforms(bind2.transforms, path27, ctx));
68525
69319
  }
68526
69320
  return errors;
68527
69321
  }
68528
- function validateLayoutDeep(node, blockId, fields3, path25 = "layout") {
69322
+ function validateLayoutDeep(node, blockId, fields3, path27 = "layout") {
68529
69323
  const ctx = {
68530
69324
  blockId,
68531
69325
  fieldIds: collectFieldIds(fields3)
68532
69326
  };
68533
- return validateLayoutNode(node, path25, ctx);
69327
+ return validateLayoutNode(node, path27, ctx);
68534
69328
  }
68535
- function validateLayoutNode(node, path25, ctx) {
69329
+ function validateLayoutNode(node, path27, ctx) {
68536
69330
  const errors = [];
68537
69331
  if (!node || typeof node !== "object") {
68538
69332
  return errors;
68539
69333
  }
68540
69334
  const n = node;
68541
69335
  if ("type" in n && typeof n.type === "string") {
68542
- const typeError = validateNodeType(n.type, path25, ctx);
69336
+ const typeError = validateNodeType(n.type, path27, ctx);
68543
69337
  if (typeError) errors.push(typeError);
68544
69338
  }
68545
69339
  if ("$bind" in n && n.$bind && typeof n.$bind === "object") {
68546
69340
  const bindErrors = validateBinding(
68547
69341
  n.$bind,
68548
- `${path25}.$bind`,
69342
+ `${path27}.$bind`,
68549
69343
  ctx
68550
69344
  );
68551
69345
  errors.push(...bindErrors);
@@ -68553,7 +69347,7 @@ function validateLayoutNode(node, path25, ctx) {
68553
69347
  if ("props" in n && n.props && typeof n.props === "object") {
68554
69348
  const propsErrors = validatePropsBindings(
68555
69349
  n.props,
68556
- `${path25}.props`,
69350
+ `${path27}.props`,
68557
69351
  ctx
68558
69352
  );
68559
69353
  errors.push(...propsErrors);
@@ -68562,7 +69356,7 @@ function validateLayoutNode(node, path25, ctx) {
68562
69356
  for (let i = 0; i < n.children.length; i++) {
68563
69357
  const childErrors = validateLayoutNode(
68564
69358
  n.children[i],
68565
- `${path25}.children[${i}]`,
69359
+ `${path27}.children[${i}]`,
68566
69360
  ctx
68567
69361
  );
68568
69362
  errors.push(...childErrors);
@@ -68570,17 +69364,17 @@ function validateLayoutNode(node, path25, ctx) {
68570
69364
  }
68571
69365
  return errors;
68572
69366
  }
68573
- function validatePropsBindings(props2, path25, ctx) {
69367
+ function validatePropsBindings(props2, path27, ctx) {
68574
69368
  const errors = [];
68575
69369
  for (const [key, value] of Object.entries(props2)) {
68576
69370
  if (value && typeof value === "object" && "$bind" in value) {
68577
69371
  const bind2 = value.$bind;
68578
- const bindErrors = validateBinding(bind2, `${path25}.${key}.$bind`, ctx);
69372
+ const bindErrors = validateBinding(bind2, `${path27}.${key}.$bind`, ctx);
68579
69373
  errors.push(...bindErrors);
68580
69374
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
68581
69375
  const nestedErrors = validatePropsBindings(
68582
69376
  value,
68583
- `${path25}.${key}`,
69377
+ `${path27}.${key}`,
68584
69378
  ctx
68585
69379
  );
68586
69380
  errors.push(...nestedErrors);
@@ -68713,7 +69507,7 @@ function collectUsedFieldRefs(node) {
68713
69507
  visit(node, []);
68714
69508
  return { topLevel, nestedByRepeater, itemNameByRepeater };
68715
69509
  }
68716
- function findMissingBindings(node, blockId, path25 = "layout") {
69510
+ function findMissingBindings(node, blockId, path27 = "layout") {
68717
69511
  const errors = [];
68718
69512
  if (!node || typeof node !== "object") {
68719
69513
  return errors;
@@ -68723,15 +69517,15 @@ function findMissingBindings(node, blockId, path25 = "layout") {
68723
69517
  if ("$repeat" in n && n.$repeat && typeof n.$repeat === "object") {
68724
69518
  if (nodeType && CONTENT_NODE_TYPES.includes(nodeType)) {
68725
69519
  errors.push({
68726
- path: path25,
68727
- message: `Block "${blockId}": ${nodeType} node at ${path25} uses $repeat, but content nodes cannot be repeat containers`,
69520
+ path: path27,
69521
+ message: `Block "${blockId}": ${nodeType} node at ${path27} uses $repeat, but content nodes cannot be repeat containers`,
68728
69522
  suggestion: `Move $repeat to a container node (grid/stack/div) and put a ${nodeType} child inside with $bind.from like "item.field".`
68729
69523
  });
68730
69524
  }
68731
69525
  if (!Array.isArray(n.children) || n.children.length === 0) {
68732
69526
  errors.push({
68733
- path: path25,
68734
- message: `Block "${blockId}": node at ${path25} uses $repeat but has no children to repeat`,
69527
+ path: path27,
69528
+ message: `Block "${blockId}": node at ${path27} uses $repeat but has no children to repeat`,
68735
69529
  suggestion: 'Add one or more child nodes under children[] that bind to the repeat item (e.g., $bind.from: "item.text").'
68736
69530
  });
68737
69531
  }
@@ -68740,15 +69534,15 @@ function findMissingBindings(node, blockId, path25 = "layout") {
68740
69534
  const hasBind = "$bind" in n && n.$bind && typeof n.$bind === "object" && "from" in n.$bind;
68741
69535
  if (Array.isArray(n.children) && n.children.length > 0) {
68742
69536
  errors.push({
68743
- path: path25,
68744
- message: `Block "${blockId}": ${nodeType} node at ${path25} has children, but content nodes must have children: null`,
69537
+ path: path27,
69538
+ message: `Block "${blockId}": ${nodeType} node at ${path27} has children, but content nodes must have children: null`,
68745
69539
  suggestion: `Replace this ${nodeType} with a container node (div/stack/inline) and put the ${nodeType} nodes inside it.`
68746
69540
  });
68747
69541
  }
68748
69542
  if (!hasBind) {
68749
69543
  errors.push({
68750
- path: `${path25}`,
68751
- message: `Block "${blockId}": ${nodeType} node at ${path25} has no $bind - it won't display any content`,
69544
+ path: `${path27}`,
69545
+ message: `Block "${blockId}": ${nodeType} node at ${path27} has no $bind - it won't display any content`,
68752
69546
  suggestion: `Add $bind: { from: "content.fieldName" } to connect this ${nodeType} to a field. Example: { "type": "${nodeType}", "$bind": { "from": "content.headline" } }`
68753
69547
  });
68754
69548
  }
@@ -68758,7 +69552,7 @@ function findMissingBindings(node, blockId, path25 = "layout") {
68758
69552
  const childErrors = findMissingBindings(
68759
69553
  n.children[i],
68760
69554
  blockId,
68761
- `${path25}.children[${i}]`
69555
+ `${path27}.children[${i}]`
68762
69556
  );
68763
69557
  errors.push(...childErrors);
68764
69558
  }
@@ -68775,13 +69569,13 @@ function getMaxDepth(node, currentDepth = 0) {
68775
69569
  );
68776
69570
  }
68777
69571
  var CONTAINER_NODE_TYPES = ["section", "stack", "grid", "div", "inline"];
68778
- function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path25 = "layout") {
69572
+ function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path27 = "layout") {
68779
69573
  if (!node || typeof node !== "object") return [];
68780
69574
  const n = node;
68781
69575
  const truncatedPaths = [];
68782
69576
  if (currentDepth === maxAllowedDepth && n.children === null) {
68783
69577
  if (CONTAINER_NODE_TYPES.includes(n.type || "")) {
68784
- truncatedPaths.push(`${path25} (${n.type ?? "node"} at depth ${currentDepth})`);
69578
+ truncatedPaths.push(`${path27} (${n.type ?? "node"} at depth ${currentDepth})`);
68785
69579
  }
68786
69580
  }
68787
69581
  if (n.children && Array.isArray(n.children)) {
@@ -68791,7 +69585,7 @@ function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path
68791
69585
  child,
68792
69586
  maxAllowedDepth,
68793
69587
  currentDepth + 1,
68794
- `${path25}.children[${i}]`
69588
+ `${path27}.children[${i}]`
68795
69589
  )
68796
69590
  );
68797
69591
  });
@@ -68811,8 +69605,8 @@ function formatValidationFeedback(errors, output) {
68811
69605
  `The layout reached the maximum depth of ${MAX_LAYOUT_DEPTH} levels.`
68812
69606
  );
68813
69607
  lines.push("These container nodes at the depth limit have no children:");
68814
- for (const path25 of truncatedPaths) {
68815
- lines.push(` \u26A0\uFE0F ${path25}`);
69608
+ for (const path27 of truncatedPaths) {
69609
+ lines.push(` \u26A0\uFE0F ${path27}`);
68816
69610
  }
68817
69611
  lines.push("");
68818
69612
  lines.push(
@@ -69121,11 +69915,12 @@ Your task: Analyze the HTML/JSX markup and identify ALL pieces of content that s
69121
69915
 
69122
69916
  1. **Use richText for formatted lists and multi-line content:**
69123
69917
  - Opening hours \u2192 single richText with formatted list (not 6 separate text fields)
69124
- - Address with line breaks \u2192 single richText (not address1, address2, city, postcode)
69918
+ - Address with line breaks \u2192 single richText with hard line breaks / Shift+Enter between lines (not address1, address2, city, postcode)
69125
69919
  - Feature lists, specs, ingredients \u2192 richText with bullet list
69126
69920
 
69127
- RichText supports: paragraphs, bold, italic, bullet lists, numbered lists, links.
69921
+ RichText supports: paragraphs, hard line breaks, bold, italic, bullet lists, numbered lists, links.
69128
69922
  The CMS editor can format content naturally without rigid field structure.
69923
+ For line-oriented content like addresses, opening hours, and contact details, keep one logical paragraph and use hard line breaks between lines. In the CMS editor, authors create those line breaks with Shift+Enter; Enter creates a new paragraph.
69129
69924
 
69130
69925
  2. **Use repeaters only when items need individual editing/reordering:**
69131
69926
  - Testimonials with avatar + name + quote \u2192 repeater (each item is distinct)
@@ -69137,8 +69932,8 @@ Your task: Analyze the HTML/JSX markup and identify ALL pieces of content that s
69137
69932
  \u274C socialInstagram, socialFacebook, socialTwitter (proliferating similar fields)
69138
69933
  \u274C address1, address2, city, state, zip (5 fields for one address)
69139
69934
 
69140
- \u2705 openingHours: single richText field with formatted content
69141
- \u2705 address: single richText field with line breaks
69935
+ \u2705 openingHours: single richText field with formatted content / hard line breaks
69936
+ \u2705 address: single richText field with hard line breaks (Shift+Enter in the editor)
69142
69937
  \u2705 socialLinks: repeater with { platform, url } IF user needs to add/remove links
69143
69938
 
69144
69939
  ## Field Type Rules
@@ -69168,7 +69963,7 @@ Your task: Analyze the HTML/JSX markup and identify ALL pieces of content that s
69168
69963
 
69169
69964
  ### When to use each type:
69170
69965
  - Single value \u2192 simple field (text, richText, media, link)
69171
- - Formatted list where structure is static \u2192 richText (opening hours, address)
69966
+ - Formatted list where structure is static \u2192 richText (opening hours, address; use hard line breaks / Shift+Enter for line-oriented text)
69172
69967
  - List where items can be added/removed/reordered \u2192 repeater
69173
69968
  - Related fields that belong together \u2192 group
69174
69969
 
@@ -69274,11 +70069,11 @@ var pass3bOutputSchema = z.object({
69274
70069
  customCssAtRules: z.array(llmMediaAtRuleSchema).nullable(),
69275
70070
  rationale: z.string()
69276
70071
  });
69277
- function getNodeAtPath(layout, path25) {
69278
- if (path25 === "" || path25 === "root" || path25 === "layout") {
70072
+ function getNodeAtPath(layout, path27) {
70073
+ if (path27 === "" || path27 === "root" || path27 === "layout") {
69279
70074
  return layout;
69280
70075
  }
69281
- let normalizedPath = path25;
70076
+ let normalizedPath = path27;
69282
70077
  if (normalizedPath.startsWith("layout.")) {
69283
70078
  normalizedPath = normalizedPath.slice(7);
69284
70079
  }
@@ -69580,43 +70375,8 @@ Do NOT include [data-block=...] in selectors - we add that automatically.
69580
70375
  var DEFAULT_MANIFEST_MODEL = process.env.RIVERBANK_MANIFEST_MODEL || "gpt-5-mini";
69581
70376
 
69582
70377
  // src/manifest/three-pass-converter.ts
69583
- function parseInlineMarkdown(text2) {
69584
- const out = [];
69585
- const pushText = (value, marks) => {
69586
- if (!value) return;
69587
- out.push(
69588
- marks && marks.length > 0 ? { type: "text", text: value, marks } : { type: "text", text: value }
69589
- );
69590
- };
69591
- let rest = text2;
69592
- while (rest.length > 0) {
69593
- const start = rest.indexOf("**");
69594
- if (start === -1) {
69595
- pushText(rest);
69596
- break;
69597
- }
69598
- const end = rest.indexOf("**", start + 2);
69599
- if (end === -1) {
69600
- pushText(rest);
69601
- break;
69602
- }
69603
- pushText(rest.slice(0, start));
69604
- pushText(rest.slice(start + 2, end), [{ type: "bold" }]);
69605
- rest = rest.slice(end + 2);
69606
- }
69607
- return out;
69608
- }
69609
70378
  function stringToTipTapDoc(text2) {
69610
- const normalized = text2.replace(/\r\n/g, "\n").trim();
69611
- if (!normalized) return { type: "doc", content: [] };
69612
- const paragraphs = normalized.split(/\n{2,}/).map((p) => p.trim()).filter(Boolean);
69613
- return {
69614
- type: "doc",
69615
- content: paragraphs.map((p) => {
69616
- const inline2 = parseInlineMarkdown(p);
69617
- return inline2.length > 0 ? { type: "paragraph", content: inline2 } : { type: "paragraph" };
69618
- })
69619
- };
70379
+ return createRichTextDocFromMarkdown(text2);
69620
70380
  }
69621
70381
  function coerceRichTextDefaultValue(value) {
69622
70382
  if (value === null || value === void 0) {
@@ -70976,6 +71736,26 @@ var eventPricingInputSchema = z.unknown().superRefine((pricing, ctx) => {
70976
71736
  }
70977
71737
  return result.pricing;
70978
71738
  });
71739
+ var eventPaymentTermsInputSchema = z.unknown().superRefine((paymentTerms, ctx) => {
71740
+ const result = classifySdkEventPaymentTerms(paymentTerms);
71741
+ if (!result.ok) {
71742
+ result.issues.forEach((validationIssue) => {
71743
+ ctx.addIssue({
71744
+ code: "custom",
71745
+ path: [...validationIssue.path],
71746
+ message: validationIssue.message
71747
+ });
71748
+ });
71749
+ }
71750
+ }).transform((paymentTerms) => {
71751
+ const result = classifySdkEventPaymentTerms(paymentTerms);
71752
+ if (!result.ok) {
71753
+ throw new Error(
71754
+ "Unreachable invalid event paymentTerms after Zod validation"
71755
+ );
71756
+ }
71757
+ return result.paymentTerms;
71758
+ });
70979
71759
  var eventUpsertInputSchema = z.object({
70980
71760
  identifier: z.string().min(1).optional(),
70981
71761
  title: z.string().min(1, "title is required"),
@@ -70985,6 +71765,7 @@ var eventUpsertInputSchema = z.object({
70985
71765
  schedule: eventScheduleInputSchema,
70986
71766
  capacity: z.number().int().positive().nullable().optional(),
70987
71767
  pricing: eventPricingInputSchema.optional(),
71768
+ paymentTerms: eventPaymentTermsInputSchema.optional(),
70988
71769
  venueRef: z.string().nullable().optional(),
70989
71770
  categoryRef: z.string().nullable().optional(),
70990
71771
  content: z.record(z.string(), z.unknown()).optional(),
@@ -71068,6 +71849,7 @@ var getCommand5 = createGetCommand({
71068
71849
  schedule: event.schedule,
71069
71850
  capacity: event.capacity,
71070
71851
  pricing: event.pricing,
71852
+ paymentTerms: event.paymentTerms,
71071
71853
  venueRef: event.venueRef,
71072
71854
  categoryRef: event.categoryRef,
71073
71855
  formRef: event.formRef,
@@ -71462,8 +72244,485 @@ async function migrateEntries(options) {
71462
72244
  legacyTitlesMigratedToDataTitle
71463
72245
  };
71464
72246
  }
72247
+ var LEGACY_DATA_FIELDS = /* @__PURE__ */ new Set([
72248
+ "title",
72249
+ "slug",
72250
+ "routeSlug",
72251
+ "path",
72252
+ "summary",
72253
+ "body",
72254
+ "image",
72255
+ "cardTitleOverride",
72256
+ "presentation"
72257
+ ]);
72258
+ function isRecord21(value) {
72259
+ return typeof value === "object" && value !== null && !Array.isArray(value);
72260
+ }
72261
+ function hasMeaningfulValue(value) {
72262
+ if (value === void 0 || value === null) return false;
72263
+ if (typeof value === "string") return value.trim().length > 0;
72264
+ if (Array.isArray(value)) return value.length > 0;
72265
+ if (isRecord21(value)) return Object.keys(value).length > 0;
72266
+ return true;
72267
+ }
72268
+ function normalizeComparable(value) {
72269
+ if (value === void 0 || value === null) return null;
72270
+ if (Array.isArray(value)) return value.map(normalizeComparable);
72271
+ if (!isRecord21(value)) return value;
72272
+ const normalized = {};
72273
+ for (const key of Object.keys(value).sort()) {
72274
+ const normalizedValue = normalizeComparable(value[key]);
72275
+ if (normalizedValue !== null) {
72276
+ normalized[key] = normalizedValue;
72277
+ }
72278
+ }
72279
+ return normalized;
72280
+ }
72281
+ function valuesMatch(a, b) {
72282
+ return equal(normalizeComparable(a), normalizeComparable(b));
72283
+ }
72284
+ function slugFromPath(value) {
72285
+ const trimmed = value.trim().replace(/\/+$/, "");
72286
+ const parts = trimmed.split("/").filter(Boolean);
72287
+ return parts.at(-1) ?? trimmed;
72288
+ }
72289
+ function legacySlugCandidates(legacy) {
72290
+ const candidates = /* @__PURE__ */ new Set();
72291
+ const data = isRecord21(legacy.entry.data) ? legacy.entry.data : {};
72292
+ for (const value of [
72293
+ legacy.entry.slug,
72294
+ data.slug,
72295
+ data.routeSlug,
72296
+ data.path,
72297
+ legacy.entry.identifier,
72298
+ legacy.fileBaseIdentifier
72299
+ ]) {
72300
+ if (typeof value !== "string" || value.trim().length === 0) continue;
72301
+ candidates.add(value.includes("/") ? slugFromPath(value) : value.trim());
72302
+ }
72303
+ return [...candidates];
72304
+ }
72305
+ async function readLegacyEventEntries(contentDir) {
72306
+ const legacyDir = path5.join(contentDir, "entries", CANONICAL_EVENT_ENTRY_TYPE);
72307
+ const files = await listFiles(legacyDir, ".json");
72308
+ files.sort();
72309
+ const entries = [];
72310
+ for (const filePath of files) {
72311
+ const raw = await readJsonFile(filePath);
72312
+ if (!isRecord21(raw)) {
72313
+ entries.push({
72314
+ tag: "invalid",
72315
+ filePath,
72316
+ reason: "Legacy event entry file must be a JSON object."
72317
+ });
72318
+ continue;
72319
+ }
72320
+ if (!isRecord21(raw.data)) {
72321
+ entries.push({
72322
+ tag: "invalid",
72323
+ filePath,
72324
+ reason: "Legacy event entry file must include an object data field."
72325
+ });
72326
+ continue;
72327
+ }
72328
+ const identifier = typeof raw.identifier === "string" && raw.identifier.trim() ? raw.identifier : path5.basename(filePath, ".json");
72329
+ entries.push({
72330
+ tag: "valid",
72331
+ legacy: {
72332
+ filePath,
72333
+ fileBaseIdentifier: path5.basename(filePath, ".json"),
72334
+ entry: { ...raw, identifier, data: raw.data }
72335
+ }
72336
+ });
72337
+ }
72338
+ return entries;
72339
+ }
72340
+ async function readCanonicalEventsWithPaths(contentDir) {
72341
+ const eventsDir = path5.join(contentDir, "events");
72342
+ const files = await listFiles(eventsDir, ".json");
72343
+ files.sort();
72344
+ const events = [];
72345
+ for (const filePath of files) {
72346
+ const event = await readJsonFile(filePath);
72347
+ events.push({ event, filePath });
72348
+ }
72349
+ return events;
72350
+ }
72351
+ function findCandidateEvents(legacy, eventsByIdentifier, eventsBySlug) {
72352
+ const byIdentifier = eventsByIdentifier.get(legacy.entry.identifier);
72353
+ if (byIdentifier) return [byIdentifier];
72354
+ const candidates = /* @__PURE__ */ new Map();
72355
+ for (const slug of legacySlugCandidates(legacy)) {
72356
+ for (const event of eventsBySlug.get(slug) ?? []) {
72357
+ candidates.set(event.identifier, event);
72358
+ }
72359
+ }
72360
+ return [...candidates.values()];
72361
+ }
72362
+ function mergeValue(input) {
72363
+ if (!hasMeaningfulValue(input.incoming)) {
72364
+ return { tag: "ignored" };
72365
+ }
72366
+ if (!hasMeaningfulValue(input.current)) {
72367
+ return { tag: "changed", event: input.set(input.incoming), field: input.path };
72368
+ }
72369
+ if (valuesMatch(input.current, input.incoming)) {
72370
+ return { tag: "unchanged" };
72371
+ }
72372
+ return { tag: "conflict", field: input.path };
72373
+ }
72374
+ function mergeLegacyEventIntoCanonical(legacy, event) {
72375
+ const data = legacy.entry.data;
72376
+ const unmappableFields = [];
72377
+ for (const key of Object.keys(data)) {
72378
+ if (!LEGACY_DATA_FIELDS.has(key) && hasMeaningfulValue(data[key])) {
72379
+ unmappableFields.push(`data.${key}`);
72380
+ }
72381
+ }
72382
+ if (legacy.entry.blocks && Object.keys(legacy.entry.blocks).length > 0) {
72383
+ unmappableFields.push("blocks");
72384
+ }
72385
+ if (unmappableFields.length > 0) {
72386
+ return { tag: "unmappable", fields: unmappableFields.sort() };
72387
+ }
72388
+ let mergedEvent = event;
72389
+ const mergedFields = [];
72390
+ const conflicts = [];
72391
+ const compareOnlyFields = [
72392
+ ["title", event.title, data.title],
72393
+ ["slug", event.slug, legacy.entry.slug ?? data.slug ?? data.routeSlug ?? data.path]
72394
+ ];
72395
+ for (const [fieldPath, current, incoming] of compareOnlyFields) {
72396
+ if (!hasMeaningfulValue(incoming)) continue;
72397
+ const normalizedIncoming = fieldPath === "slug" && typeof incoming === "string" ? slugFromPath(incoming) : incoming;
72398
+ if (!valuesMatch(current, normalizedIncoming)) {
72399
+ conflicts.push(fieldPath);
72400
+ }
72401
+ }
72402
+ const mergeTargets = [
72403
+ {
72404
+ path: "content.summary",
72405
+ current: event.content?.summary,
72406
+ incoming: data.summary,
72407
+ set: (value) => ({ ...mergedEvent, content: { ...mergedEvent.content, summary: value } })
72408
+ },
72409
+ {
72410
+ path: "content.body",
72411
+ current: event.content?.body,
72412
+ incoming: data.body,
72413
+ set: (value) => ({
72414
+ ...mergedEvent,
72415
+ content: { ...mergedEvent.content, body: value }
72416
+ })
72417
+ },
72418
+ {
72419
+ path: "content.image",
72420
+ current: event.content?.image,
72421
+ incoming: data.image,
72422
+ set: (value) => ({
72423
+ ...mergedEvent,
72424
+ content: { ...mergedEvent.content, image: value }
72425
+ })
72426
+ },
72427
+ {
72428
+ path: "presentation.cardTitleOverride",
72429
+ current: event.presentation?.cardTitleOverride,
72430
+ incoming: data.cardTitleOverride,
72431
+ set: (value) => ({
72432
+ ...mergedEvent,
72433
+ presentation: {
72434
+ ...mergedEvent.presentation,
72435
+ cardTitleOverride: value
72436
+ }
72437
+ })
72438
+ }
72439
+ ];
72440
+ for (const target of mergeTargets) {
72441
+ const result = mergeValue({ ...target, event: mergedEvent });
72442
+ if (result.tag === "changed") {
72443
+ mergedEvent = result.event;
72444
+ mergedFields.push(result.field);
72445
+ } else if (result.tag === "conflict") {
72446
+ conflicts.push(result.field);
72447
+ }
72448
+ }
72449
+ if (hasMeaningfulValue(data.presentation)) {
72450
+ if (!isRecord21(data.presentation)) {
72451
+ return { tag: "unmappable", fields: ["data.presentation"] };
72452
+ }
72453
+ for (const [key, value] of Object.entries(data.presentation)) {
72454
+ const fieldPath = `presentation.${key}`;
72455
+ const result = mergeValue({
72456
+ event: mergedEvent,
72457
+ path: fieldPath,
72458
+ current: mergedEvent.presentation?.[key],
72459
+ incoming: value,
72460
+ set: (nextValue) => ({
72461
+ ...mergedEvent,
72462
+ presentation: { ...mergedEvent.presentation, [key]: nextValue }
72463
+ })
72464
+ });
72465
+ if (result.tag === "changed") {
72466
+ mergedEvent = result.event;
72467
+ mergedFields.push(result.field);
72468
+ } else if (result.tag === "conflict") {
72469
+ conflicts.push(result.field);
72470
+ }
72471
+ }
72472
+ }
72473
+ return {
72474
+ tag: "merged",
72475
+ event: mergedEvent,
72476
+ fields: mergedFields,
72477
+ conflicts
72478
+ };
72479
+ }
72480
+ async function planEventMigration(contentDir) {
72481
+ const legacyReadResults = await readLegacyEventEntries(contentDir);
72482
+ const invalidLegacyItems = legacyReadResults.filter((result) => result.tag === "invalid").map((result) => ({
72483
+ tag: "invalidLegacyShape",
72484
+ legacyFilePath: result.filePath,
72485
+ reason: result.reason
72486
+ }));
72487
+ const legacyEntries = legacyReadResults.filter((result) => result.tag === "valid").map((result) => result.legacy);
72488
+ const canonicalEvents = await readCanonicalEventsWithPaths(contentDir);
72489
+ const eventFilePaths = new Map(canonicalEvents.map(({ event, filePath }) => [event.identifier, filePath]));
72490
+ const eventsByIdentifier = new Map(canonicalEvents.map(({ event }) => [event.identifier, event]));
72491
+ const eventsBySlug = /* @__PURE__ */ new Map();
72492
+ for (const { event } of canonicalEvents) {
72493
+ const existing = eventsBySlug.get(event.slug) ?? [];
72494
+ eventsBySlug.set(event.slug, [...existing, event]);
72495
+ }
72496
+ const matches = legacyEntries.map((legacy) => ({
72497
+ legacy,
72498
+ candidates: findCandidateEvents(legacy, eventsByIdentifier, eventsBySlug)
72499
+ }));
72500
+ const eventMatchCounts = /* @__PURE__ */ new Map();
72501
+ for (const match of matches) {
72502
+ if (match.candidates.length === 1) {
72503
+ const candidate = match.candidates[0];
72504
+ if (!candidate) continue;
72505
+ eventMatchCounts.set(candidate.identifier, (eventMatchCounts.get(candidate.identifier) ?? 0) + 1);
72506
+ }
72507
+ }
72508
+ const items = [...invalidLegacyItems];
72509
+ for (const match of matches) {
72510
+ if (match.candidates.length === 0) {
72511
+ items.push({
72512
+ tag: "orphanedLegacy",
72513
+ legacyFilePath: match.legacy.filePath,
72514
+ legacyIdentifier: match.legacy.entry.identifier,
72515
+ reason: "No canonical content/events/*.json payload matched by identifier, slug, or route slug."
72516
+ });
72517
+ continue;
72518
+ }
72519
+ if (match.candidates.length > 1) {
72520
+ items.push({
72521
+ tag: "ambiguousMatch",
72522
+ legacyFilePath: match.legacy.filePath,
72523
+ candidateEventIdentifiers: match.candidates.map((event2) => event2.identifier).sort()
72524
+ });
72525
+ continue;
72526
+ }
72527
+ const event = match.candidates[0];
72528
+ if (!event) {
72529
+ items.push({
72530
+ tag: "orphanedLegacy",
72531
+ legacyFilePath: match.legacy.filePath,
72532
+ legacyIdentifier: match.legacy.entry.identifier,
72533
+ reason: "No canonical content/events/*.json payload matched by identifier, slug, or route slug."
72534
+ });
72535
+ continue;
72536
+ }
72537
+ if ((eventMatchCounts.get(event.identifier) ?? 0) > 1) {
72538
+ items.push({
72539
+ tag: "ambiguousMatch",
72540
+ legacyFilePath: match.legacy.filePath,
72541
+ candidateEventIdentifiers: [event.identifier]
72542
+ });
72543
+ continue;
72544
+ }
72545
+ const mergePlan = mergeLegacyEventIntoCanonical(match.legacy, event);
72546
+ if (mergePlan.tag === "unmappable") {
72547
+ items.push({
72548
+ tag: "unmappableLegacyFields",
72549
+ legacyFilePath: match.legacy.filePath,
72550
+ eventIdentifier: event.identifier,
72551
+ fields: mergePlan.fields
72552
+ });
72553
+ continue;
72554
+ }
72555
+ if (mergePlan.conflicts.length > 0) {
72556
+ items.push({
72557
+ tag: "conflict",
72558
+ legacyFilePath: match.legacy.filePath,
72559
+ eventIdentifier: event.identifier,
72560
+ conflicts: mergePlan.conflicts
72561
+ });
72562
+ continue;
72563
+ }
72564
+ const eventFilePath = eventFilePaths.get(event.identifier) ?? path5.join(contentDir, "events", `${event.identifier}.json`);
72565
+ if (mergePlan.fields.length === 0) {
72566
+ items.push({
72567
+ tag: "archiveLegacyOnly",
72568
+ legacyFilePath: match.legacy.filePath,
72569
+ eventFilePath,
72570
+ eventIdentifier: event.identifier,
72571
+ reason: "Legacy event entry copy already matches canonical event payload."
72572
+ });
72573
+ } else {
72574
+ items.push({
72575
+ tag: "mergeLegacyIntoEvent",
72576
+ legacyFilePath: match.legacy.filePath,
72577
+ eventFilePath,
72578
+ eventIdentifier: event.identifier,
72579
+ mergedEvent: mergePlan.event,
72580
+ mergedFields: mergePlan.fields
72581
+ });
72582
+ }
72583
+ }
72584
+ const blockers = items.filter(isBlockedPlanItem);
72585
+ if (blockers.length > 0) {
72586
+ return { tag: "blocked", contentDir, items, blockers };
72587
+ }
72588
+ return { tag: "writable", contentDir, items: items.filter(isWritablePlanItem) };
72589
+ }
72590
+ function isWritablePlanItem(item) {
72591
+ return item.tag === "mergeLegacyIntoEvent" || item.tag === "archiveLegacyOnly";
72592
+ }
72593
+ function isBlockedPlanItem(item) {
72594
+ return !isWritablePlanItem(item);
72595
+ }
72596
+ async function archiveLegacyFile(contentDir, legacyFilePath) {
72597
+ const archiveDir = path5.join(contentDir, ".legacy", "entries", CANONICAL_EVENT_ENTRY_TYPE);
72598
+ await ensureDir(archiveDir);
72599
+ const destinationPath = path5.join(archiveDir, path5.basename(legacyFilePath));
72600
+ if (!await fileExists(destinationPath)) {
72601
+ await fs5.rename(legacyFilePath, destinationPath);
72602
+ return;
72603
+ }
72604
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
72605
+ const ext = path5.extname(destinationPath);
72606
+ const base = destinationPath.slice(0, -ext.length);
72607
+ await fs5.rename(legacyFilePath, `${base}.${timestamp}${ext}`);
72608
+ }
72609
+ async function migrateEvents(options) {
72610
+ const plan = await planEventMigration(options.contentDir);
72611
+ const summary = {
72612
+ merged: 0,
72613
+ archiveOnly: 0,
72614
+ conflicts: 0,
72615
+ ambiguous: 0,
72616
+ unmappable: 0,
72617
+ orphaned: 0,
72618
+ invalid: 0
72619
+ };
72620
+ let eventsToWrite = 0;
72621
+ let legacyFilesToArchive = 0;
72622
+ for (const item of plan.items) {
72623
+ switch (item.tag) {
72624
+ case "mergeLegacyIntoEvent":
72625
+ summary.merged += 1;
72626
+ if (plan.tag === "writable" && !options.dryRun) {
72627
+ await writeJsonFile(item.eventFilePath, item.mergedEvent);
72628
+ await archiveLegacyFile(options.contentDir, item.legacyFilePath);
72629
+ }
72630
+ if (plan.tag === "writable") {
72631
+ eventsToWrite += 1;
72632
+ legacyFilesToArchive += 1;
72633
+ }
72634
+ break;
72635
+ case "archiveLegacyOnly":
72636
+ summary.archiveOnly += 1;
72637
+ if (plan.tag === "writable" && !options.dryRun) {
72638
+ await archiveLegacyFile(options.contentDir, item.legacyFilePath);
72639
+ }
72640
+ if (plan.tag === "writable") {
72641
+ legacyFilesToArchive += 1;
72642
+ }
72643
+ break;
72644
+ case "conflict":
72645
+ summary.conflicts += 1;
72646
+ break;
72647
+ case "ambiguousMatch":
72648
+ summary.ambiguous += 1;
72649
+ break;
72650
+ case "unmappableLegacyFields":
72651
+ summary.unmappable += 1;
72652
+ break;
72653
+ case "orphanedLegacy":
72654
+ summary.orphaned += 1;
72655
+ break;
72656
+ case "invalidLegacyShape":
72657
+ summary.invalid += 1;
72658
+ break;
72659
+ }
72660
+ }
72661
+ return {
72662
+ status: plan.tag,
72663
+ legacyFilesFound: plan.items.length,
72664
+ eventsToWrite,
72665
+ legacyFilesToArchive,
72666
+ ...summary,
72667
+ dryRun: options.dryRun ?? false,
72668
+ items: plan.items
72669
+ };
72670
+ }
71465
72671
 
71466
72672
  // src/cli/commands/migrate.ts
72673
+ function formatEventMigrationItem(item) {
72674
+ switch (item.tag) {
72675
+ case "mergeLegacyIntoEvent":
72676
+ return [
72677
+ "merge",
72678
+ path5.basename(item.legacyFilePath),
72679
+ item.eventIdentifier,
72680
+ item.mergedFields.join(", ")
72681
+ ];
72682
+ case "archiveLegacyOnly":
72683
+ return [
72684
+ "archive",
72685
+ path5.basename(item.legacyFilePath),
72686
+ item.eventIdentifier,
72687
+ item.reason
72688
+ ];
72689
+ case "conflict":
72690
+ return [
72691
+ "conflict",
72692
+ path5.basename(item.legacyFilePath),
72693
+ item.eventIdentifier,
72694
+ item.conflicts.join(", ")
72695
+ ];
72696
+ case "ambiguousMatch":
72697
+ return [
72698
+ "ambiguous",
72699
+ path5.basename(item.legacyFilePath),
72700
+ item.candidateEventIdentifiers.join(", "),
72701
+ "Multiple canonical events matched this legacy entry."
72702
+ ];
72703
+ case "unmappableLegacyFields":
72704
+ return [
72705
+ "unmappable",
72706
+ path5.basename(item.legacyFilePath),
72707
+ item.eventIdentifier ?? "",
72708
+ item.fields.join(", ")
72709
+ ];
72710
+ case "orphanedLegacy":
72711
+ return [
72712
+ "orphaned",
72713
+ path5.basename(item.legacyFilePath),
72714
+ item.legacyIdentifier,
72715
+ item.reason
72716
+ ];
72717
+ case "invalidLegacyShape":
72718
+ return [
72719
+ "invalid",
72720
+ path5.basename(item.legacyFilePath),
72721
+ "",
72722
+ item.reason
72723
+ ];
72724
+ }
72725
+ }
71467
72726
  var migrateCommand = new Command("migrate").description("Migrate local SDK content formats").addCommand(
71468
72727
  new Command("entries").description("Migrate entries to canonical file format and remove legacy title fields").argument("[type]", "Content type key to migrate (optional)").option("--content-dir <dir>", "Content directory (overrides config)").option("--dry-run", "Preview changes without writing files").option("--force", "Overwrite existing entry files when migrating legacy formats").option("--yes", "Skip confirmation prompt").addHelpText(
71469
72728
  "after",
@@ -71494,6 +72753,13 @@ Examples:
71494
72753
  try {
71495
72754
  const cliConfig = await loadCliConfig();
71496
72755
  const contentDir = path5.resolve(options.contentDir ?? cliConfig.contentDir);
72756
+ if (type === "event") {
72757
+ process.exitCode = 1;
72758
+ output.result(false, "`event` entries use the canonical events migration.", {
72759
+ suggestion: 'Run "riverbankcms migrate events" to fold content/entries/event/*.json into content/events/*.json.'
72760
+ });
72761
+ return;
72762
+ }
71497
72763
  const confirmed = await confirmAction(
71498
72764
  options.dryRun ? "Preview entry migrations?" : "Migrate local entries to the new file format?",
71499
72765
  { yes: options.yes },
@@ -71530,6 +72796,86 @@ Examples:
71530
72796
  handleCommandError(error, output, { target: "local" });
71531
72797
  }
71532
72798
  })
72799
+ ).addCommand(
72800
+ new Command("events").description("Migrate legacy event entries into canonical event files").option("--content-dir <dir>", "Content directory (overrides config)").option("--dry-run", "Preview changes without writing files").option("--yes", "Skip confirmation prompt").addHelpText(
72801
+ "after",
72802
+ `
72803
+ Description:
72804
+ Folds legacy event entry files into canonical SDK event payloads:
72805
+ content/entries/event/*.json -> content/events/*.json
72806
+
72807
+ Safe migrated legacy files are archived to:
72808
+ content/.legacy/entries/event/*.json
72809
+
72810
+ The migration stops before writing when it finds divergent copy,
72811
+ ambiguous matches, unmappable fields, or orphaned legacy event entries.
72812
+
72813
+ Examples:
72814
+ $ riverbankcms migrate events --dry-run
72815
+ $ riverbankcms migrate events --yes
72816
+ `
72817
+ ).action(async (options, command) => {
72818
+ const { output, envTargets } = getOutputContext(command);
72819
+ if (envTargets.length > 1) {
72820
+ return output.error("Migrate is local-only and does not support --env=both", {
72821
+ suggestion: "Use --env=local (default)"
72822
+ });
72823
+ }
72824
+ try {
72825
+ const cliConfig = await loadCliConfig();
72826
+ const contentDir = path5.resolve(options.contentDir ?? cliConfig.contentDir);
72827
+ const confirmed = await confirmAction(
72828
+ options.dryRun ? "Preview event entry migration?" : "Migrate legacy event entries into canonical event files?",
72829
+ { yes: options.yes },
72830
+ false
72831
+ );
72832
+ if (!confirmed) {
72833
+ output.info("Migration cancelled.");
72834
+ return;
72835
+ }
72836
+ const result = await migrateEvents({
72837
+ contentDir,
72838
+ dryRun: options.dryRun
72839
+ });
72840
+ if (result.status === "blocked") {
72841
+ process.exitCode = 1;
72842
+ output.result(false, "Event migration blocked; no files were written or archived.", {
72843
+ conflicts: result.conflicts,
72844
+ ambiguous: result.ambiguous,
72845
+ unmappable: result.unmappable,
72846
+ orphaned: result.orphaned,
72847
+ invalid: result.invalid
72848
+ });
72849
+ } else if (options.dryRun) {
72850
+ output.info("[DRY RUN] Event migration preview:");
72851
+ } else {
72852
+ output.success("Event entries migrated successfully");
72853
+ }
72854
+ output.table(
72855
+ ["Metric", "Count"],
72856
+ [
72857
+ ["Legacy event files found", String(result.legacyFilesFound)],
72858
+ ["Events to write", String(result.eventsToWrite)],
72859
+ ["Legacy files to archive", String(result.legacyFilesToArchive)],
72860
+ ["Merge plans", String(result.merged)],
72861
+ ["Archive-only plans", String(result.archiveOnly)],
72862
+ ["Conflicts", String(result.conflicts)],
72863
+ ["Ambiguous matches", String(result.ambiguous)],
72864
+ ["Unmappable files", String(result.unmappable)],
72865
+ ["Orphaned files", String(result.orphaned)],
72866
+ ["Invalid files", String(result.invalid)]
72867
+ ]
72868
+ );
72869
+ if (result.items.length > 0) {
72870
+ output.table(
72871
+ ["Action", "Legacy File", "Event", "Details"],
72872
+ result.items.map(formatEventMigrationItem)
72873
+ );
72874
+ }
72875
+ } catch (error) {
72876
+ handleCommandError(error, output, { target: "local" });
72877
+ }
72878
+ })
71533
72879
  );
71534
72880
 
71535
72881
  // src/cli/commands/style.ts