@riverbankcms/sdk 0.84.1 → 0.85.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 (60) hide show
  1. package/dist/{PreviewEditorSidebar-X7RLMEI6.mjs → PreviewEditorSidebar-4PH35ZIE.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-CT67N4O3.mjs → PreviewEditorUI-WHMCRJGM.mjs} +11 -6
  3. package/dist/SdkPreviewModeRuntime-4FGSVUYI.mjs +8 -0
  4. package/dist/_dts/ai/src/contracts/proposals.d.ts +684 -0
  5. package/dist/_dts/api/src/bookingConfig.d.ts +2 -0
  6. package/dist/_dts/api/src/index.d.ts +3 -3
  7. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +2 -1
  8. package/dist/_dts/api/src/sdk-event-payment-terms.d.ts +16 -0
  9. package/dist/_dts/api/src/sdk-event-upsert.d.ts +11 -2
  10. package/dist/_dts/api/src/sdkContracts.d.ts +3 -0
  11. package/dist/_dts/api/src/types.d.ts +1 -0
  12. package/dist/_dts/api/src/url.d.ts +12 -4
  13. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +2 -0
  14. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +3 -1
  15. package/dist/_dts/content-editor/src/hooks/useSimpleAutosave.d.ts +8 -0
  16. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +2 -2
  17. package/dist/_dts/preview-next/src/client/preview/MaintenanceModeBadge.d.ts +3 -2
  18. package/dist/_dts/preview-next/src/client/preview/PreviewEditorUI.d.ts +2 -1
  19. package/dist/_dts/sdk/src/cli/canonical-entry-policy.d.ts +53 -0
  20. package/dist/_dts/sdk/src/cli/commands/migrate.d.ts +1 -0
  21. package/dist/_dts/sdk/src/cli/commands/pull.d.ts +7 -1
  22. package/dist/_dts/sdk/src/cli/content/reader.d.ts +2 -0
  23. package/dist/_dts/sdk/src/cli/migrations/events.d.ts +73 -0
  24. package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
  25. package/dist/_dts/sdk/src/client/management/types.d.ts +6 -0
  26. package/dist/_dts/sdk/src/version.d.ts +1 -1
  27. package/dist/_dts/site-commands/src/commands.d.ts +57 -0
  28. package/dist/_dts/surfaces/src/index.d.ts +12 -0
  29. package/dist/{chunk-LBBPD2IW.mjs → chunk-4QNLOTES.mjs} +11 -16
  30. package/dist/{chunk-X5ZCSU6F.mjs → chunk-NFWGLRZZ.mjs} +1 -70
  31. package/dist/{chunk-QRKJDWT7.mjs → chunk-OCGTXHSO.mjs} +8 -7
  32. package/dist/{chunk-3LXFQS7T.mjs → chunk-PYDHOMEO.mjs} +1 -1
  33. package/dist/{chunk-RCTJAZSK.mjs → chunk-WFPYN7KA.mjs} +2 -2
  34. package/dist/{chunk-O62NDCTI.mjs → chunk-ZR2GQK2A.mjs} +6 -37
  35. package/dist/cli/index.mjs +1460 -414
  36. package/dist/client/{bookingForm-DYXT6YB6.mjs → bookingForm-36CWQUMV.mjs} +1 -1
  37. package/dist/client/bookings.mjs +1 -4
  38. package/dist/client/{chunk-UHDWIXVR.mjs → chunk-3C2VTPWI.mjs} +3 -2
  39. package/dist/client/{chunk-GFSQNTRW.mjs → chunk-SDIYSQAY.mjs} +0 -4
  40. package/dist/client/client.mjs +12 -16
  41. package/dist/client/{courseRegistration-YBOGURTA.mjs → courseRegistration-TMKU6ABO.mjs} +1 -1
  42. package/dist/client/{eventCalendar-K4QJVCMD.mjs → eventCalendar-G6TI32X6.mjs} +2 -2
  43. package/dist/client/{eventCombined-MTXGMTCZ.mjs → eventCombined-SCKEMNAR.mjs} +2 -2
  44. package/dist/client/{eventDetails-3PC4NL3U.mjs → eventDetails-XPIFXXPK.mjs} +2 -2
  45. package/dist/client/{eventListing-TFJET6DN.mjs → eventListing-7QFMEMGT.mjs} +2 -2
  46. package/dist/client/{eventRegistration-QGPBGJTW.mjs → eventRegistration-TOODSZUI.mjs} +2 -2
  47. package/dist/client/{form-MDKR4FNB.mjs → form-MTCMVCZT.mjs} +1 -1
  48. package/dist/client/{newsletterForm-ZR5UDGBT.mjs → newsletterForm-PCAIPFMA.mjs} +1 -1
  49. package/dist/client/rendering/client.mjs +2 -5
  50. package/dist/client/rendering/islands.mjs +9 -9
  51. package/dist/client/rendering.mjs +2 -5
  52. package/dist/client/spam-protection.mjs +0 -4
  53. package/dist/preview-next/client/runtime.mjs +5 -5
  54. package/dist/{sdk-runtime-7HJYPRWQ.mjs → sdk-runtime-QLOCYKVU.mjs} +6 -6
  55. package/dist/server/index.mjs +10 -11
  56. package/dist/server/next.mjs +10 -11
  57. package/dist/server/prebuild.mjs +1 -1
  58. package/dist/server/server.mjs +10 -11
  59. package/package.json +1 -1
  60. package/dist/SdkPreviewModeRuntime-EIMQ3S2V.mjs +0 -8
@@ -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';
@@ -12490,8 +12490,8 @@ var init_generatedDesignPipeline = __esm({
12490
12490
  }
12491
12491
  });
12492
12492
  function validateBlockSequence(snapshots, ctx) {
12493
- for (const issue4 of collectBlockSequenceIssues(snapshots)) {
12494
- ctx.addIssue(issue4);
12493
+ for (const issue5 of collectBlockSequenceIssues(snapshots)) {
12494
+ ctx.addIssue(issue5);
12495
12495
  }
12496
12496
  }
12497
12497
  function collectBlockSequenceIssues(snapshots) {
@@ -13344,11 +13344,11 @@ function bind(from, options) {
13344
13344
  }
13345
13345
  });
13346
13346
  }
13347
- function when(path25, options) {
13347
+ function when(path27, options) {
13348
13348
  return (node) => ({
13349
13349
  ...node,
13350
13350
  $when: {
13351
- when: { from: path25 },
13351
+ when: { from: path27 },
13352
13352
  ...options?.equals !== void 0 ? { equals: options.equals } : {},
13353
13353
  ...options?.not ? { not: true } : {}
13354
13354
  }
@@ -13455,7 +13455,7 @@ var init_builder2 = __esm({
13455
13455
  });
13456
13456
 
13457
13457
  // ../blocks/src/system/node/fragments/backgroundLayer.ts
13458
- function backgroundLayer(path25, options = {}) {
13458
+ function backgroundLayer(path27, options = {}) {
13459
13459
  const {
13460
13460
  styleClassName = "background-style rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full rb-w-full rb-pointer-events-none",
13461
13461
  imageClassName,
@@ -13469,7 +13469,7 @@ function backgroundLayer(path25, options = {}) {
13469
13469
  className: styleClassName,
13470
13470
  style: {
13471
13471
  $bind: {
13472
- from: path25,
13472
+ from: path27,
13473
13473
  transforms: [
13474
13474
  {
13475
13475
  id: "background.resolveStyle",
@@ -13479,20 +13479,20 @@ function backgroundLayer(path25, options = {}) {
13479
13479
  }
13480
13480
  }
13481
13481
  });
13482
- const imageLayer = createBackgroundImageNode(path25, imageClassName, {
13482
+ const imageLayer = createBackgroundImageNode(path27, imageClassName, {
13483
13483
  loading: imageLoading,
13484
13484
  fetchPriority: imageFetchPriority
13485
13485
  });
13486
- const overlayLayer = createBackgroundOverlayNode(path25, overlayClassName);
13486
+ const overlayLayer = createBackgroundOverlayNode(path27, overlayClassName);
13487
13487
  return omitImageLayer ? [styleLayer, overlayLayer] : [styleLayer, imageLayer, overlayLayer];
13488
13488
  }
13489
- function createBackgroundImageNode(path25, baseClassName = "rb-absolute rb-z-neg-10", options = {}) {
13490
- const imagePath = `${path25}.image`;
13489
+ function createBackgroundImageNode(path27, baseClassName = "rb-absolute rb-z-neg-10", options = {}) {
13490
+ const imagePath = `${path27}.image`;
13491
13491
  return media(
13492
13492
  {
13493
13493
  className: {
13494
13494
  $bind: {
13495
- from: path25,
13495
+ from: path27,
13496
13496
  transforms: [
13497
13497
  {
13498
13498
  id: "background.resolveImageClassName",
@@ -13503,7 +13503,7 @@ function createBackgroundImageNode(path25, baseClassName = "rb-absolute rb-z-neg
13503
13503
  },
13504
13504
  style: {
13505
13505
  $bind: {
13506
- from: path25,
13506
+ from: path27,
13507
13507
  transforms: [{ id: "background.resolveImageStyle" }]
13508
13508
  }
13509
13509
  },
@@ -13515,8 +13515,8 @@ function createBackgroundImageNode(path25, baseClassName = "rb-absolute rb-z-neg
13515
13515
  bind(imagePath)
13516
13516
  );
13517
13517
  }
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`;
13518
+ 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") {
13519
+ const overlayPath = `${path27}.overlay`;
13520
13520
  return el("div", {
13521
13521
  className,
13522
13522
  style: {
@@ -14356,10 +14356,10 @@ var init_sectionForegroundStyles = __esm({
14356
14356
  });
14357
14357
 
14358
14358
  // ../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) => {
14359
+ function readPath(source, path27) {
14360
+ if (!source || !path27) return void 0;
14361
+ if (!path27.includes(".")) return source[path27];
14362
+ return path27.split(".").reduce((acc, segment) => {
14363
14363
  if (acc && typeof acc === "object" && segment in acc) {
14364
14364
  return acc[segment];
14365
14365
  }
@@ -15351,27 +15351,27 @@ function scopePropValue(value, scope) {
15351
15351
  }
15352
15352
  return value;
15353
15353
  }
15354
- function scopeContentPath(path25, scope) {
15354
+ function scopeContentPath(path27, scope) {
15355
15355
  if (!scope || scope.length === 0) {
15356
- return path25;
15356
+ return path27;
15357
15357
  }
15358
- if (path25 === "content") {
15358
+ if (path27 === "content") {
15359
15359
  return `content.${scope}`;
15360
15360
  }
15361
- if (path25.startsWith("content.")) {
15362
- const remainder = path25.slice("content.".length);
15361
+ if (path27.startsWith("content.")) {
15362
+ const remainder = path27.slice("content.".length);
15363
15363
  return remainder.length > 0 ? `content.${scope}.${remainder}` : `content.${scope}`;
15364
15364
  }
15365
- if (path25.startsWith("content[")) {
15366
- return path25.replace(/^content/, `content.${scope}`);
15365
+ if (path27.startsWith("content[")) {
15366
+ return path27.replace(/^content/, `content.${scope}`);
15367
15367
  }
15368
- if (path25.startsWith("$root.")) {
15369
- return path25;
15368
+ if (path27.startsWith("$root.")) {
15369
+ return path27;
15370
15370
  }
15371
- if (path25.includes(".")) {
15372
- return path25;
15371
+ if (path27.includes(".")) {
15372
+ return path27;
15373
15373
  }
15374
- return `content.${scope}.${path25}`;
15374
+ return `content.${scope}.${path27}`;
15375
15375
  }
15376
15376
  var FRAGMENT_ID_PATTERN, FIELD_ID_PATTERN, dataLoaderSchema, fragmentDataSchema, fragmentConfigSchema, FragmentConfigError;
15377
15377
  var init_types14 = __esm({
@@ -18247,8 +18247,8 @@ function decodeSuccess(value) {
18247
18247
  function decodeFailure(issues) {
18248
18248
  return { ok: false, issues };
18249
18249
  }
18250
- function zodIssuePath(path25) {
18251
- return path25.flatMap((segment) => {
18250
+ function zodIssuePath(path27) {
18251
+ return path27.flatMap((segment) => {
18252
18252
  if (typeof segment === "string" || typeof segment === "number") {
18253
18253
  return [segment];
18254
18254
  }
@@ -18267,9 +18267,9 @@ function createZodCodec(schema) {
18267
18267
  return decodeSuccess(parsed.data);
18268
18268
  }
18269
18269
  return decodeFailure(
18270
- parsed.error.issues.map((issue4) => ({
18271
- path: zodIssuePath(issue4.path),
18272
- message: issue4.message
18270
+ parsed.error.issues.map((issue5) => ({
18271
+ path: zodIssuePath(issue5.path),
18272
+ message: issue5.message
18273
18273
  }))
18274
18274
  );
18275
18275
  }
@@ -28589,20 +28589,20 @@ function validationContext(options = {}) {
28589
28589
  allowIncomplete: isDraft || (options.allowIncomplete ?? false)
28590
28590
  };
28591
28591
  }
28592
- function formatFieldPath(path25) {
28593
- return path25.map((segment) => String(segment)).join(".");
28592
+ function formatFieldPath(path27) {
28593
+ return path27.map((segment) => String(segment)).join(".");
28594
28594
  }
28595
- function toZodIssuePath(path25) {
28596
- return [...path25];
28595
+ function toZodIssuePath(path27) {
28596
+ return [...path27];
28597
28597
  }
28598
- function fieldIssueToMessage(issue4) {
28599
- switch (issue4.kind) {
28598
+ function fieldIssueToMessage(issue5) {
28599
+ switch (issue5.kind) {
28600
28600
  case "required":
28601
28601
  return "This field is required";
28602
28602
  case "wrongType":
28603
- return `${issue4.label} needs ${issue4.expected}`;
28603
+ return `${issue5.label} needs ${issue5.expected}`;
28604
28604
  case "tooLong":
28605
- return `Use ${issue4.maximum} characters or fewer`;
28605
+ return `Use ${issue5.maximum} characters or fewer`;
28606
28606
  case "invalidEmail":
28607
28607
  return "Enter a valid email address";
28608
28608
  case "invalidPhone":
@@ -28618,36 +28618,36 @@ function fieldIssueToMessage(issue4) {
28618
28618
  case "invalidDateTime":
28619
28619
  return "Choose a valid date and time";
28620
28620
  case "invalidNumber":
28621
- return `${issue4.label} needs a number`;
28621
+ return `${issue5.label} needs a number`;
28622
28622
  case "tooSmall":
28623
- return `${issue4.label} must be ${issue4.minimum} or more`;
28623
+ return `${issue5.label} must be ${issue5.minimum} or more`;
28624
28624
  case "tooLarge":
28625
- return `${issue4.label} must be ${issue4.maximum} or less`;
28625
+ return `${issue5.label} must be ${issue5.maximum} or less`;
28626
28626
  case "invalidSlug":
28627
- return `${issue4.label} can only use lowercase letters, numbers, and dashes`;
28627
+ return `${issue5.label} can only use lowercase letters, numbers, and dashes`;
28628
28628
  case "invalidOption":
28629
- return `Choose one of the available options for ${issue4.label}`;
28629
+ return `Choose one of the available options for ${issue5.label}`;
28630
28630
  case "tooFewItems":
28631
- return `${issue4.label} must have at least ${issue4.minimum} ${pluralize(issue4.itemLabel, issue4.minimum)}`;
28631
+ return `${issue5.label} must have at least ${issue5.minimum} ${pluralize(issue5.itemLabel, issue5.minimum)}`;
28632
28632
  case "tooManyItems":
28633
- return `${issue4.label} must have at most ${issue4.maximum} ${pluralize(issue4.itemLabel, issue4.maximum)}`;
28633
+ return `${issue5.label} must have at most ${issue5.maximum} ${pluralize(issue5.itemLabel, issue5.maximum)}`;
28634
28634
  case "invalidRichText":
28635
- return `${issue4.label} must be valid rich text`;
28635
+ return `${issue5.label} must be valid rich text`;
28636
28636
  case "invalidMedia":
28637
- return `${issue4.label} must be a valid media item`;
28637
+ return `${issue5.label} must be a valid media item`;
28638
28638
  case "invalidLink":
28639
- return `${issue4.label} must be a valid link`;
28639
+ return `${issue5.label} must be a valid link`;
28640
28640
  case "invalidReference":
28641
- return `${issue4.label} must reference a valid item`;
28641
+ return `${issue5.label} must reference a valid item`;
28642
28642
  default:
28643
- return assertNever2(issue4);
28643
+ return assertNever2(issue5);
28644
28644
  }
28645
28645
  }
28646
28646
  function pluralize(label, count) {
28647
28647
  if (count === 1) return label;
28648
28648
  return label.endsWith("s") ? label : `${label}s`;
28649
28649
  }
28650
- function deriveFieldValidationPlan(field, path25 = [field.id]) {
28650
+ function deriveFieldValidationPlan(field, path27 = [field.id]) {
28651
28651
  const required = Boolean(field.required);
28652
28652
  switch (field.type) {
28653
28653
  case "text": {
@@ -28658,7 +28658,7 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28658
28658
  });
28659
28659
  if (typeof field.ui?.min === "number") constraints2.push({ kind: "numberMin", minimum: field.ui.min });
28660
28660
  if (typeof field.ui?.max === "number") constraints2.push({ kind: "numberMax", maximum: field.ui.max });
28661
- return makePlan("number", "number", field, path25, required, constraints2);
28661
+ return makePlan("number", "number", field, path27, required, constraints2);
28662
28662
  }
28663
28663
  const constraints = commonConstraints(required, {
28664
28664
  kind: field.ui?.widget === "iconPicker" ? "blockIconValue" : "textType"
@@ -28667,7 +28667,7 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28667
28667
  if (inputType === "tel") constraints.push({ kind: "phoneFormat" });
28668
28668
  if (field.ui?.pattern) constraints.push({ kind: "patternFormat", pattern: field.ui.pattern });
28669
28669
  if (typeof field.maxLength === "number") constraints.push({ kind: "maxLength", maximum: field.maxLength });
28670
- return makePlan("string", "string", field, path25, required, constraints);
28670
+ return makePlan("string", "string", field, path27, required, constraints);
28671
28671
  }
28672
28672
  case "number": {
28673
28673
  const constraints = commonConstraints(required, {
@@ -28675,34 +28675,34 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28675
28675
  });
28676
28676
  if (typeof field.min === "number") constraints.push({ kind: "numberMin", minimum: field.min });
28677
28677
  if (typeof field.max === "number") constraints.push({ kind: "numberMax", maximum: field.max });
28678
- return makePlan("number", "number", field, path25, required, constraints);
28678
+ return makePlan("number", "number", field, path27, required, constraints);
28679
28679
  }
28680
28680
  case "slug": {
28681
28681
  const constraints = commonConstraints(required, { kind: "textType" }, { kind: "slugFormat" });
28682
28682
  if (typeof field.maxLength === "number") constraints.push({ kind: "maxLength", maximum: field.maxLength });
28683
- return makePlan("string", "string", field, path25, required, constraints);
28683
+ return makePlan("string", "string", field, path27, required, constraints);
28684
28684
  }
28685
28685
  case "url":
28686
28686
  return makePlan(
28687
28687
  "string",
28688
28688
  "string",
28689
28689
  field,
28690
- path25,
28690
+ path27,
28691
28691
  required,
28692
28692
  commonConstraints(required, { kind: "textType" }, { kind: "urlFormat", allowRelative: Boolean(field.allowRelative) })
28693
28693
  );
28694
28694
  case "reference":
28695
- return makePlan("string", "string", field, path25, required, commonConstraints(required, { kind: "referenceText" }));
28695
+ return makePlan("string", "string", field, path27, required, commonConstraints(required, { kind: "referenceText" }));
28696
28696
  case "date":
28697
- return makePlan("string", "string", field, path25, required, commonConstraints(required, { kind: "textType" }, { kind: "dateFormat" }));
28697
+ return makePlan("string", "string", field, path27, required, commonConstraints(required, { kind: "textType" }, { kind: "dateFormat" }));
28698
28698
  case "time":
28699
- return makePlan("string", "string", field, path25, required, commonConstraints(required, { kind: "textType" }, { kind: "timeFormat" }));
28699
+ return makePlan("string", "string", field, path27, required, commonConstraints(required, { kind: "textType" }, { kind: "timeFormat" }));
28700
28700
  case "datetime":
28701
28701
  return makePlan(
28702
28702
  "string",
28703
28703
  "string",
28704
28704
  field,
28705
- path25,
28705
+ path27,
28706
28706
  required,
28707
28707
  commonConstraints(required, { kind: "textType" }, { kind: "datetimeFormat" })
28708
28708
  );
@@ -28711,7 +28711,7 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28711
28711
  "select",
28712
28712
  "select",
28713
28713
  field,
28714
- path25,
28714
+ path27,
28715
28715
  required,
28716
28716
  commonConstraints(required, {
28717
28717
  kind: "selectOption",
@@ -28720,40 +28720,40 @@ function deriveFieldValidationPlan(field, path25 = [field.id]) {
28720
28720
  })
28721
28721
  );
28722
28722
  case "richText":
28723
- return makePlan("richText", "object", field, path25, required, commonConstraints(required, { kind: "richTextDoc" }));
28723
+ return makePlan("richText", "object", field, path27, required, commonConstraints(required, { kind: "richTextDoc" }));
28724
28724
  case "media":
28725
28725
  case "file":
28726
- return makePlan("media", "object", field, path25, required, commonConstraints(required, { kind: "mediaObject" }));
28726
+ return makePlan("media", "object", field, path27, required, commonConstraints(required, { kind: "mediaObject" }));
28727
28727
  case "link":
28728
- return makePlan("link", "object", field, path25, required, commonConstraints(required, { kind: "linkObject" }));
28728
+ return makePlan("link", "object", field, path27, required, commonConstraints(required, { kind: "linkObject" }));
28729
28729
  case "boolean":
28730
- return makePlan("boolean", "boolean", field, path25, required, requiredConstraints(required));
28730
+ return makePlan("boolean", "boolean", field, path27, required, requiredConstraints(required));
28731
28731
  case "repeater":
28732
28732
  return {
28733
- ...makePlan("repeater", "array", field, path25, required, commonConstraints(required, { kind: "arrayType" })),
28733
+ ...makePlan("repeater", "array", field, path27, required, commonConstraints(required, { kind: "arrayType" })),
28734
28734
  ...field.polymorphic && field.itemTypes ? {
28735
- repeatedItemVariants: deriveRepeatedItemVariants(field, [...path25, 0])
28735
+ repeatedItemVariants: deriveRepeatedItemVariants(field, [...path27, 0])
28736
28736
  } : {
28737
- repeatedItemPlan: deriveNestedFieldPlans(getRepeaterFields(field), [...path25, 0])
28737
+ repeatedItemPlan: deriveNestedFieldPlans(getRepeaterFields(field), [...path27, 0])
28738
28738
  },
28739
28739
  constraints: withRepeaterItemConstraints(field, commonConstraints(required, { kind: "arrayType" }))
28740
28740
  };
28741
28741
  case "group":
28742
28742
  case "modal":
28743
28743
  return {
28744
- ...makePlan("group", "object", field, path25, required, requiredConstraints(required)),
28745
- children: deriveNestedFieldPlans(field.schema?.fields ?? [], path25),
28744
+ ...makePlan("group", "object", field, path27, required, requiredConstraints(required)),
28745
+ children: deriveNestedFieldPlans(field.schema?.fields ?? [], path27),
28746
28746
  allowNullChildren: field.type === "group" && field.ui?.widget === "locationPicker"
28747
28747
  };
28748
28748
  case "tabGroup":
28749
28749
  return {
28750
- ...makePlan("group", "object", field, path25, required, requiredConstraints(required)),
28751
- children: field.tabs.flatMap((tab) => deriveNestedFieldPlans(tab.fields, path25))
28750
+ ...makePlan("group", "object", field, path27, required, requiredConstraints(required)),
28751
+ children: field.tabs.flatMap((tab) => deriveNestedFieldPlans(tab.fields, path27))
28752
28752
  };
28753
28753
  case "presetOrCustom":
28754
28754
  case "contentTypeSelect":
28755
28755
  case "entryPicker":
28756
- return makePlan("passthrough", "unknown", field, path25, false, []);
28756
+ return makePlan("passthrough", "unknown", field, path27, false, []);
28757
28757
  default:
28758
28758
  return assertNever2(field);
28759
28759
  }
@@ -28767,14 +28767,14 @@ function commonConstraints(required, ...specific) {
28767
28767
  function requiredConstraints(required) {
28768
28768
  return required ? [{ kind: "required" }] : [];
28769
28769
  }
28770
- function makePlan(kind, valueKind2, field, path25, required, constraints) {
28770
+ function makePlan(kind, valueKind2, field, path27, required, constraints) {
28771
28771
  return {
28772
28772
  kind,
28773
28773
  valueKind: valueKind2,
28774
28774
  fieldId: field.id,
28775
28775
  label: field.label,
28776
28776
  fieldType: field.type,
28777
- path: path25,
28777
+ path: path27,
28778
28778
  required,
28779
28779
  visibility: fieldVisibility(field),
28780
28780
  constraints
@@ -29111,18 +29111,18 @@ function materializeRepeaterItemPlan(plan, parentPath, index) {
29111
29111
  return rebaseFieldPlanPath(plan, [...parentPath, 0], [...parentPath, index]);
29112
29112
  }
29113
29113
  function rebaseFieldPlanPath(plan, fromPrefix, toPrefix) {
29114
- const path25 = rebaseFieldPath(plan.path, fromPrefix, toPrefix);
29114
+ const path27 = rebaseFieldPath(plan.path, fromPrefix, toPrefix);
29115
29115
  switch (plan.kind) {
29116
29116
  case "group":
29117
29117
  return {
29118
29118
  ...plan,
29119
- path: path25,
29119
+ path: path27,
29120
29120
  children: plan.children.map((childPlan) => rebaseFieldPlanPath(childPlan, fromPrefix, toPrefix))
29121
29121
  };
29122
29122
  case "repeater":
29123
29123
  return {
29124
29124
  ...plan,
29125
- path: path25,
29125
+ path: path27,
29126
29126
  ...plan.repeatedItemVariants ? {
29127
29127
  repeatedItemVariants: plan.repeatedItemVariants.map((variant) => ({
29128
29128
  ...variant,
@@ -29143,20 +29143,20 @@ function rebaseFieldPlanPath(plan, fromPrefix, toPrefix) {
29143
29143
  case "passthrough":
29144
29144
  return {
29145
29145
  ...plan,
29146
- path: path25
29146
+ path: path27
29147
29147
  };
29148
29148
  default:
29149
29149
  return assertNever2(plan);
29150
29150
  }
29151
29151
  }
29152
- function rebaseFieldPath(path25, fromPrefix, toPrefix) {
29153
- if (!startsWithFieldPath(path25, fromPrefix)) {
29154
- throw new Error(`Cannot rebase field path ${formatFieldPath(path25)} from ${formatFieldPath(fromPrefix)}`);
29152
+ function rebaseFieldPath(path27, fromPrefix, toPrefix) {
29153
+ if (!startsWithFieldPath(path27, fromPrefix)) {
29154
+ throw new Error(`Cannot rebase field path ${formatFieldPath(path27)} from ${formatFieldPath(fromPrefix)}`);
29155
29155
  }
29156
- return [...toPrefix, ...path25.slice(fromPrefix.length)];
29156
+ return [...toPrefix, ...path27.slice(fromPrefix.length)];
29157
29157
  }
29158
- function startsWithFieldPath(path25, prefix) {
29159
- return prefix.every((segment, index) => path25[index] === segment);
29158
+ function startsWithFieldPath(path27, prefix) {
29159
+ return prefix.every((segment, index) => path27[index] === segment);
29160
29160
  }
29161
29161
  function issue(plan, kind, extra) {
29162
29162
  return {
@@ -29182,8 +29182,8 @@ function fieldPlanToZod(plan, options = {}) {
29182
29182
  }
29183
29183
  function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
29184
29184
  const message = fieldIssueToMessage(validationIssue);
29185
- const path25 = relativeZodIssuePath(validationIssue.path, rootPath);
29186
- const issuePath = path25.length > 0 ? { path: toZodIssuePath(path25) } : {};
29185
+ const path27 = relativeZodIssuePath(validationIssue.path, rootPath);
29186
+ const issuePath = path27.length > 0 ? { path: toZodIssuePath(path27) } : {};
29187
29187
  switch (validationIssue.kind) {
29188
29188
  case "required":
29189
29189
  if (validationIssue.emptyOrigin) {
@@ -29236,8 +29236,8 @@ function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
29236
29236
  assertNever2(validationIssue);
29237
29237
  }
29238
29238
  }
29239
- function relativeZodIssuePath(path25, rootPath) {
29240
- return startsWithFieldPath(path25, rootPath) ? path25.slice(rootPath.length) : path25;
29239
+ function relativeZodIssuePath(path27, rootPath) {
29240
+ return startsWithFieldPath(path27, rootPath) ? path27.slice(rootPath.length) : path27;
29241
29241
  }
29242
29242
  function compilePattern(pattern) {
29243
29243
  try {
@@ -32395,9 +32395,9 @@ function maybeBuildSupabaseTransformUrl(inputUrl, options) {
32395
32395
  const remainder = url.pathname.slice(idx + marker.length);
32396
32396
  const parts = remainder.split("/").filter(Boolean);
32397
32397
  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}`;
32398
+ const path27 = parts.slice(1).join("/");
32399
+ if (!bucket || !path27) return inputUrl;
32400
+ url.pathname = `/storage/v1/render/image/public/${bucket}/${path27}`;
32401
32401
  url.search = "";
32402
32402
  if (width) url.searchParams.set("width", String(width));
32403
32403
  if (height) url.searchParams.set("height", String(height));
@@ -42213,17 +42213,21 @@ function looksLikeLocalAuthority(authority) {
42213
42213
  const normalized = authority.toLowerCase();
42214
42214
  return normalized === "localhost" || normalized.startsWith("localhost:") || normalized.startsWith("127.") || normalized.startsWith("0.0.0.0") || normalized.includes(".localhost") || normalized.endsWith(".local") || normalized.endsWith(".test");
42215
42215
  }
42216
- function normalizeDashboardUrlBase(input) {
42216
+ function normalizeDashboardOrigin(input) {
42217
42217
  const trimmed = input.trim();
42218
42218
  if (!trimmed) return "";
42219
42219
  const withoutTrailingSlash = trimmed.replace(/\/+$/, "");
42220
42220
  const withoutApiSuffix = withoutTrailingSlash.replace(/\/api\/?$/, "");
42221
42221
  if (/^https?:\/\//i.test(withoutApiSuffix)) {
42222
- return withoutApiSuffix;
42222
+ return new URL(withoutApiSuffix).origin;
42223
42223
  }
42224
42224
  const authority = withoutApiSuffix.replace(/^\/+/, "");
42225
42225
  const protocol = looksLikeLocalAuthority(authority) ? "http" : "https";
42226
- return `${protocol}://${authority}`;
42226
+ return new URL(`${protocol}://${authority}`).origin;
42227
+ }
42228
+ function deriveCmsApiUrlFromDashboardUrl(input) {
42229
+ const origin = normalizeDashboardOrigin(input);
42230
+ return origin ? `${origin}/api` : "";
42227
42231
  }
42228
42232
  function getCmsApiUrl() {
42229
42233
  if (typeof window !== "undefined") {
@@ -42235,15 +42239,10 @@ function getCmsApiUrl() {
42235
42239
  }
42236
42240
  const dashboardUrl = process.env.NEXT_PUBLIC_DASHBOARD_URL;
42237
42241
  if (dashboardUrl) {
42238
- const base = normalizeDashboardUrlBase(dashboardUrl);
42239
- return `${base}/api`;
42240
- }
42241
- const legacyApiUrl = process.env.NEXT_PUBLIC_CMS_API_URL;
42242
- if (legacyApiUrl) {
42243
- return legacyApiUrl.replace(/\/$/, "");
42242
+ return deriveCmsApiUrlFromDashboardUrl(dashboardUrl);
42244
42243
  }
42245
42244
  throw new Error(
42246
- "NEXT_PUBLIC_DASHBOARD_URL is not configured. Set it to your dashboard URL (e.g., http://localhost:4000)"
42245
+ "CMS_API_URL or NEXT_PUBLIC_DASHBOARD_URL is not configured. Set NEXT_PUBLIC_DASHBOARD_URL to your dashboard URL (e.g., http://localhost:4000)"
42247
42246
  );
42248
42247
  }
42249
42248
  function resolveApiBaseUrl() {
@@ -43008,11 +43007,11 @@ siteBannerSettingsSchema.superRefine((value, ctx) => {
43008
43007
  return;
43009
43008
  }
43010
43009
  const analysis = analyzeSiteBannerBody(value.body);
43011
- for (const issue4 of analysis.issues) {
43010
+ for (const issue5 of analysis.issues) {
43012
43011
  ctx.addIssue({
43013
43012
  code: z.ZodIssueCode.custom,
43014
43013
  path: ["body"],
43015
- message: siteBannerBodyIssueMessage(issue4)
43014
+ message: siteBannerBodyIssueMessage(issue5)
43016
43015
  });
43017
43016
  }
43018
43017
  });
@@ -43046,8 +43045,8 @@ function analyzeSiteBannerBody(body) {
43046
43045
  issues
43047
43046
  };
43048
43047
  }
43049
- function siteBannerBodyIssueMessage(issue4) {
43050
- switch (issue4) {
43048
+ function siteBannerBodyIssueMessage(issue5) {
43049
+ switch (issue5) {
43051
43050
  case "empty":
43052
43051
  return "Banner message is required when the banner is enabled.";
43053
43052
  case "too-many-paragraphs":
@@ -43555,8 +43554,8 @@ var TEMPLATE_BINDING_META_PATHS = [
43555
43554
  "createdAt",
43556
43555
  "updatedAt"
43557
43556
  ];
43558
- function describeInvalidTemplateBindingMetaPath(path25) {
43559
- return `Meta path "${path25}" is not valid. Allowed: ${TEMPLATE_BINDING_META_PATHS.join(", ")}`;
43557
+ function describeInvalidTemplateBindingMetaPath(path27) {
43558
+ return `Meta path "${path27}" is not valid. Allowed: ${TEMPLATE_BINDING_META_PATHS.join(", ")}`;
43560
43559
  }
43561
43560
 
43562
43561
  // ../content-model/src/routeTemplate.ts
@@ -43730,7 +43729,7 @@ var fieldBindingSchema = z.object({
43730
43729
  var metaBindingSchema = z.object({
43731
43730
  source: z.literal("meta"),
43732
43731
  path: z.enum(TEMPLATE_BINDING_META_PATHS, {
43733
- error: (issue4) => describeInvalidTemplateBindingMetaPath(String(issue4.input))
43732
+ error: (issue5) => describeInvalidTemplateBindingMetaPath(String(issue5.input))
43734
43733
  })
43735
43734
  });
43736
43735
  var literalBindingSchema = z.object({
@@ -43741,7 +43740,7 @@ var transformBindingSchema = z.object({
43741
43740
  source: z.literal("transform"),
43742
43741
  path: z.string().min(1, "Transform path is required"),
43743
43742
  transform: z.enum(BINDING_TRANSFORM_VALUES, {
43744
- error: (issue4) => describeInvalidBindingTransform(String(issue4.input))
43743
+ error: (issue5) => describeInvalidBindingTransform(String(issue5.input))
43745
43744
  })
43746
43745
  });
43747
43746
  var baseBindingSchema = z.discriminatedUnion("source", [
@@ -43945,7 +43944,7 @@ var contentConfigSchema = contentConfigBaseSchema.superRefine((data, ctx) => {
43945
43944
  });
43946
43945
  }
43947
43946
  const paths = data.pages.map((p) => p.path);
43948
- const duplicatePaths = paths.filter((path25, i) => paths.indexOf(path25) !== i);
43947
+ const duplicatePaths = paths.filter((path27, i) => paths.indexOf(path27) !== i);
43949
43948
  if (duplicatePaths.length > 0) {
43950
43949
  ctx.addIssue({
43951
43950
  code: z.ZodIssueCode.custom,
@@ -44002,18 +44001,18 @@ function validateLayoutNodeTypes(layout) {
44002
44001
  errors
44003
44002
  };
44004
44003
  }
44005
- function validateNodeTypesRecursive(node, path25, errors) {
44004
+ function validateNodeTypesRecursive(node, path27, errors) {
44006
44005
  if (!ALLOWED_NODE_TYPES_SET.has(node.type)) {
44007
44006
  errors.push({
44008
- path: `${path25}.type`,
44007
+ path: `${path27}.type`,
44009
44008
  type: "invalid_node_type",
44010
44009
  value: node.type,
44011
- message: `Unknown node type "${node.type}" at ${path25}. Valid types: section, stack, text, etc.`
44010
+ message: `Unknown node type "${node.type}" at ${path27}. Valid types: section, stack, text, etc.`
44012
44011
  });
44013
44012
  }
44014
44013
  if (node.children && Array.isArray(node.children)) {
44015
44014
  node.children.forEach((child, index) => {
44016
- validateNodeTypesRecursive(child, `${path25}.children[${index}]`, errors);
44015
+ validateNodeTypesRecursive(child, `${path27}.children[${index}]`, errors);
44017
44016
  });
44018
44017
  }
44019
44018
  }
@@ -44025,45 +44024,45 @@ function validateTransformIds(layout) {
44025
44024
  errors
44026
44025
  };
44027
44026
  }
44028
- function validateTransformIdsRecursive(node, path25, errors) {
44027
+ function validateTransformIdsRecursive(node, path27, errors) {
44029
44028
  if (node.$bind?.transforms && Array.isArray(node.$bind.transforms)) {
44030
- validateTransformList(node.$bind.transforms, `${path25}.$bind.transforms`, errors);
44029
+ validateTransformList(node.$bind.transforms, `${path27}.$bind.transforms`, errors);
44031
44030
  }
44032
44031
  if (node.$repeat?.collection?.transforms && Array.isArray(node.$repeat.collection.transforms)) {
44033
- validateTransformList(node.$repeat.collection.transforms, `${path25}.$repeat.collection.transforms`, errors);
44032
+ validateTransformList(node.$repeat.collection.transforms, `${path27}.$repeat.collection.transforms`, errors);
44034
44033
  }
44035
44034
  if (node.$when?.when?.transforms && Array.isArray(node.$when.when.transforms)) {
44036
- validateTransformList(node.$when.when.transforms, `${path25}.$when.when.transforms`, errors);
44035
+ validateTransformList(node.$when.when.transforms, `${path27}.$when.when.transforms`, errors);
44037
44036
  }
44038
44037
  if (node.$scopes && Array.isArray(node.$scopes)) {
44039
44038
  node.$scopes.forEach((scope, index) => {
44040
44039
  if (scope.from?.transforms && Array.isArray(scope.from.transforms)) {
44041
- validateTransformList(scope.from.transforms, `${path25}.$scopes[${index}].from.transforms`, errors);
44040
+ validateTransformList(scope.from.transforms, `${path27}.$scopes[${index}].from.transforms`, errors);
44042
44041
  }
44043
44042
  });
44044
44043
  }
44045
44044
  if (node.props) {
44046
- validatePropsTransforms(node.props, `${path25}.props`, errors);
44045
+ validatePropsTransforms(node.props, `${path27}.props`, errors);
44047
44046
  }
44048
44047
  if (node.children && Array.isArray(node.children)) {
44049
44048
  node.children.forEach((child, index) => {
44050
- validateTransformIdsRecursive(child, `${path25}.children[${index}]`, errors);
44049
+ validateTransformIdsRecursive(child, `${path27}.children[${index}]`, errors);
44051
44050
  });
44052
44051
  }
44053
44052
  }
44054
- function validateTransformList(transforms, path25, errors) {
44053
+ function validateTransformList(transforms, path27, errors) {
44055
44054
  transforms.forEach((transform, index) => {
44056
44055
  if (!ALLOWED_TRANSFORM_IDS_SET.has(transform.id)) {
44057
44056
  errors.push({
44058
- path: `${path25}[${index}].id`,
44057
+ path: `${path27}[${index}].id`,
44059
44058
  type: "invalid_transform_id",
44060
44059
  value: transform.id,
44061
- message: `Unknown transform "${transform.id}" at ${path25}. Valid transforms: string.uppercase, value.fallback, etc.`
44060
+ message: `Unknown transform "${transform.id}" at ${path27}. Valid transforms: string.uppercase, value.fallback, etc.`
44062
44061
  });
44063
44062
  }
44064
44063
  });
44065
44064
  }
44066
- function validatePropsTransforms(props2, path25, errors) {
44065
+ function validatePropsTransforms(props2, path27, errors) {
44067
44066
  for (const [key, value] of Object.entries(props2)) {
44068
44067
  if (isBindingObject(value)) {
44069
44068
  const binding = value;
@@ -44071,16 +44070,16 @@ function validatePropsTransforms(props2, path25, errors) {
44071
44070
  binding.$bind.transforms.forEach((transform, index) => {
44072
44071
  if (!ALLOWED_TRANSFORM_IDS_SET.has(transform.id)) {
44073
44072
  errors.push({
44074
- path: `${path25}.${key}.$bind.transforms[${index}].id`,
44073
+ path: `${path27}.${key}.$bind.transforms[${index}].id`,
44075
44074
  type: "invalid_transform_id",
44076
44075
  value: transform.id,
44077
- message: `Unknown transform "${transform.id}" at ${path25}.${key}. Valid transforms: string.uppercase, value.fallback, etc.`
44076
+ message: `Unknown transform "${transform.id}" at ${path27}.${key}. Valid transforms: string.uppercase, value.fallback, etc.`
44078
44077
  });
44079
44078
  }
44080
44079
  });
44081
44080
  }
44082
44081
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
44083
- validatePropsTransforms(value, `${path25}.${key}`, errors);
44082
+ validatePropsTransforms(value, `${path27}.${key}`, errors);
44084
44083
  }
44085
44084
  }
44086
44085
  }
@@ -44625,8 +44624,8 @@ async function readApiResponse(response, requestInfo, options = {}) {
44625
44624
  function createHttpClient(config2) {
44626
44625
  const baseUrl = `${config2.dashboardUrl}/api/sdk/${config2.siteId}`;
44627
44626
  const timeout = config2.timeout ?? 3e4;
44628
- async function request(method, path25, options) {
44629
- let url = `${baseUrl}${path25}`;
44627
+ async function request(method, path27, options) {
44628
+ let url = `${baseUrl}${path27}`;
44630
44629
  if (options?.params && Object.keys(options.params).length > 0) {
44631
44630
  const searchParams = new URLSearchParams(options.params);
44632
44631
  url = `${url}?${searchParams.toString()}`;
@@ -44649,7 +44648,7 @@ function createHttpClient(config2) {
44649
44648
  } catch (error) {
44650
44649
  const requestInfo2 = buildRequestInfo({
44651
44650
  method,
44652
- path: path25,
44651
+ path: path27,
44653
44652
  url,
44654
44653
  baseUrl,
44655
44654
  dashboardUrl: config2.dashboardUrl,
@@ -44674,7 +44673,7 @@ function createHttpClient(config2) {
44674
44673
  }
44675
44674
  const requestInfo = buildRequestInfo({
44676
44675
  method,
44677
- path: path25,
44676
+ path: path27,
44678
44677
  url,
44679
44678
  baseUrl,
44680
44679
  dashboardUrl: config2.dashboardUrl,
@@ -44704,17 +44703,17 @@ function createHttpClient(config2) {
44704
44703
  return json.data;
44705
44704
  }
44706
44705
  return {
44707
- async get(path25, params) {
44708
- return request("GET", path25, { params });
44706
+ async get(path27, params) {
44707
+ return request("GET", path27, { params });
44709
44708
  },
44710
- async post(path25, body) {
44711
- return request("POST", path25, { body });
44709
+ async post(path27, body) {
44710
+ return request("POST", path27, { body });
44712
44711
  },
44713
- async patch(path25, body) {
44714
- return request("PATCH", path25, { body });
44712
+ async patch(path27, body) {
44713
+ return request("PATCH", path27, { body });
44715
44714
  },
44716
- async delete(path25, body) {
44717
- await request("DELETE", path25, { body });
44715
+ async delete(path27, body) {
44716
+ await request("DELETE", path27, { body });
44718
44717
  }
44719
44718
  };
44720
44719
  }
@@ -46159,12 +46158,12 @@ function collectPushConfigSyncWarnings(sync) {
46159
46158
  async function pushToDashboard(output, dashboardUrl, siteId, apiKey, config2, options) {
46160
46159
  const normalizedDashboardUrl = dashboardUrl.replace(/\/+$/, "");
46161
46160
  const baseUrl = `${normalizedDashboardUrl}/api`;
46162
- const path25 = `/sites/${siteId}/sdk-config`;
46163
- const pushUrl = `${baseUrl}${path25}`;
46161
+ const path27 = `/sites/${siteId}/sdk-config`;
46162
+ const pushUrl = `${baseUrl}${path27}`;
46164
46163
  output.info(`Pushing config to ${pushUrl}...`);
46165
46164
  const requestInfo = {
46166
46165
  method: "POST",
46167
- path: path25,
46166
+ path: path27,
46168
46167
  url: pushUrl,
46169
46168
  baseUrl,
46170
46169
  dashboardUrl: normalizedDashboardUrl,
@@ -46234,9 +46233,9 @@ async function pushConfigAction(output, options) {
46234
46233
  const parseResult = riverbankSiteConfigSchema.safeParse(rawConfig);
46235
46234
  if (!parseResult.success) {
46236
46235
  output.error("Invalid config", {
46237
- issues: parseResult.error.issues.map((issue4) => ({
46238
- path: issue4.path.join("."),
46239
- message: issue4.message
46236
+ issues: parseResult.error.issues.map((issue5) => ({
46237
+ path: issue5.path.join("."),
46238
+ message: issue5.message
46240
46239
  }))
46241
46240
  });
46242
46241
  }
@@ -46943,23 +46942,7 @@ async function writeEvents(contentDir, pulledEvents, options) {
46943
46942
  const eventsMeta = {};
46944
46943
  for (const event of pulledEvents.events) {
46945
46944
  const filePath = path5.join(eventsDir, `${event.identifier}.json`);
46946
- const eventPayload = {
46947
- identifier: event.identifier,
46948
- title: event.title,
46949
- slug: event.slug,
46950
- status: event.status,
46951
- visibility: event.visibility,
46952
- schedule: event.schedule,
46953
- capacity: event.capacity,
46954
- pricing: event.pricing,
46955
- venueRef: event.venueRef,
46956
- categoryRef: event.categoryRef,
46957
- content: event.content,
46958
- formRef: event.formRef,
46959
- settings: event.settings,
46960
- presentation: event.presentation,
46961
- tags: event.tags
46962
- };
46945
+ const eventPayload = toWritableLocalEvent(event);
46963
46946
  stripEnvSpecificMediaFieldsInPlace(eventPayload);
46964
46947
  await writeJsonFile(filePath, eventPayload);
46965
46948
  filePaths.push(filePath);
@@ -46979,6 +46962,26 @@ async function writeEvents(contentDir, pulledEvents, options) {
46979
46962
  }
46980
46963
  return { filePaths, metaPath };
46981
46964
  }
46965
+ function toWritableLocalEvent(event) {
46966
+ return {
46967
+ identifier: event.identifier,
46968
+ title: event.title,
46969
+ slug: event.slug,
46970
+ status: event.status,
46971
+ visibility: event.visibility,
46972
+ schedule: event.schedule,
46973
+ capacity: event.capacity,
46974
+ pricing: event.pricing,
46975
+ paymentTerms: event.paymentTerms,
46976
+ venueRef: event.venueRef,
46977
+ categoryRef: event.categoryRef,
46978
+ content: event.content,
46979
+ formRef: event.formRef,
46980
+ settings: event.settings,
46981
+ presentation: event.presentation,
46982
+ tags: event.tags
46983
+ };
46984
+ }
46982
46985
  async function writeCourses(contentDir, pulledCourses, options) {
46983
46986
  const coursesDir = path5.join(contentDir, "courses");
46984
46987
  const metaDir = path5.join(contentDir, ".meta");
@@ -47316,7 +47319,7 @@ async function readSettings(contentDir) {
47316
47319
  throw new Error(
47317
47320
  `${filePath}: invalid settings.json
47318
47321
  ` + parsed.error.issues.map(
47319
- (issue4) => ` - ${issue4.path.join(".") || "(root)"}: ${issue4.message}`
47322
+ (issue5) => ` - ${issue5.path.join(".") || "(root)"}: ${issue5.message}`
47320
47323
  ).join("\n")
47321
47324
  );
47322
47325
  }
@@ -49034,11 +49037,11 @@ function findChangedFields(local, remote, prefix = "") {
49034
49037
  const changes = [];
49035
49038
  const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(remote)]);
49036
49039
  for (const key of allKeys) {
49037
- const path25 = prefix ? `${prefix}.${key}` : key;
49040
+ const path27 = prefix ? `${prefix}.${key}` : key;
49038
49041
  const localVal = local[key];
49039
49042
  const remoteVal = remote[key];
49040
49043
  if (!equal(localVal, remoteVal)) {
49041
- changes.push(path25);
49044
+ changes.push(path27);
49042
49045
  }
49043
49046
  }
49044
49047
  return changes;
@@ -50108,11 +50111,11 @@ function findChangedFieldsWithValues(local, remote, prefix = "") {
50108
50111
  const changes = [];
50109
50112
  const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(remote)]);
50110
50113
  for (const key of allKeys) {
50111
- const path25 = prefix ? `${prefix}.${key}` : key;
50114
+ const path27 = prefix ? `${prefix}.${key}` : key;
50112
50115
  const localVal = local[key];
50113
50116
  const remoteVal = remote[key];
50114
50117
  if (!equal(localVal, remoteVal)) {
50115
- changes.push({ path: path25, before: remoteVal, after: localVal });
50118
+ changes.push({ path: path27, before: remoteVal, after: localVal });
50116
50119
  }
50117
50120
  }
50118
50121
  return changes;
@@ -50529,6 +50532,117 @@ function maskPullDiffForScope(diff, pullScope) {
50529
50532
  }
50530
50533
  return diff;
50531
50534
  }
50535
+ var CANONICAL_EVENT_ENTRY_TYPE = "event";
50536
+ var EVENT_MIGRATION_COMMAND = "riverbankcms migrate events";
50537
+ var EVENT_PUSH_COMMAND = "riverbankcms push events";
50538
+ var EVENT_PULL_COMMAND = "riverbankcms pull events";
50539
+ var CANONICAL_ENTRY_POLICIES = [{
50540
+ contentType: CANONICAL_EVENT_ENTRY_TYPE,
50541
+ migrationCommand: EVENT_MIGRATION_COMMAND,
50542
+ commands: {
50543
+ push: EVENT_PUSH_COMMAND,
50544
+ pull: EVENT_PULL_COMMAND
50545
+ }
50546
+ }];
50547
+ function getCanonicalEntryPolicy(contentType) {
50548
+ const normalizedType = contentType?.trim().toLowerCase();
50549
+ return CANONICAL_ENTRY_POLICIES.find((policy) => policy.contentType === normalizedType) ?? null;
50550
+ }
50551
+ function buildScopeViolation(input) {
50552
+ const command = input.policy.commands[input.operation];
50553
+ return {
50554
+ contentType: input.policy.contentType,
50555
+ message: "`event` entries are managed through the canonical events surface.",
50556
+ 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.`
50557
+ };
50558
+ }
50559
+ function getCanonicalEntrySyncDecision(input) {
50560
+ const normalizedScope = input.scope.toLowerCase();
50561
+ if (normalizedScope === "entries") {
50562
+ const scopedPolicy = getCanonicalEntryPolicy(input.contentType);
50563
+ if (scopedPolicy) {
50564
+ return {
50565
+ tag: "reject",
50566
+ violation: buildScopeViolation({ policy: scopedPolicy, operation: input.operation })
50567
+ };
50568
+ }
50569
+ if (!input.contentType) {
50570
+ return {
50571
+ tag: "allow-with-canonical-exclusions",
50572
+ policies: CANONICAL_ENTRY_POLICIES
50573
+ };
50574
+ }
50575
+ }
50576
+ if (normalizedScope === "all") {
50577
+ return {
50578
+ tag: "allow-with-canonical-exclusions",
50579
+ policies: CANONICAL_ENTRY_POLICIES
50580
+ };
50581
+ }
50582
+ return { tag: "allow" };
50583
+ }
50584
+ function shouldExcludeCanonicalEntries(decision) {
50585
+ return decision.tag === "allow-with-canonical-exclusions";
50586
+ }
50587
+ function filterGenericEntryContentTypes(contentTypes) {
50588
+ return contentTypes.filter((contentType) => !getCanonicalEntryPolicy(contentType));
50589
+ }
50590
+ function stripCanonicalEventEntriesFromLocalContent(content) {
50591
+ const eventEntries = content.entries.get(CANONICAL_EVENT_ENTRY_TYPE);
50592
+ if (!eventEntries) {
50593
+ return { content, removedEntryCount: 0, removedContentTypes: [] };
50594
+ }
50595
+ const entries = new Map(content.entries);
50596
+ entries.delete(CANONICAL_EVENT_ENTRY_TYPE);
50597
+ return {
50598
+ content: { ...content, entries },
50599
+ removedEntryCount: eventEntries.length,
50600
+ removedContentTypes: [CANONICAL_EVENT_ENTRY_TYPE]
50601
+ };
50602
+ }
50603
+ function stripCanonicalEventEntriesFromPulledContent(content) {
50604
+ const eventEntries = content.entries[CANONICAL_EVENT_ENTRY_TYPE];
50605
+ if (!eventEntries) {
50606
+ return { content, removedEntryCount: 0, removedContentTypes: [] };
50607
+ }
50608
+ const { [CANONICAL_EVENT_ENTRY_TYPE]: _removed, ...entries } = content.entries;
50609
+ const filteredMetaEntries = Object.fromEntries(
50610
+ Object.entries(content.meta.entries ?? {}).filter(([key]) => {
50611
+ const [contentType] = key.split(":");
50612
+ return contentType !== CANONICAL_EVENT_ENTRY_TYPE;
50613
+ })
50614
+ );
50615
+ return {
50616
+ content: {
50617
+ ...content,
50618
+ entries,
50619
+ meta: {
50620
+ ...content.meta,
50621
+ ...content.meta.entries ? { entries: filteredMetaEntries } : {}
50622
+ }
50623
+ },
50624
+ removedEntryCount: eventEntries.length,
50625
+ removedContentTypes: [CANONICAL_EVENT_ENTRY_TYPE]
50626
+ };
50627
+ }
50628
+ async function findLegacyEventEntryFiles(contentDir) {
50629
+ const eventEntriesDir = path5.join(contentDir, "entries", CANONICAL_EVENT_ENTRY_TYPE);
50630
+ try {
50631
+ const items = await fs5.readdir(eventEntriesDir, { withFileTypes: true });
50632
+ return items.filter((item) => item.isFile() && item.name.endsWith(".json")).map((item) => path5.join(eventEntriesDir, item.name)).sort();
50633
+ } catch (error) {
50634
+ if (error.code === "ENOENT") {
50635
+ return [];
50636
+ }
50637
+ throw error;
50638
+ }
50639
+ }
50640
+ function formatLegacyEventEntryWarning(files) {
50641
+ return {
50642
+ files: files.map((file) => path5.relative(process.cwd(), file)),
50643
+ suggestion: `Generic event entry files are ignored by broad sync. Run "${EVENT_MIGRATION_COMMAND}" to fold legacy event copy into content/events/*.json.`
50644
+ };
50645
+ }
50532
50646
  function findChangedTopLevelKeys(a, b) {
50533
50647
  const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
50534
50648
  const changed = [];
@@ -50880,6 +50994,17 @@ async function fetchAllContentPaginated(client, contentTypes, output, baseConten
50880
50994
  }
50881
50995
  };
50882
50996
  }
50997
+ async function pullAllContentWithCanonicalEntryPolicy(client, output) {
50998
+ const result = await client.pull.all();
50999
+ if (!result.meta.truncated) {
51000
+ return stripCanonicalEventEntriesFromPulledContent(result).content;
51001
+ }
51002
+ output.warn("Content was truncated due to size limits.");
51003
+ output.info("Fetching complete data via pagination...");
51004
+ const contentTypes = filterGenericEntryContentTypes(Object.keys(result.entries));
51005
+ const paginatedResult = await fetchAllContentPaginated(client, contentTypes, output, result);
51006
+ return stripCanonicalEventEntriesFromPulledContent(paginatedResult).content;
51007
+ }
50883
51008
  function createScopedPullContent(meta, overrides) {
50884
51009
  return {
50885
51010
  entries: {},
@@ -51012,6 +51137,30 @@ function shouldPromptForOverwrite(opts) {
51012
51137
  if (opts.force || opts.yes) return false;
51013
51138
  return true;
51014
51139
  }
51140
+ function emitCanonicalEntryScopeRejection(output, decision) {
51141
+ if (decision.tag !== "reject") {
51142
+ return false;
51143
+ }
51144
+ process.exitCode = 1;
51145
+ output.result(false, decision.violation.message, {
51146
+ contentType: decision.violation.contentType,
51147
+ suggestion: decision.violation.suggestion
51148
+ });
51149
+ return true;
51150
+ }
51151
+ async function warnForLocalLegacyEventEntries(input) {
51152
+ if (!shouldExcludeCanonicalEntries(input.decision) || !input.dirExists) {
51153
+ return;
51154
+ }
51155
+ const legacyEventEntryFiles = await findLegacyEventEntryFiles(input.contentDir);
51156
+ if (legacyEventEntryFiles.length === 0) {
51157
+ return;
51158
+ }
51159
+ input.output.warn(
51160
+ "Legacy event entry files detected and ignored by generic entry sync.",
51161
+ formatLegacyEventEntryWarning(legacyEventEntryFiles)
51162
+ );
51163
+ }
51015
51164
  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", `
51016
51165
  Examples:
51017
51166
  $ riverbankcms pull # Pull all content
@@ -51103,6 +51252,20 @@ Media Sync:
51103
51252
  });
51104
51253
  return;
51105
51254
  }
51255
+ const canonicalEntrySyncDecision2 = getCanonicalEntrySyncDecision({
51256
+ scope: pullScope2,
51257
+ contentType: type,
51258
+ operation: "pull"
51259
+ });
51260
+ if (emitCanonicalEntryScopeRejection(output, canonicalEntrySyncDecision2)) {
51261
+ return;
51262
+ }
51263
+ await warnForLocalLegacyEventEntries({
51264
+ output,
51265
+ contentDir,
51266
+ decision: canonicalEntrySyncDecision2,
51267
+ dirExists: await contentDirExists(contentDir)
51268
+ });
51106
51269
  output.info(`[DRY RUN] Fetching content from ${envLabel}...`);
51107
51270
  if (options.withTheme && pullScope2 !== "all") {
51108
51271
  output.warn('--with-theme only applies when pulling all content (use "riverbankcms pull theme" instead)');
@@ -51309,13 +51472,7 @@ Media Sync:
51309
51472
  { entries: { [type]: pulled.entries } }
51310
51473
  );
51311
51474
  } else {
51312
- let result = await client.pull.all();
51313
- if (result.meta.truncated) {
51314
- output.warn("Content was truncated due to size limits.");
51315
- output.info("Fetching complete data via pagination...");
51316
- const contentTypes = Object.keys(result.entries);
51317
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51318
- }
51475
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51319
51476
  remoteContent = createScopedPullContent(result.meta, { entries: result.entries });
51320
51477
  }
51321
51478
  break;
@@ -51354,13 +51511,7 @@ Media Sync:
51354
51511
  `[DRY RUN] Would also pull theme to ${path5.join(path5.basename(contentDir), "themes", `${themeName}.json`)}`
51355
51512
  );
51356
51513
  }
51357
- let result = await client.pull.all();
51358
- if (result.meta.truncated) {
51359
- output.warn("Content was truncated due to size limits.");
51360
- output.info("Fetching complete data via pagination...");
51361
- const contentTypes = Object.keys(result.entries);
51362
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51363
- }
51514
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51364
51515
  remoteContent = result;
51365
51516
  break;
51366
51517
  }
@@ -51469,6 +51620,20 @@ Media Sync:
51469
51620
  });
51470
51621
  return;
51471
51622
  }
51623
+ const canonicalEntrySyncDecision = getCanonicalEntrySyncDecision({
51624
+ scope: pullScope,
51625
+ contentType: type,
51626
+ operation: "pull"
51627
+ });
51628
+ if (emitCanonicalEntryScopeRejection(output, canonicalEntrySyncDecision)) {
51629
+ return;
51630
+ }
51631
+ await warnForLocalLegacyEventEntries({
51632
+ output,
51633
+ contentDir,
51634
+ decision: canonicalEntrySyncDecision,
51635
+ dirExists
51636
+ });
51472
51637
  if (shouldPromptForOverwrite({
51473
51638
  pullScope,
51474
51639
  contentDirExists: dirExists,
@@ -51578,13 +51743,7 @@ Media Sync:
51578
51743
  });
51579
51744
  } else {
51580
51745
  output.info("Pulling all entries");
51581
- let result = await client.pull.all();
51582
- if (result.meta.truncated) {
51583
- output.warn("Content was truncated due to size limits.");
51584
- output.info("Fetching complete data via pagination...");
51585
- const contentTypes = Object.keys(result.entries);
51586
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51587
- }
51746
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51588
51747
  const mediaContent = createScopedPullContent(result.meta, { entries: result.entries });
51589
51748
  await applyMediaIdentifiers(mediaContent);
51590
51749
  await syncMediaIfRequested(mediaContent);
@@ -51731,13 +51890,7 @@ Media Sync:
51731
51890
  case "all":
51732
51891
  default: {
51733
51892
  output.info("Pulling all content");
51734
- let result = await client.pull.all();
51735
- if (result.meta.truncated) {
51736
- output.warn("Content was truncated due to size limits.");
51737
- output.info("Fetching complete data via pagination...");
51738
- const contentTypes = Object.keys(result.entries);
51739
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51740
- }
51893
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51741
51894
  result.settingsWarnings?.forEach((warning) => output.warn(warning));
51742
51895
  await applyMediaIdentifiers(result);
51743
51896
  await syncMediaIfRequested(result);
@@ -52119,8 +52272,8 @@ function normalizeLocalContentShape(content) {
52119
52272
  var identifierRegex = /^[a-z0-9][a-z0-9-]*$/;
52120
52273
  var currencyRegex = /^[A-Z]{3}$/;
52121
52274
  var isoDateTimeRegex = /^\d{4}-\d{2}-\d{2}T.+/;
52122
- function issue2(path25, message) {
52123
- return { path: path25, message };
52275
+ function issue2(path27, message) {
52276
+ return { path: path27, message };
52124
52277
  }
52125
52278
  function isRecord15(value) {
52126
52279
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -52137,27 +52290,27 @@ function isWholeMinuteIsoDateTime(value) {
52137
52290
  return Number.isFinite(epochMs) && epochMs % 6e4 === 0;
52138
52291
  }
52139
52292
  function validateTicketType(raw, index, currency) {
52140
- const path25 = ["ticketTypes", String(index)];
52141
- if (!isRecord15(raw)) return [issue2(path25, "Ticket type must be an object")];
52293
+ const path27 = ["ticketTypes", String(index)];
52294
+ if (!isRecord15(raw)) return [issue2(path27, "Ticket type must be an object")];
52142
52295
  const issues = [];
52143
52296
  const identifier = raw.identifier;
52144
52297
  if (typeof identifier !== "string" || !identifierRegex.test(identifier)) {
52145
52298
  issues.push(
52146
52299
  issue2(
52147
- [...path25, "identifier"],
52300
+ [...path27, "identifier"],
52148
52301
  "Ticket identifier must use lowercase letters, numbers, and hyphens"
52149
52302
  )
52150
52303
  );
52151
52304
  }
52152
52305
  const name = raw.name;
52153
52306
  if (typeof name !== "string" || name.trim().length === 0) {
52154
- issues.push(issue2([...path25, "name"], "Ticket name is required"));
52307
+ issues.push(issue2([...path27, "name"], "Ticket name is required"));
52155
52308
  }
52156
52309
  const priceAmount = raw.priceAmount;
52157
52310
  if (!isWholeNumber(priceAmount) || priceAmount < 0) {
52158
52311
  issues.push(
52159
52312
  issue2(
52160
- [...path25, "priceAmount"],
52313
+ [...path27, "priceAmount"],
52161
52314
  "Ticket priceAmount must be a non-negative integer"
52162
52315
  )
52163
52316
  );
@@ -52166,7 +52319,7 @@ function validateTicketType(raw, index, currency) {
52166
52319
  if (priceCurrency !== void 0 && priceCurrency !== null && priceCurrency !== currency) {
52167
52320
  issues.push(
52168
52321
  issue2(
52169
- [...path25, "priceCurrency"],
52322
+ [...path27, "priceCurrency"],
52170
52323
  "Ticket priceCurrency must match pricing.priceCurrency"
52171
52324
  )
52172
52325
  );
@@ -52175,7 +52328,7 @@ function validateTicketType(raw, index, currency) {
52175
52328
  if (sortOrder !== void 0 && (!isWholeNumber(sortOrder) || sortOrder < 0)) {
52176
52329
  issues.push(
52177
52330
  issue2(
52178
- [...path25, "sortOrder"],
52331
+ [...path27, "sortOrder"],
52179
52332
  "Ticket sortOrder must be a non-negative integer"
52180
52333
  )
52181
52334
  );
@@ -52184,7 +52337,7 @@ function validateTicketType(raw, index, currency) {
52184
52337
  if (capacityLimit2 !== void 0 && capacityLimit2 !== null && (!isWholeNumber(capacityLimit2) || capacityLimit2 < 1)) {
52185
52338
  issues.push(
52186
52339
  issue2(
52187
- [...path25, "capacityLimit"],
52340
+ [...path27, "capacityLimit"],
52188
52341
  "Ticket capacityLimit must be a positive integer"
52189
52342
  )
52190
52343
  );
@@ -52193,7 +52346,7 @@ function validateTicketType(raw, index, currency) {
52193
52346
  if (attendanceScope !== void 0 && attendanceScope !== "in_person" && attendanceScope !== "online" && attendanceScope !== "both") {
52194
52347
  issues.push(
52195
52348
  issue2(
52196
- [...path25, "attendanceScope"],
52349
+ [...path27, "attendanceScope"],
52197
52350
  "Ticket attendanceScope must be in_person, online, or both"
52198
52351
  )
52199
52352
  );
@@ -52202,7 +52355,7 @@ function validateTicketType(raw, index, currency) {
52202
52355
  if (saleStartsAt !== void 0 && saleStartsAt !== null && (typeof saleStartsAt !== "string" || !isWholeMinuteIsoDateTime(saleStartsAt))) {
52203
52356
  issues.push(
52204
52357
  issue2(
52205
- [...path25, "saleStartsAt"],
52358
+ [...path27, "saleStartsAt"],
52206
52359
  "Ticket saleStartsAt must be an ISO datetime aligned to a whole minute"
52207
52360
  )
52208
52361
  );
@@ -52211,7 +52364,7 @@ function validateTicketType(raw, index, currency) {
52211
52364
  if (saleEndsAt !== void 0 && saleEndsAt !== null && (typeof saleEndsAt !== "string" || !isWholeMinuteIsoDateTime(saleEndsAt))) {
52212
52365
  issues.push(
52213
52366
  issue2(
52214
- [...path25, "saleEndsAt"],
52367
+ [...path27, "saleEndsAt"],
52215
52368
  "Ticket saleEndsAt must be an ISO datetime aligned to a whole minute"
52216
52369
  )
52217
52370
  );
@@ -52219,7 +52372,7 @@ function validateTicketType(raw, index, currency) {
52219
52372
  if (typeof saleStartsAt === "string" && typeof saleEndsAt === "string" && Date.parse(saleEndsAt) <= Date.parse(saleStartsAt)) {
52220
52373
  issues.push(
52221
52374
  issue2(
52222
- [...path25, "saleEndsAt"],
52375
+ [...path27, "saleEndsAt"],
52223
52376
  "Ticket saleEndsAt must be after saleStartsAt"
52224
52377
  )
52225
52378
  );
@@ -52228,7 +52381,7 @@ function validateTicketType(raw, index, currency) {
52228
52381
  if (cmsTicketTypeId !== void 0 && cmsTicketTypeId !== null && (typeof cmsTicketTypeId !== "string" || cmsTicketTypeId.length === 0)) {
52229
52382
  issues.push(
52230
52383
  issue2(
52231
- [...path25, "cmsTicketTypeId"],
52384
+ [...path27, "cmsTicketTypeId"],
52232
52385
  "Ticket cmsTicketTypeId must be a non-empty string"
52233
52386
  )
52234
52387
  );
@@ -52406,11 +52559,239 @@ function classifySdkEventPricing(rawInput) {
52406
52559
  }
52407
52560
  }
52408
52561
 
52562
+ // ../api/src/sdk-event-payment-terms.ts
52563
+ var supportedKinds = /* @__PURE__ */ new Set([
52564
+ "upfront",
52565
+ "deferred_manual",
52566
+ "flexible_balance"
52567
+ ]);
52568
+ function issue3(path27, message) {
52569
+ return { path: path27, message };
52570
+ }
52571
+ function isRecord16(value) {
52572
+ return typeof value === "object" && value !== null && !Array.isArray(value);
52573
+ }
52574
+ function isWholeNumber2(value) {
52575
+ return typeof value === "number" && Number.isInteger(value);
52576
+ }
52577
+ function isPositiveWholeNumber(value) {
52578
+ return isWholeNumber2(value) && value > 0;
52579
+ }
52580
+ function isDepositRefundability(value) {
52581
+ return value === "refundable" || value === "non_refundable";
52582
+ }
52583
+ function isSupportedOptionKind(value) {
52584
+ return typeof value === "string" && supportedKinds.has(value);
52585
+ }
52586
+ function validateFlexibleBalanceDueDateRule(raw, path27) {
52587
+ if (!isRecord16(raw)) {
52588
+ return [issue3(path27, "Flexible balance dueDateRule must be an object")];
52589
+ }
52590
+ if (raw.kind === "relative_to_start_date") {
52591
+ if (!isPositiveWholeNumber(raw.daysBeforeStart)) {
52592
+ return [
52593
+ issue3(
52594
+ [...path27, "daysBeforeStart"],
52595
+ "Flexible balance daysBeforeStart must be a positive integer"
52596
+ )
52597
+ ];
52598
+ }
52599
+ return {
52600
+ kind: "relative_to_start_date",
52601
+ daysBeforeStart: raw.daysBeforeStart
52602
+ };
52603
+ }
52604
+ if (raw.kind === "fixed_calendar_date") {
52605
+ if (typeof raw.dueAt !== "string" || !Number.isFinite(Date.parse(raw.dueAt))) {
52606
+ return [
52607
+ issue3(
52608
+ [...path27, "dueAt"],
52609
+ "Flexible balance fixed dueAt must be an ISO datetime"
52610
+ )
52611
+ ];
52612
+ }
52613
+ return {
52614
+ kind: "fixed_calendar_date",
52615
+ dueAt: raw.dueAt
52616
+ };
52617
+ }
52618
+ return [
52619
+ issue3(
52620
+ [...path27, "kind"],
52621
+ "Flexible balance dueDateRule kind must be relative_to_start_date or fixed_calendar_date"
52622
+ )
52623
+ ];
52624
+ }
52625
+ function validateFlexibleBalanceConfig(raw, path27) {
52626
+ if (!isRecord16(raw)) {
52627
+ return [issue3(path27, "Flexible balance config must be an object")];
52628
+ }
52629
+ const issues = [];
52630
+ const upfrontAmountCents = raw.upfrontAmountCents;
52631
+ const depositRefundability = raw.depositRefundability;
52632
+ let validatedUpfrontAmountCents = null;
52633
+ let validatedDepositRefundability = null;
52634
+ if (!isWholeNumber2(upfrontAmountCents) || upfrontAmountCents < 0) {
52635
+ issues.push(
52636
+ issue3(
52637
+ [...path27, "upfrontAmountCents"],
52638
+ "Flexible balance upfrontAmountCents must be a non-negative integer"
52639
+ )
52640
+ );
52641
+ } else {
52642
+ validatedUpfrontAmountCents = upfrontAmountCents;
52643
+ }
52644
+ if (!isDepositRefundability(depositRefundability)) {
52645
+ issues.push(
52646
+ issue3(
52647
+ [...path27, "depositRefundability"],
52648
+ "Flexible balance depositRefundability must be refundable or non_refundable"
52649
+ )
52650
+ );
52651
+ } else {
52652
+ validatedDepositRefundability = depositRefundability;
52653
+ }
52654
+ const dueDateRule = validateFlexibleBalanceDueDateRule(
52655
+ raw.dueDateRule,
52656
+ [...path27, "dueDateRule"]
52657
+ );
52658
+ if (Array.isArray(dueDateRule)) {
52659
+ issues.push(...dueDateRule);
52660
+ }
52661
+ if (issues.length > 0 || Array.isArray(dueDateRule) || validatedUpfrontAmountCents === null || validatedDepositRefundability === null) {
52662
+ return issues;
52663
+ }
52664
+ return {
52665
+ upfrontAmountCents: validatedUpfrontAmountCents,
52666
+ depositRefundability: validatedDepositRefundability,
52667
+ dueDateRule
52668
+ };
52669
+ }
52670
+ function validateCollectionOption(raw, index) {
52671
+ const path27 = ["allowedOptions", String(index)];
52672
+ if (!isRecord16(raw)) {
52673
+ return [issue3(path27, "Payment option must be an object")];
52674
+ }
52675
+ if (raw.kind === "instalment_plan") {
52676
+ return [
52677
+ issue3(
52678
+ [...path27, "kind"],
52679
+ "Event instalment plans are not supported yet. Use upfront, deferred_manual, or flexible_balance."
52680
+ )
52681
+ ];
52682
+ }
52683
+ if (!isSupportedOptionKind(raw.kind)) {
52684
+ return [
52685
+ issue3(
52686
+ [...path27, "kind"],
52687
+ "Payment option kind must be upfront, deferred_manual, or flexible_balance"
52688
+ )
52689
+ ];
52690
+ }
52691
+ switch (raw.kind) {
52692
+ case "upfront":
52693
+ case "deferred_manual":
52694
+ return { kind: raw.kind };
52695
+ case "flexible_balance": {
52696
+ const config2 = validateFlexibleBalanceConfig(raw.config, [
52697
+ ...path27,
52698
+ "config"
52699
+ ]);
52700
+ if (Array.isArray(config2)) {
52701
+ return config2;
52702
+ }
52703
+ return { kind: "flexible_balance", config: config2 };
52704
+ }
52705
+ }
52706
+ }
52707
+ function optionCombinationIssues(options) {
52708
+ const issues = [];
52709
+ const seenKinds = /* @__PURE__ */ new Set();
52710
+ options.forEach((option, index) => {
52711
+ if (seenKinds.has(option.kind)) {
52712
+ issues.push(
52713
+ issue3(
52714
+ ["allowedOptions", String(index), "kind"],
52715
+ `Duplicate payment option kind "${option.kind}"`
52716
+ )
52717
+ );
52718
+ }
52719
+ seenKinds.add(option.kind);
52720
+ });
52721
+ if (options.length > 2) {
52722
+ issues.push(
52723
+ issue3(
52724
+ ["allowedOptions"],
52725
+ "Event payment terms can offer one option, or a choice between upfront and one alternative option"
52726
+ )
52727
+ );
52728
+ }
52729
+ if (options.length === 2 && (!seenKinds.has("upfront") || !seenKinds.has("deferred_manual") && !seenKinds.has("flexible_balance"))) {
52730
+ issues.push(
52731
+ issue3(
52732
+ ["allowedOptions"],
52733
+ "Event payment terms with two options must combine upfront with deferred_manual or flexible_balance"
52734
+ )
52735
+ );
52736
+ }
52737
+ return issues;
52738
+ }
52739
+ function classifySdkEventPaymentTerms(rawInput) {
52740
+ if (rawInput === void 0 || rawInput === null) {
52741
+ return { ok: true, paymentTerms: void 0 };
52742
+ }
52743
+ if (!isRecord16(rawInput)) {
52744
+ return {
52745
+ ok: false,
52746
+ issues: [issue3([], "Event paymentTerms must be an object")]
52747
+ };
52748
+ }
52749
+ if (!Array.isArray(rawInput.allowedOptions)) {
52750
+ return {
52751
+ ok: false,
52752
+ issues: [
52753
+ issue3(["allowedOptions"], "Event paymentTerms.allowedOptions is required")
52754
+ ]
52755
+ };
52756
+ }
52757
+ if (rawInput.allowedOptions.length === 0) {
52758
+ return {
52759
+ ok: false,
52760
+ issues: [
52761
+ issue3(
52762
+ ["allowedOptions"],
52763
+ "Event paymentTerms.allowedOptions must include at least one option"
52764
+ )
52765
+ ]
52766
+ };
52767
+ }
52768
+ const options = [];
52769
+ const issues = [];
52770
+ rawInput.allowedOptions.forEach((option, index) => {
52771
+ const validated = validateCollectionOption(option, index);
52772
+ if (Array.isArray(validated)) {
52773
+ issues.push(...validated);
52774
+ return;
52775
+ }
52776
+ options.push(validated);
52777
+ });
52778
+ issues.push(...optionCombinationIssues(options));
52779
+ if (issues.length > 0) {
52780
+ return { ok: false, issues };
52781
+ }
52782
+ return {
52783
+ ok: true,
52784
+ paymentTerms: {
52785
+ allowedOptions: options
52786
+ }
52787
+ };
52788
+ }
52789
+
52409
52790
  // src/cli/commands/push/pushAllExtras.ts
52410
52791
  function nullishToNull(value) {
52411
52792
  return value == null ? null : value;
52412
52793
  }
52413
- function isRecord16(value) {
52794
+ function isRecord17(value) {
52414
52795
  return typeof value === "object" && value !== null && !Array.isArray(value);
52415
52796
  }
52416
52797
  function stringValue(value, fallback) {
@@ -52425,8 +52806,13 @@ function normalizeEventPricingForCompare(pricing) {
52425
52806
  if (result.ok) return result.pricing;
52426
52807
  return { kind: "free" };
52427
52808
  }
52809
+ function normalizeEventPaymentTermsForCompare(paymentTerms) {
52810
+ const result = classifySdkEventPaymentTerms(paymentTerms);
52811
+ if (result.ok) return result.paymentTerms;
52812
+ return void 0;
52813
+ }
52428
52814
  function normalizeVenueAddress(value) {
52429
- const obj = isRecord16(value) ? value : {};
52815
+ const obj = isRecord17(value) ? value : {};
52430
52816
  return {
52431
52817
  line1: nullishToNull(typeof obj.line1 === "string" ? obj.line1 : void 0),
52432
52818
  line2: nullishToNull(typeof obj.line2 === "string" ? obj.line2 : void 0),
@@ -52443,7 +52829,7 @@ function normalizeVenueAddress(value) {
52443
52829
  };
52444
52830
  }
52445
52831
  function normalizeVenueLocation(value) {
52446
- if (!isRecord16(value)) return null;
52832
+ if (!isRecord17(value)) return null;
52447
52833
  const obj = value;
52448
52834
  const lat = typeof obj.lat === "number" ? obj.lat : null;
52449
52835
  const lng = typeof obj.lng === "number" ? obj.lng : null;
@@ -52451,7 +52837,7 @@ function normalizeVenueLocation(value) {
52451
52837
  return { lat, lng };
52452
52838
  }
52453
52839
  function normalizeVenueForCompare(venue) {
52454
- const obj = isRecord16(venue) ? venue : {};
52840
+ const obj = isRecord17(venue) ? venue : {};
52455
52841
  return {
52456
52842
  slug: String(obj.slug),
52457
52843
  title: String(obj.title),
@@ -52472,7 +52858,7 @@ function normalizeVenueForCompare(venue) {
52472
52858
  };
52473
52859
  }
52474
52860
  function normalizeEventCategoryForCompare(category) {
52475
- const obj = isRecord16(category) ? category : {};
52861
+ const obj = isRecord17(category) ? category : {};
52476
52862
  return {
52477
52863
  identifier: String(obj.identifier),
52478
52864
  name: String(obj.name),
@@ -52484,8 +52870,8 @@ function normalizeEventCategoryForCompare(category) {
52484
52870
  };
52485
52871
  }
52486
52872
  function normalizeRemoteEventForCompare(event) {
52487
- const obj = isRecord16(event) ? event : {};
52488
- const schedule = isRecord16(obj.schedule) ? obj.schedule : {};
52873
+ const obj = isRecord17(event) ? event : {};
52874
+ const schedule = isRecord17(obj.schedule) ? obj.schedule : {};
52489
52875
  return {
52490
52876
  identifier: String(obj.identifier),
52491
52877
  title: String(obj.title),
@@ -52504,6 +52890,7 @@ function normalizeRemoteEventForCompare(event) {
52504
52890
  typeof obj.capacity === "number" ? obj.capacity : void 0
52505
52891
  ),
52506
52892
  pricing: normalizeEventPricingForCompare(obj.pricing),
52893
+ paymentTerms: normalizeEventPaymentTermsForCompare(obj.paymentTerms),
52507
52894
  venueRef: nullishToNull(
52508
52895
  typeof obj.venueRef === "string" ? obj.venueRef : void 0
52509
52896
  ),
@@ -52513,14 +52900,14 @@ function normalizeRemoteEventForCompare(event) {
52513
52900
  formRef: nullishToNull(
52514
52901
  typeof obj.formRef === "string" ? obj.formRef : void 0
52515
52902
  ),
52516
- content: isRecord16(obj.content) ? obj.content : {},
52517
- settings: isRecord16(obj.settings) ? obj.settings : {},
52518
- presentation: isRecord16(obj.presentation) ? obj.presentation : null,
52903
+ content: isRecord17(obj.content) ? obj.content : {},
52904
+ settings: isRecord17(obj.settings) ? obj.settings : {},
52905
+ presentation: isRecord17(obj.presentation) ? obj.presentation : null,
52519
52906
  tags: Array.isArray(obj.tags) ? obj.tags : []
52520
52907
  };
52521
52908
  }
52522
52909
  function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52523
- const local = isRecord16(localEvent) ? localEvent : {};
52910
+ const local = isRecord17(localEvent) ? localEvent : {};
52524
52911
  const base = remoteEvent ? normalizeRemoteEventForCompare(remoteEvent) : normalizeRemoteEventForCompare({
52525
52912
  identifier: local.identifier,
52526
52913
  title: local.title,
@@ -52529,6 +52916,7 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52529
52916
  visibility: local.visibility ?? "private",
52530
52917
  schedule: local.schedule ?? {},
52531
52918
  pricing: local.pricing ?? {},
52919
+ paymentTerms: local.paymentTerms,
52532
52920
  capacity: local.capacity ?? null,
52533
52921
  venueRef: local.venueRef ?? null,
52534
52922
  categoryRef: local.categoryRef ?? null,
@@ -52538,7 +52926,7 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52538
52926
  presentation: local.presentation ?? null,
52539
52927
  tags: local.tags ?? []
52540
52928
  });
52541
- const schedule = isRecord16(local.schedule) ? local.schedule : {};
52929
+ const schedule = isRecord17(local.schedule) ? local.schedule : {};
52542
52930
  return {
52543
52931
  ...base,
52544
52932
  identifier: stringValue(local.identifier, base.identifier),
@@ -52559,6 +52947,7 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52559
52947
  typeof local.capacity === "number" ? local.capacity : void 0
52560
52948
  ),
52561
52949
  pricing: local.pricing === void 0 ? base.pricing : normalizeEventPricingForCompare(local.pricing),
52950
+ paymentTerms: local.paymentTerms === void 0 ? base.paymentTerms : normalizeEventPaymentTermsForCompare(local.paymentTerms),
52562
52951
  venueRef: local.venueRef === void 0 ? base.venueRef : nullishToNull(
52563
52952
  typeof local.venueRef === "string" ? local.venueRef : void 0
52564
52953
  ),
@@ -52568,9 +52957,9 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52568
52957
  formRef: local.formRef === void 0 ? base.formRef : nullishToNull(
52569
52958
  typeof local.formRef === "string" ? local.formRef : void 0
52570
52959
  ),
52571
- content: local.content === void 0 ? base.content : isRecord16(local.content) ? local.content : {},
52572
- settings: local.settings === void 0 ? base.settings : isRecord16(local.settings) ? local.settings : {},
52573
- presentation: local.presentation === void 0 ? base.presentation : isRecord16(local.presentation) ? local.presentation : null,
52960
+ content: local.content === void 0 ? base.content : isRecord17(local.content) ? local.content : {},
52961
+ settings: local.settings === void 0 ? base.settings : isRecord17(local.settings) ? local.settings : {},
52962
+ presentation: local.presentation === void 0 ? base.presentation : isRecord17(local.presentation) ? local.presentation : null,
52574
52963
  tags: local.tags === void 0 ? base.tags : Array.isArray(local.tags) ? local.tags : []
52575
52964
  };
52576
52965
  }
@@ -52582,7 +52971,7 @@ function toIsoStringOrOriginal(value) {
52582
52971
  function normalizeCourseSessions(value) {
52583
52972
  if (!Array.isArray(value)) return [];
52584
52973
  return value.map((session) => {
52585
- const obj = isRecord16(session) ? session : {};
52974
+ const obj = isRecord17(session) ? session : {};
52586
52975
  return {
52587
52976
  startsAt: toIsoStringOrOriginal(obj.startsAt),
52588
52977
  endsAt: toIsoStringOrOriginal(obj.endsAt)
@@ -52594,18 +52983,18 @@ function normalizeCourseSessions(value) {
52594
52983
  }
52595
52984
  function normalizeCourseProgram(value) {
52596
52985
  if (value == null) return null;
52597
- if (!isRecord16(value)) {
52986
+ if (!isRecord17(value)) {
52598
52987
  return { identifier: null, data: {} };
52599
52988
  }
52600
52989
  return {
52601
52990
  identifier: nullishToNull(
52602
52991
  typeof value.identifier === "string" ? value.identifier : void 0
52603
52992
  ),
52604
- data: isRecord16(value.data) ? value.data : {}
52993
+ data: isRecord17(value.data) ? value.data : {}
52605
52994
  };
52606
52995
  }
52607
52996
  function normalizeRemoteCourseForCompare(course) {
52608
- const obj = isRecord16(course) ? course : {};
52997
+ const obj = isRecord17(course) ? course : {};
52609
52998
  return {
52610
52999
  identifier: String(obj.identifier),
52611
53000
  title: String(obj.title),
@@ -52640,7 +53029,7 @@ function normalizeRemoteCourseForCompare(course) {
52640
53029
  };
52641
53030
  }
52642
53031
  function normalizeLocalCourseAgainstRemoteForCompare(localCourse, remoteCourse) {
52643
- const local = isRecord16(localCourse) ? localCourse : {};
53032
+ const local = isRecord17(localCourse) ? localCourse : {};
52644
53033
  const base = remoteCourse ? normalizeRemoteCourseForCompare(remoteCourse) : normalizeRemoteCourseForCompare({
52645
53034
  identifier: local.identifier,
52646
53035
  title: local.title,
@@ -52661,11 +53050,11 @@ function normalizeLocalCourseAgainstRemoteForCompare(localCourse, remoteCourse)
52661
53050
  });
52662
53051
  const status = local.status === void 0 ? base.status : local.status === "active" || local.status === "cancelled" || local.status === "completed" ? local.status : "draft";
52663
53052
  const visibility = local.visibility === void 0 ? base.visibility : local.visibility === "public" || local.visibility === "private" || local.visibility === "unlisted" ? local.visibility : "public";
52664
- const program2 = local.program === void 0 ? base.program : local.program === null ? null : isRecord16(local.program) ? {
53053
+ const program2 = local.program === void 0 ? base.program : local.program === null ? null : isRecord17(local.program) ? {
52665
53054
  identifier: local.program.identifier === void 0 ? base.program?.identifier ?? null : nullishToNull(
52666
53055
  typeof local.program.identifier === "string" ? local.program.identifier : void 0
52667
53056
  ),
52668
- data: isRecord16(local.program.data) ? local.program.data : base.program?.data ?? {}
53057
+ data: isRecord17(local.program.data) ? local.program.data : base.program?.data ?? {}
52669
53058
  } : base.program;
52670
53059
  return {
52671
53060
  ...base,
@@ -53334,9 +53723,24 @@ var fixedPriceIntentSchema = z.object({
53334
53723
  kind: z.literal("fixed_price"),
53335
53724
  price: moneyAmountSchema
53336
53725
  }).strict();
53726
+ var inlineEventTicketTypeSchema = z.object({
53727
+ identifier: recipeIdentifierSchema,
53728
+ cmsTicketTypeId: z.string().min(1).nullable().optional(),
53729
+ name: z.string().min(1),
53730
+ description: z.string().nullable().optional(),
53731
+ priceAmount: nonNegativeIntegerSchema,
53732
+ priceCurrency: currencySchema.optional(),
53733
+ isActive: z.boolean().optional(),
53734
+ sortOrder: nonNegativeIntegerSchema.optional(),
53735
+ capacityLimit: positiveIntegerSchema.nullable().optional(),
53736
+ attendanceScope: z.enum(["in_person", "online", "both"]).optional(),
53737
+ saleStartsAt: isoDateTimeSchema.nullable().optional(),
53738
+ saleEndsAt: isoDateTimeSchema.nullable().optional()
53739
+ }).strict();
53337
53740
  var ticketTypesPricingIntentSchema = z.object({
53338
53741
  kind: z.literal("ticket_types"),
53339
- currency: currencySchema.optional()
53742
+ currency: currencySchema.optional(),
53743
+ ticketTypes: z.array(inlineEventTicketTypeSchema).readonly().optional()
53340
53744
  }).strict();
53341
53745
  var manualPaymentPricingIntentSchema = z.object({
53342
53746
  kind: z.literal("manual_payment"),
@@ -53781,6 +54185,7 @@ var upsertEventSeriesCommandSchema = z.object({
53781
54185
  occurrences: z.array(eventOccurrenceSchema).min(1).readonly(),
53782
54186
  content: contentSummarySchema.optional(),
53783
54187
  settings: unknownRecordSchema.optional(),
54188
+ paymentTerms: z.unknown().optional(),
53784
54189
  presentation: unknownRecordSchema.nullable().optional(),
53785
54190
  tags: z.array(z.string()).readonly().optional(),
53786
54191
  staffRefs: z.array(staffRefSchema).readonly().optional()
@@ -54900,7 +55305,7 @@ function getSiteCommandLifecycleIntent(command) {
54900
55305
  init_src();
54901
55306
 
54902
55307
  // ../site-commands/src/guards.ts
54903
- function isRecord17(value) {
55308
+ function isRecord18(value) {
54904
55309
  return typeof value === "object" && value !== null;
54905
55310
  }
54906
55311
 
@@ -55160,13 +55565,13 @@ function collectOfferingRequires(input, intervals, intervalPath) {
55160
55565
  function optionalRef(ref, field) {
55161
55566
  return ref ? [{ ref, field }] : [];
55162
55567
  }
55163
- function collectVenueRefsFromIntervals(intervals, path25) {
55164
- return intervals.flatMap((interval, index) => optionalRef(interval.venueRef, `${path25}[${index}].venueRef`));
55568
+ function collectVenueRefsFromIntervals(intervals, path27) {
55569
+ return intervals.flatMap((interval, index) => optionalRef(interval.venueRef, `${path27}[${index}].venueRef`));
55165
55570
  }
55166
- function collectNavigationRefs(items, path25) {
55571
+ function collectNavigationRefs(items, path27) {
55167
55572
  return items.flatMap((item, index) => {
55168
- if (!isRecord17(item)) return [];
55169
- const itemPath = `${path25}[${index}]`;
55573
+ if (!isRecord18(item)) return [];
55574
+ const itemPath = `${path27}[${index}]`;
55170
55575
  const refs = [];
55171
55576
  if (typeof item.pageRef === "string") {
55172
55577
  refs.push({ ref: item.pageRef, field: `${itemPath}.pageRef` });
@@ -55180,26 +55585,26 @@ function collectNavigationRefs(items, path25) {
55180
55585
  return refs;
55181
55586
  });
55182
55587
  }
55183
- function collectBlockRefs(blocks, path25) {
55588
+ function collectBlockRefs(blocks, path27) {
55184
55589
  return blocks.flatMap((block, index) => {
55185
- if (!isRecord17(block)) return [];
55186
- const blockPath = `${path25}[${index}]`;
55590
+ if (!isRecord18(block)) return [];
55591
+ const blockPath = `${path27}[${index}]`;
55187
55592
  return [
55188
55593
  ...collectNestedRefs(block.props, `${blockPath}.props`),
55189
55594
  ...collectNestedRefs(block.children, `${blockPath}.children`)
55190
55595
  ];
55191
55596
  });
55192
55597
  }
55193
- function collectNestedRefs(value, path25) {
55598
+ function collectNestedRefs(value, path27) {
55194
55599
  if (typeof value === "string") {
55195
55600
  const parsed = parseResourceRef(value);
55196
- return parsed.ok ? [{ ref: value, field: path25 }] : [];
55601
+ return parsed.ok ? [{ ref: value, field: path27 }] : [];
55197
55602
  }
55198
55603
  if (Array.isArray(value)) {
55199
- return value.flatMap((item, index) => collectNestedRefs(item, `${path25}[${index}]`));
55604
+ return value.flatMap((item, index) => collectNestedRefs(item, `${path27}[${index}]`));
55200
55605
  }
55201
- if (!isRecord17(value)) return [];
55202
- return Object.entries(value).flatMap(([key, child]) => collectNestedRefs(child, `${path25}.${key}`));
55606
+ if (!isRecord18(value)) return [];
55607
+ return Object.entries(value).flatMap(([key, child]) => collectNestedRefs(child, `${path27}.${key}`));
55203
55608
  }
55204
55609
 
55205
55610
  // ../site-commands/src/staticExecutionGaps.ts
@@ -55282,7 +55687,7 @@ function parseCommandBatch(input) {
55282
55687
  if (unknownTypeErrors.length > 0) return err(unknownTypeErrors);
55283
55688
  const parsed = siteCommandBatchSchema.safeParse(input);
55284
55689
  if (!parsed.success) {
55285
- return err(parsed.error.issues.map((issue4) => invalidPayloadError(input, issue4)));
55690
+ return err(parsed.error.issues.map((issue5) => invalidPayloadError(input, issue5)));
55286
55691
  }
55287
55692
  return ok(parsed.data);
55288
55693
  }
@@ -55454,9 +55859,9 @@ function deriveIdempotencyKey(input) {
55454
55859
  ].join("|"));
55455
55860
  }
55456
55861
  function findUnknownCommandTypes(input) {
55457
- if (!isRecord17(input) || !Array.isArray(input.commands)) return [];
55862
+ if (!isRecord18(input) || !Array.isArray(input.commands)) return [];
55458
55863
  return input.commands.flatMap((command, commandIndex) => {
55459
- if (!isRecord17(command) || typeof command.type !== "string") return [];
55864
+ if (!isRecord18(command) || typeof command.type !== "string") return [];
55460
55865
  if (commandTypeSet.has(command.type)) return [];
55461
55866
  return [{
55462
55867
  code: "unknown_command_type",
@@ -55466,32 +55871,32 @@ function findUnknownCommandTypes(input) {
55466
55871
  }];
55467
55872
  });
55468
55873
  }
55469
- function invalidPayloadError(input, issue4) {
55470
- const commandIndex = commandIndexForIssuePath(issue4.path);
55874
+ function invalidPayloadError(input, issue5) {
55875
+ const commandIndex = commandIndexForIssuePath(issue5.path);
55471
55876
  const commandType = commandTypeForIssue(input, commandIndex);
55472
- const field = formatIssuePath(issue4.path);
55877
+ const field = formatIssuePath(issue5.path);
55473
55878
  return {
55474
55879
  code: "invalid_command_payload",
55475
55880
  commandIndex,
55476
55881
  commandType,
55477
55882
  field,
55478
- message: `${field}: ${issue4.message}`
55883
+ message: `${field}: ${issue5.message}`
55479
55884
  };
55480
55885
  }
55481
- function commandIndexForIssuePath(path25) {
55482
- return path25[0] === "commands" && typeof path25[1] === "number" ? path25[1] : -1;
55886
+ function commandIndexForIssuePath(path27) {
55887
+ return path27[0] === "commands" && typeof path27[1] === "number" ? path27[1] : -1;
55483
55888
  }
55484
55889
  function commandTypeForIssue(input, commandIndex) {
55485
- if (!isRecord17(input) || !isUnknownArray3(input.commands)) return null;
55890
+ if (!isRecord18(input) || !isUnknownArray3(input.commands)) return null;
55486
55891
  const command = input.commands[commandIndex];
55487
- return isRecord17(command) && typeof command.type === "string" ? command.type : null;
55892
+ return isRecord18(command) && typeof command.type === "string" ? command.type : null;
55488
55893
  }
55489
55894
  function isUnknownArray3(value) {
55490
55895
  return Array.isArray(value);
55491
55896
  }
55492
- function formatIssuePath(path25) {
55493
- if (path25.length === 0) return "<root>";
55494
- return path25.reduce((formatted, segment) => {
55897
+ function formatIssuePath(path27) {
55898
+ if (path27.length === 0) return "<root>";
55899
+ return path27.reduce((formatted, segment) => {
55495
55900
  if (typeof segment === "number") return `${formatted}[${segment}]`;
55496
55901
  if (formatted.length === 0) return String(segment);
55497
55902
  return `${formatted}.${String(segment)}`;
@@ -55729,11 +56134,12 @@ function indexOfferingCommands(batch) {
55729
56134
  function checkTicketPricedEventsHaveTickets(indexes) {
55730
56135
  return indexes.events.flatMap((event) => {
55731
56136
  const tickets = indexes.ticketsByEventRef.get(event.ref) ?? [];
55732
- if (event.input.pricing.kind !== "ticket_types" || tickets.length > 0) return [];
56137
+ const inlineTickets = event.input.pricing.kind === "ticket_types" ? event.input.pricing.ticketTypes ?? [] : [];
56138
+ if (event.input.pricing.kind !== "ticket_types" || tickets.length + inlineTickets.length > 0) return [];
55733
56139
  return [commandInvariantViolation(
55734
56140
  event.ref,
55735
56141
  "input.pricing",
55736
- "Events using ticket_types pricing require at least one upsertEventTicketType command."
56142
+ "Events using ticket_types pricing require at least one inline ticket type or upsertEventTicketType command."
55737
56143
  )];
55738
56144
  });
55739
56145
  }
@@ -55741,7 +56147,10 @@ function checkTicketQuantitiesWithinCapacity(indexes) {
55741
56147
  return indexes.events.flatMap((event) => {
55742
56148
  const capacity2 = limitedCapacityQuantity(event.input.capacity);
55743
56149
  if (capacity2 === void 0) return [];
55744
- const ticketQuantityTotal = (indexes.ticketsByEventRef.get(event.ref) ?? []).reduce((total, ticket) => total + (ticket.input.quantity ?? 0), 0);
56150
+ 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(
56151
+ (total, ticket) => total + (ticket.capacityLimit ?? 0),
56152
+ 0
56153
+ ) : 0);
55745
56154
  if (ticketQuantityTotal <= capacity2) return [];
55746
56155
  return [commandInvariantViolation(
55747
56156
  event.ref,
@@ -56156,8 +56565,8 @@ init_src();
56156
56565
  var timeRegex = /^([01]\d|2[0-3]):([0-5]\d)(:([0-5]\d))?$/;
56157
56566
  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)$/;
56158
56567
  var localDateTimeRegex = /^(\d{4})-(\d{2})-(\d{2})T([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?(\.\d{1,3})?$/;
56159
- function issue3(path25, message) {
56160
- return { path: path25, message };
56568
+ function issue4(path27, message) {
56569
+ return { path: path27, message };
56161
56570
  }
56162
56571
  function isValidDateParts(year, month, day) {
56163
56572
  const date = new Date(Date.UTC(year, month - 1, day));
@@ -56221,22 +56630,22 @@ function maxDurationMessage(options) {
56221
56630
  function classifyCanonicalSchedule(input, options) {
56222
56631
  const issues = [];
56223
56632
  if (options.requireCanonicalFields && input.recurrenceRule === void 0) {
56224
- issues.push(issue3(["recurrenceRule"], "recurrenceRule is required"));
56633
+ issues.push(issue4(["recurrenceRule"], "recurrenceRule is required"));
56225
56634
  }
56226
56635
  if (input.defaultStartTime !== void 0 && input.defaultStartTime !== null && !timeRegex.test(input.defaultStartTime)) {
56227
- issues.push(issue3(["defaultStartTime"], "Invalid time format (HH:MM or HH:MM:SS)"));
56636
+ issues.push(issue4(["defaultStartTime"], "Invalid time format (HH:MM or HH:MM:SS)"));
56228
56637
  }
56229
56638
  if (options.requireCanonicalFields && !input.defaultStartTime) {
56230
- issues.push(issue3(["defaultStartTime"], "defaultStartTime is required"));
56639
+ issues.push(issue4(["defaultStartTime"], "defaultStartTime is required"));
56231
56640
  }
56232
56641
  if (options.requireCanonicalFields && input.durationMinutes === void 0) {
56233
- issues.push(issue3(["durationMinutes"], "durationMinutes is required"));
56642
+ issues.push(issue4(["durationMinutes"], "durationMinutes is required"));
56234
56643
  }
56235
56644
  if (input.durationMinutes !== void 0 && input.durationMinutes !== null) {
56236
56645
  if (input.durationMinutes < 1) {
56237
- issues.push(issue3(["durationMinutes"], "durationMinutes must be at least 1"));
56646
+ issues.push(issue4(["durationMinutes"], "durationMinutes must be at least 1"));
56238
56647
  } else if (exceedsMaxDuration(input.durationMinutes, options)) {
56239
- issues.push(issue3(["durationMinutes"], maxDurationMessage(options)));
56648
+ issues.push(issue4(["durationMinutes"], maxDurationMessage(options)));
56240
56649
  }
56241
56650
  }
56242
56651
  if (issues.length > 0) return { ok: false, issues };
@@ -56261,34 +56670,34 @@ function classifySdkEventSchedule(input, options = {}) {
56261
56670
  return classifyCanonicalSchedule(input, options);
56262
56671
  }
56263
56672
  if (hasStartsAt && hasCanonicalStart) {
56264
- issues.push(issue3(["startsAt"], "Use either startsAt or startDate/defaultStartTime, not both"));
56673
+ issues.push(issue4(["startsAt"], "Use either startsAt or startDate/defaultStartTime, not both"));
56265
56674
  }
56266
56675
  if (input.recurrenceRule) {
56267
- issues.push(issue3(["recurrenceRule"], "startsAt schedules are only supported for one-off events"));
56676
+ issues.push(issue4(["recurrenceRule"], "startsAt schedules are only supported for one-off events"));
56268
56677
  }
56269
56678
  if (!hasStartsAt) {
56270
- issues.push(issue3(["startsAt"], "startsAt is required when endsAt is provided"));
56679
+ issues.push(issue4(["startsAt"], "startsAt is required when endsAt is provided"));
56271
56680
  }
56272
56681
  if (!hasEndsAt && !hasDateTimeDuration) {
56273
- issues.push(issue3(["endsAt"], "Provide either endsAt or durationMinutes with startsAt"));
56682
+ issues.push(issue4(["endsAt"], "Provide either endsAt or durationMinutes with startsAt"));
56274
56683
  }
56275
56684
  if (hasEndsAt && hasDateTimeDuration) {
56276
- issues.push(issue3(["endsAt"], "Use either endsAt or durationMinutes with startsAt, not both"));
56685
+ issues.push(issue4(["endsAt"], "Use either endsAt or durationMinutes with startsAt, not both"));
56277
56686
  }
56278
56687
  const startsAt = typeof input.startsAt === "string" ? parseSdkEventDateTime(input.startsAt) : null;
56279
56688
  const endsAt = typeof input.endsAt === "string" ? parseSdkEventDateTime(input.endsAt) : null;
56280
56689
  if (hasStartsAt && !startsAt) {
56281
- issues.push(issue3(["startsAt"], "Invalid datetime format. Use ISO datetime format, e.g. 2026-06-01T10:00:00Z"));
56690
+ issues.push(issue4(["startsAt"], "Invalid datetime format. Use ISO datetime format, e.g. 2026-06-01T10:00:00Z"));
56282
56691
  }
56283
56692
  if (hasEndsAt && !endsAt) {
56284
- issues.push(issue3(["endsAt"], "Invalid datetime format. Use ISO datetime format, e.g. 2026-06-07T10:00:00Z"));
56693
+ issues.push(issue4(["endsAt"], "Invalid datetime format. Use ISO datetime format, e.g. 2026-06-07T10:00:00Z"));
56285
56694
  }
56286
56695
  if (startsAt && endsAt) {
56287
56696
  const durationMinutes = durationMinutesBetween(startsAt, endsAt);
56288
56697
  if (durationMinutes === null) {
56289
- issues.push(issue3(["endsAt"], "endsAt must be after startsAt and align to a whole minute"));
56698
+ issues.push(issue4(["endsAt"], "endsAt must be after startsAt and align to a whole minute"));
56290
56699
  } else if (exceedsMaxDuration(durationMinutes, options)) {
56291
- issues.push(issue3(["endsAt"], maxDurationMessage(options)));
56700
+ issues.push(issue4(["endsAt"], maxDurationMessage(options)));
56292
56701
  }
56293
56702
  if (issues.length === 0 && durationMinutes !== null) {
56294
56703
  return {
@@ -56307,9 +56716,9 @@ function classifySdkEventSchedule(input, options = {}) {
56307
56716
  }
56308
56717
  if (startsAt && hasDateTimeDuration && input.durationMinutes !== void 0 && input.durationMinutes !== null) {
56309
56718
  if (input.durationMinutes < 1) {
56310
- issues.push(issue3(["durationMinutes"], "durationMinutes must be at least 1"));
56719
+ issues.push(issue4(["durationMinutes"], "durationMinutes must be at least 1"));
56311
56720
  } else if (exceedsMaxDuration(input.durationMinutes, options)) {
56312
- issues.push(issue3(["durationMinutes"], maxDurationMessage(options)));
56721
+ issues.push(issue4(["durationMinutes"], maxDurationMessage(options)));
56313
56722
  }
56314
56723
  if (issues.length === 0) {
56315
56724
  const endsAtMs = startsAt.epochMs + input.durationMinutes * 6e4;
@@ -56592,10 +57001,10 @@ function eventSeriesCommand(event) {
56592
57001
  categoryIdentifier: event.categoryRef ?? void 0,
56593
57002
  formIdentifier: event.formRef ?? void 0,
56594
57003
  capacity: capacity(event.capacity),
56595
- pricing: pricing.value,
56596
- priceDisplay: event.pricing?.priceDisplay ?? void 0,
56597
- acceptsPasses: event.pricing?.acceptsPasses ?? void 0,
56598
- acceptsMemberships: event.pricing?.acceptsMemberships ?? void 0,
57004
+ pricing: pricing.value.pricing,
57005
+ priceDisplay: pricing.value.priceDisplay ?? void 0,
57006
+ acceptsPasses: pricing.value.acceptsPasses,
57007
+ acceptsMemberships: pricing.value.acceptsMemberships,
56599
57008
  occurrences: [occurrence.value],
56600
57009
  content: event.content ? {
56601
57010
  summary: event.content.summary ?? void 0,
@@ -56603,6 +57012,7 @@ function eventSeriesCommand(event) {
56603
57012
  image: event.content.image ?? void 0
56604
57013
  } : void 0,
56605
57014
  settings: event.settings,
57015
+ paymentTerms: event.paymentTerms,
56606
57016
  presentation: event.presentation,
56607
57017
  tags: event.tags
56608
57018
  }
@@ -56686,20 +57096,36 @@ function eventPricing(event) {
56686
57096
  }
56687
57097
  switch (pricing.pricing.kind) {
56688
57098
  case "free":
56689
- return ok({ kind: "free" });
57099
+ return ok({
57100
+ pricing: { kind: "free" },
57101
+ priceDisplay: pricing.pricing.priceDisplay,
57102
+ acceptsPasses: pricing.pricing.acceptsPasses,
57103
+ acceptsMemberships: pricing.pricing.acceptsMemberships
57104
+ });
56690
57105
  case "fixed_price":
56691
57106
  return ok({
56692
- kind: "fixed_price",
56693
- price: {
56694
- amountCents: pricing.pricing.priceAmount,
56695
- currency: pricing.pricing.priceCurrency
56696
- }
57107
+ pricing: {
57108
+ kind: "fixed_price",
57109
+ price: {
57110
+ amountCents: pricing.pricing.priceAmount,
57111
+ currency: pricing.pricing.priceCurrency
57112
+ }
57113
+ },
57114
+ priceDisplay: pricing.pricing.priceDisplay,
57115
+ acceptsPasses: pricing.pricing.acceptsPasses,
57116
+ acceptsMemberships: pricing.pricing.acceptsMemberships
56697
57117
  });
56698
57118
  case "ticket_types":
56699
- return unsupported(
56700
- event.identifier,
56701
- `Event ${event.identifier} uses ticket-type pricing; command-backed event pushes do not support ticket types yet.`
56702
- );
57119
+ return ok({
57120
+ pricing: {
57121
+ kind: "ticket_types",
57122
+ currency: pricing.pricing.priceCurrency,
57123
+ ticketTypes: pricing.pricing.ticketTypes
57124
+ },
57125
+ priceDisplay: pricing.pricing.priceDisplay,
57126
+ acceptsPasses: pricing.pricing.acceptsPasses,
57127
+ acceptsMemberships: pricing.pricing.acceptsMemberships
57128
+ });
56703
57129
  default:
56704
57130
  return assertNever(pricing.pricing);
56705
57131
  }
@@ -56757,6 +57183,9 @@ function eventSeriesUpsertInput(command) {
56757
57183
  schedule: scheduleFromOccurrence(occurrence),
56758
57184
  capacity: capacityLimit(command.input.capacity),
56759
57185
  pricing: eventPricingInput(command.input),
57186
+ ...command.input.paymentTerms === void 0 ? {} : {
57187
+ paymentTerms: command.input.paymentTerms
57188
+ },
56760
57189
  venueRef: command.input.venueIdentifier ?? (command.input.venueRef ? refSlug(command.input.venueRef) : null),
56761
57190
  categoryRef: command.input.categoryIdentifier ?? (command.input.categoryRef ? refSlug(command.input.categoryRef) : null),
56762
57191
  content: eventContentInput(command.input.content),
@@ -56770,8 +57199,8 @@ function eventContentInput(content) {
56770
57199
  if (!content) return void 0;
56771
57200
  return {
56772
57201
  ...content.summary ? { summary: content.summary } : {},
56773
- ...typeof content.body === "string" || isRecord18(content.body) ? { body: content.body } : {},
56774
- ...typeof content.image === "string" || isRecord18(content.image) ? { image: content.image } : {}
57202
+ ...typeof content.body === "string" || isRecord19(content.body) ? { body: content.body } : {},
57203
+ ...typeof content.image === "string" || isRecord19(content.image) ? { image: content.image } : {}
56775
57204
  };
56776
57205
  }
56777
57206
  function courseUpsertInput(command) {
@@ -56818,9 +57247,19 @@ function eventPricingInput(input) {
56818
57247
  acceptsMemberships: input.acceptsMemberships ?? false
56819
57248
  };
56820
57249
  case "ticket_types":
56821
- throw new Error(
56822
- "Unsupported ticket-type event command reached SDK mapper."
56823
- );
57250
+ if (!input.pricing.ticketTypes || input.pricing.ticketTypes.length === 0) {
57251
+ throw new Error(
57252
+ "Ticket-type event command is missing inline ticketTypes."
57253
+ );
57254
+ }
57255
+ return {
57256
+ kind: "ticket_types",
57257
+ priceCurrency: input.pricing.currency ?? "USD",
57258
+ priceDisplay: input.priceDisplay ?? null,
57259
+ acceptsPasses: input.acceptsPasses ?? false,
57260
+ acceptsMemberships: input.acceptsMemberships ?? false,
57261
+ ticketTypes: input.pricing.ticketTypes
57262
+ };
56824
57263
  case "manual_payment":
56825
57264
  case "external":
56826
57265
  throw new Error(
@@ -56942,7 +57381,7 @@ function toUtcIso(date, time) {
56942
57381
  const normalizedTime = time.length === 5 ? `${time}:00` : time;
56943
57382
  return (/* @__PURE__ */ new Date(`${date}T${normalizedTime}Z`)).toISOString();
56944
57383
  }
56945
- function isRecord18(value) {
57384
+ function isRecord19(value) {
56946
57385
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
56947
57386
  }
56948
57387
  function unsupported(identifier, message) {
@@ -57784,15 +58223,15 @@ function validateBlockContent(data, manifest, customFields) {
57784
58223
  validator.parse(data);
57785
58224
  } catch (error) {
57786
58225
  if (error instanceof ZodError) {
57787
- for (const issue4 of error.issues) {
57788
- const fieldPath = issue4.path.join(".");
57789
- if (issue4.code === "invalid_type" && issue4.received === "undefined") {
58226
+ for (const issue5 of error.issues) {
58227
+ const fieldPath = issue5.path.join(".");
58228
+ if (issue5.code === "invalid_type" && issue5.received === "undefined") {
57790
58229
  continue;
57791
58230
  }
57792
58231
  warnings.push({
57793
58232
  type: "invalid_content",
57794
58233
  field: fieldPath || "(root)",
57795
- message: `Invalid content${fieldPath ? ` in "${fieldPath}"` : ""}: ${issue4.message}`
58234
+ message: `Invalid content${fieldPath ? ` in "${fieldPath}"` : ""}: ${issue5.message}`
57796
58235
  });
57797
58236
  }
57798
58237
  }
@@ -59228,7 +59667,7 @@ async function handleThemePushForAllScope(params) {
59228
59667
  }
59229
59668
  const validation = themeSchema2.safeParse(localTheme.theme);
59230
59669
  if (!validation.success) {
59231
- const errors = validation.error.issues.map((issue4) => ` - ${issue4.path.join(".")}: ${issue4.message}`).join("\n");
59670
+ const errors = validation.error.issues.map((issue5) => ` - ${issue5.path.join(".")}: ${issue5.message}`).join("\n");
59232
59671
  output.warn(
59233
59672
  `Skipping theme push - invalid theme at content/themes/${themeName}.json:
59234
59673
  ${errors}`
@@ -59894,7 +60333,7 @@ function firstNestedContainerChange(localChanges, remoteChanges) {
59894
60333
  }
59895
60334
  function firstSameFieldConflictPath(localChanges, remoteChanges) {
59896
60335
  const remotePaths = new Set(remoteChanges.keys());
59897
- return [...localChanges.keys()].filter((path25) => remotePaths.has(path25)).sort()[0] ?? null;
60336
+ return [...localChanges.keys()].filter((path27) => remotePaths.has(path27)).sort()[0] ?? null;
59898
60337
  }
59899
60338
  function unsupportedNestedMerge(subject, fieldPath) {
59900
60339
  return {
@@ -59976,37 +60415,37 @@ function valueKind(value) {
59976
60415
  if (typeof value === "object") return "object";
59977
60416
  return "scalar";
59978
60417
  }
59979
- function entryChange(path25, value, containerKind) {
60418
+ function entryChange(path27, value, containerKind) {
59980
60419
  switch (containerKind) {
59981
60420
  case "array":
59982
- if (Array.isArray(value)) return { path: path25, value, containerKind };
60421
+ if (Array.isArray(value)) return { path: path27, value, containerKind };
59983
60422
  break;
59984
60423
  case "object":
59985
60424
  if (value && typeof value === "object" && !Array.isArray(value)) {
59986
- return { path: path25, value, containerKind };
60425
+ return { path: path27, value, containerKind };
59987
60426
  }
59988
60427
  break;
59989
60428
  case "null":
59990
- if (value === null || value === void 0) return { path: path25, value, containerKind };
60429
+ if (value === null || value === void 0) return { path: path27, value, containerKind };
59991
60430
  break;
59992
60431
  case "scalar":
59993
- if (isScalarEntryChangeValue(value)) return { path: path25, value, containerKind };
60432
+ if (isScalarEntryChangeValue(value)) return { path: path27, value, containerKind };
59994
60433
  break;
59995
60434
  default:
59996
60435
  assertNever(containerKind);
59997
60436
  }
59998
- throw new Error(`Invalid entry merge change at ${path25}.`);
60437
+ throw new Error(`Invalid entry merge change at ${path27}.`);
59999
60438
  }
60000
60439
  function isScalarEntryChangeValue(value) {
60001
60440
  return value === void 0 || value === null || ["boolean", "number", "string"].includes(typeof value);
60002
60441
  }
60003
- function expectStringValue(path25, value) {
60442
+ function expectStringValue(path27, value) {
60004
60443
  if (typeof value === "string") return value;
60005
- throw new Error(`Entry merge expected ${path25} to be a string.`);
60444
+ throw new Error(`Entry merge expected ${path27} to be a string.`);
60006
60445
  }
60007
- function expectBooleanValue(path25, value) {
60446
+ function expectBooleanValue(path27, value) {
60008
60447
  if (typeof value === "boolean") return value;
60009
- throw new Error(`Entry merge expected ${path25} to be a boolean.`);
60448
+ throw new Error(`Entry merge expected ${path27} to be a boolean.`);
60010
60449
  }
60011
60450
  function expectStatusValue(value) {
60012
60451
  if (value === "draft" || value === "published") return value;
@@ -60644,6 +61083,19 @@ async function executePushForEnv(output, target, scope, type, identifier, option
60644
61083
  }
60645
61084
  const pushScope = parsedPushScope;
60646
61085
  const jsonOutput = globalOpts.json ?? false;
61086
+ const canonicalEntrySyncDecision = getCanonicalEntrySyncDecision({
61087
+ scope: pushScope,
61088
+ contentType: type,
61089
+ operation: "push"
61090
+ });
61091
+ if (canonicalEntrySyncDecision.tag === "reject") {
61092
+ process.exitCode = 1;
61093
+ output.result(false, canonicalEntrySyncDecision.violation.message, {
61094
+ contentType: canonicalEntrySyncDecision.violation.contentType,
61095
+ suggestion: canonicalEntrySyncDecision.violation.suggestion
61096
+ });
61097
+ return { success: false };
61098
+ }
60647
61099
  const deleteOrphanedEnabled = options.deleteOrphaned ?? false;
60648
61100
  let deleteMissingEnabled = options.deleteMissing ?? false;
60649
61101
  if (deleteMissingEnabled) {
@@ -60714,7 +61166,7 @@ ${available.map((t) => ` - ${t.name} (content/themes/${t.name}.json)`).join("\n
60714
61166
  }
60715
61167
  const validation = themeSchema.safeParse(localTheme.theme);
60716
61168
  if (!validation.success) {
60717
- const errors = validation.error.issues.map((issue4) => ` - ${issue4.path.join(".")}: ${issue4.message}`).join("\n");
61169
+ const errors = validation.error.issues.map((issue5) => ` - ${issue5.path.join(".")}: ${issue5.message}`).join("\n");
60718
61170
  output.error(
60719
61171
  `Invalid theme file at content/themes/${themeName}.json:
60720
61172
  ${errors}`
@@ -60902,8 +61354,16 @@ ${errors}`
60902
61354
  });
60903
61355
  return { success: false };
60904
61356
  }
61357
+ const legacyEventEntryFiles = shouldExcludeCanonicalEntries(canonicalEntrySyncDecision) ? await findLegacyEventEntryFiles(contentDir) : [];
61358
+ if (legacyEventEntryFiles.length > 0) {
61359
+ output.warn(
61360
+ "Legacy event entry files detected and ignored by generic entry sync.",
61361
+ formatLegacyEventEntryWarning(legacyEventEntryFiles)
61362
+ );
61363
+ }
60905
61364
  output.info("Reading local content...");
60906
- const localContent = normalizeLocalContentShape(await readAllContent(contentDir));
61365
+ const rawLocalContent = normalizeLocalContentShape(await readAllContent(contentDir));
61366
+ const localContent = shouldExcludeCanonicalEntries(canonicalEntrySyncDecision) ? stripCanonicalEventEntriesFromLocalContent(rawLocalContent).content : rawLocalContent;
60907
61367
  if (options.mergeRemote) {
60908
61368
  return planAndReportRemoteEntryMerge({
60909
61369
  output,
@@ -60945,7 +61405,7 @@ ${errors}`
60945
61405
  return { success: true };
60946
61406
  }
60947
61407
  output.info("Fetching remote content for comparison...");
60948
- const remoteContent = await client.pull.all();
61408
+ const remoteContent = stripCanonicalEventEntriesFromPulledContent(await client.pull.all()).content;
60949
61409
  if (remoteContent.meta.truncated) {
60950
61410
  output.warn("Warning: Remote content was truncated due to size limits.");
60951
61411
  output.warn(
@@ -61228,7 +61688,7 @@ ${errors}`
61228
61688
  if (metadataFlags.shouldUpdateMetadata && !skipMeta) {
61229
61689
  try {
61230
61690
  output.info("Updating local metadata...");
61231
- const freshRemote = await client.pull.all();
61691
+ const freshRemote = stripCanonicalEventEntriesFromPulledContent(await client.pull.all()).content;
61232
61692
  const entriesForMeta = {};
61233
61693
  if (metadataFlags.willUpdateEntries && freshRemote.meta.entries) {
61234
61694
  for (const [key, meta] of Object.entries(freshRemote.meta.entries)) {
@@ -63007,7 +63467,7 @@ var THEME_FIELD_CATEGORY_MAP = {
63007
63467
  };
63008
63468
 
63009
63469
  // src/cli/init-docs/zod-to-markdown.ts
63010
- function isRecord19(value) {
63470
+ function isRecord20(value) {
63011
63471
  return typeof value === "object" && value !== null && !Array.isArray(value);
63012
63472
  }
63013
63473
  function isZodTypeAny(value) {
@@ -63135,7 +63595,7 @@ function extractLiteralValue(schema) {
63135
63595
  const typeName = getTypeName(schema);
63136
63596
  if (typeName !== ZodTypeName.ZodLiteral) return void 0;
63137
63597
  const def = schema._def;
63138
- if (!isRecord19(def)) return void 0;
63598
+ if (!isRecord20(def)) return void 0;
63139
63599
  return String(def.value);
63140
63600
  }
63141
63601
  function extractSchemaInfo(schema, skipFields = []) {
@@ -63205,7 +63665,7 @@ function extractFieldInfo(name, schema) {
63205
63665
  }
63206
63666
  if (typeName === ZodTypeName.ZodRecord) {
63207
63667
  const def = inner._def;
63208
- const valueSchema = isRecord19(def) ? def.valueType : void 0;
63668
+ const valueSchema = isRecord20(def) ? def.valueType : void 0;
63209
63669
  if (!isZodTypeAny(valueSchema)) {
63210
63670
  info.recordValueType = "unknown";
63211
63671
  return info;
@@ -63220,7 +63680,7 @@ function extractFieldInfo(name, schema) {
63220
63680
  }
63221
63681
  } else if (getTypeName(valueInner) === ZodTypeName.ZodRecord) {
63222
63682
  const nestedDef = valueInner._def;
63223
- const nestedValueSchema = isRecord19(nestedDef) ? nestedDef.valueType : void 0;
63683
+ const nestedValueSchema = isRecord20(nestedDef) ? nestedDef.valueType : void 0;
63224
63684
  if (!isZodTypeAny(nestedValueSchema)) {
63225
63685
  info.recordValueType = "record<string, unknown>";
63226
63686
  return info;
@@ -63231,7 +63691,7 @@ function extractFieldInfo(name, schema) {
63231
63691
  }
63232
63692
  if (typeName === ZodTypeName.ZodUnion || typeName === ZodTypeName.ZodDiscriminatedUnion) {
63233
63693
  const def = inner._def;
63234
- const optionsValue = isRecord19(def) ? def.options : void 0;
63694
+ const optionsValue = isRecord20(def) ? def.options : void 0;
63235
63695
  const options = Array.isArray(optionsValue) ? optionsValue.filter(isZodTypeAny) : [];
63236
63696
  const optionTypes = options.map((opt) => {
63237
63697
  const { inner: optInner } = unwrapSchema(opt);
@@ -64396,7 +64856,7 @@ var SimpleCache = class {
64396
64856
  };
64397
64857
 
64398
64858
  // src/version.ts
64399
- var SDK_VERSION = "0.84.1";
64859
+ var SDK_VERSION = "0.85.0";
64400
64860
 
64401
64861
  // src/client/error.ts
64402
64862
  var RiverbankApiError = class _RiverbankApiError extends Error {
@@ -65340,14 +65800,14 @@ function createRiverbankClient(config2) {
65340
65800
  );
65341
65801
  }
65342
65802
  async function getPageWithResilienceInternal(params) {
65343
- const { siteId, path: path25, preview = false, signal } = params;
65344
- const cacheKey = `page:${siteId}:${path25}:${preview}`;
65803
+ const { siteId, path: path27, preview = false, signal } = params;
65804
+ const cacheKey = `page:${siteId}:${path27}:${preview}`;
65345
65805
  return resilientFetch(
65346
65806
  cacheKey,
65347
65807
  async (sig) => {
65348
65808
  return await apiClient({
65349
65809
  endpoint: "getContentByPath",
65350
- params: { siteId, path: path25, preview: String(preview) },
65810
+ params: { siteId, path: path27, preview: String(preview) },
65351
65811
  options: { signal: sig }
65352
65812
  });
65353
65813
  },
@@ -65355,7 +65815,7 @@ function createRiverbankClient(config2) {
65355
65815
  preview,
65356
65816
  signal,
65357
65817
  // Prebuild fallback only for published pages (not preview)
65358
- prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadPage(siteId, path25) : void 0
65818
+ prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadPage(siteId, path27) : void 0
65359
65819
  }
65360
65820
  );
65361
65821
  }
@@ -65797,17 +66257,17 @@ function createRiverbankClient(config2) {
65797
66257
  };
65798
66258
  },
65799
66259
  async checkRedirect(params) {
65800
- const { siteId, path: path25, signal } = params;
65801
- if (!siteId || !path25) {
66260
+ const { siteId, path: path27, signal } = params;
66261
+ if (!siteId || !path27) {
65802
66262
  throw new Error("checkRedirect() requires siteId and path");
65803
66263
  }
65804
- const cacheKey = `redirect:${siteId}:${path25}`;
66264
+ const cacheKey = `redirect:${siteId}:${path27}`;
65805
66265
  return resilientFetchData(
65806
66266
  cacheKey,
65807
66267
  async (sig) => {
65808
66268
  return await apiClient({
65809
66269
  endpoint: "checkRedirect",
65810
- params: { site: siteId, path: path25 },
66270
+ params: { site: siteId, path: path27 },
65811
66271
  options: { signal: sig }
65812
66272
  });
65813
66273
  },
@@ -65884,13 +66344,13 @@ function pathToFilename(routePath) {
65884
66344
  return routePath.slice(1).replace(/[^a-zA-Z0-9\-\/]/g, "_").replace(/\//g, "-") + ".json";
65885
66345
  }
65886
66346
  function ensureDir4(dirPath) {
65887
- if (!fs10.existsSync(dirPath)) {
65888
- fs10.mkdirSync(dirPath, { recursive: true });
66347
+ if (!fs11.existsSync(dirPath)) {
66348
+ fs11.mkdirSync(dirPath, { recursive: true });
65889
66349
  }
65890
66350
  }
65891
66351
  function writeJsonFile3(filePath, data) {
65892
66352
  const content = JSON.stringify(data, null, 2);
65893
- fs10.writeFileSync(filePath, content, "utf-8");
66353
+ fs11.writeFileSync(filePath, content, "utf-8");
65894
66354
  return Buffer.byteLength(content, "utf-8");
65895
66355
  }
65896
66356
  function calculateChecksum(data) {
@@ -66217,7 +66677,7 @@ async function loadDeployConfig() {
66217
66677
  }
66218
66678
  async function checkWorkingDirectoryClean(git, prebuildOutput) {
66219
66679
  const status = await git.status();
66220
- const dirtyFiles = status.files.map((f) => f.path).filter((path25) => !path25.startsWith(prebuildOutput));
66680
+ const dirtyFiles = status.files.map((f) => f.path).filter((path27) => !path27.startsWith(prebuildOutput));
66221
66681
  return {
66222
66682
  clean: dirtyFiles.length === 0,
66223
66683
  dirtyFiles
@@ -66488,9 +66948,9 @@ Examples:
66488
66948
  const parseResult = verifyConfigSchema.safeParse(rawConfig);
66489
66949
  if (!parseResult.success) {
66490
66950
  return output.error("Invalid config format", {
66491
- issues: parseResult.error.issues.map((issue4) => ({
66492
- path: issue4.path.join("."),
66493
- message: issue4.message
66951
+ issues: parseResult.error.issues.map((issue5) => ({
66952
+ path: issue5.path.join("."),
66953
+ message: issue5.message
66494
66954
  })),
66495
66955
  suggestion: "Ensure your config exports a valid riverbank config object"
66496
66956
  });
@@ -66748,25 +67208,25 @@ function mapMediaGuardDiagnosticsToAuditIssues(diagnostics) {
66748
67208
  }
66749
67209
  }));
66750
67210
  }
66751
- function extractEmbedReferences(data, path25 = []) {
67211
+ function extractEmbedReferences(data, path27 = []) {
66752
67212
  const refs = [];
66753
67213
  if (!data || typeof data !== "object") return refs;
66754
67214
  if (Array.isArray(data)) {
66755
67215
  data.forEach((item, index) => {
66756
- refs.push(...extractEmbedReferences(item, [...path25, String(index)]));
67216
+ refs.push(...extractEmbedReferences(item, [...path27, String(index)]));
66757
67217
  });
66758
67218
  return refs;
66759
67219
  }
66760
67220
  const obj = data;
66761
67221
  if (obj.kind === "embed" && typeof obj.contentType === "string" && typeof obj.identifier === "string") {
66762
67222
  refs.push({
66763
- path: path25.join("."),
67223
+ path: path27.join("."),
66764
67224
  contentType: obj.contentType,
66765
67225
  identifier: obj.identifier
66766
67226
  });
66767
67227
  }
66768
67228
  for (const [key, value] of Object.entries(obj)) {
66769
- refs.push(...extractEmbedReferences(value, [...path25, key]));
67229
+ refs.push(...extractEmbedReferences(value, [...path27, key]));
66770
67230
  }
66771
67231
  return refs;
66772
67232
  }
@@ -67018,8 +67478,8 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
67018
67478
  client
67019
67479
  });
67020
67480
  const mediaIssues = mapMediaGuardDiagnosticsToAuditIssues(mediaGuardResult.diagnostics);
67021
- errors.push(...mediaIssues.filter((issue4) => issue4.severity === "error"));
67022
- warnings.push(...mediaIssues.filter((issue4) => issue4.severity === "warning"));
67481
+ errors.push(...mediaIssues.filter((issue5) => issue5.severity === "error"));
67482
+ warnings.push(...mediaIssues.filter((issue5) => issue5.severity === "warning"));
67023
67483
  }
67024
67484
  if (!isJsonOutput) {
67025
67485
  output.info("Checking for duplicate page paths...");
@@ -67043,8 +67503,8 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
67043
67503
  }
67044
67504
  errors.push(...auditEventReferences(localContent.events, auditCtx));
67045
67505
  const courseRefIssues = auditCourseReferences(localContent.courses, auditCtx);
67046
- errors.push(...courseRefIssues.filter((issue4) => issue4.severity === "error"));
67047
- warnings.push(...courseRefIssues.filter((issue4) => issue4.severity === "warning"));
67506
+ errors.push(...courseRefIssues.filter((issue5) => issue5.severity === "error"));
67507
+ warnings.push(...courseRefIssues.filter((issue5) => issue5.severity === "warning"));
67048
67508
  const success = errors.length === 0;
67049
67509
  const result = { success, errors, warnings };
67050
67510
  if (isJsonOutput) {
@@ -67059,14 +67519,14 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
67059
67519
  output.info("");
67060
67520
  if (errors.length > 0) {
67061
67521
  output.warn(`Found ${errors.length} error(s):`);
67062
- for (const issue4 of errors) {
67063
- output.info(` [ERROR] ${issue4.message}`);
67522
+ for (const issue5 of errors) {
67523
+ output.info(` [ERROR] ${issue5.message}`);
67064
67524
  }
67065
67525
  }
67066
67526
  if (warnings.length > 0) {
67067
67527
  output.warn(`Found ${warnings.length} warning(s):`);
67068
- for (const issue4 of warnings) {
67069
- output.info(` [WARN] ${issue4.message}`);
67528
+ for (const issue5 of warnings) {
67529
+ output.info(` [WARN] ${issue5.message}`);
67070
67530
  }
67071
67531
  }
67072
67532
  if (success && warnings.length === 0) {
@@ -67700,7 +68160,7 @@ function formatThemeSummaryForPrompt(summary) {
67700
68160
  }
67701
68161
 
67702
68162
  // src/manifest/validation/layout-utils.ts
67703
- function collectLayoutNodeInfos(node, path25 = "layout", out = []) {
68163
+ function collectLayoutNodeInfos(node, path27 = "layout", out = []) {
67704
68164
  if (!node || typeof node !== "object") return out;
67705
68165
  const n = node;
67706
68166
  const type = typeof n.type === "string" ? n.type : "unknown";
@@ -67709,10 +68169,10 @@ function collectLayoutNodeInfos(node, path25 = "layout", out = []) {
67709
68169
  const b = n.$bind;
67710
68170
  if (typeof b.from === "string") bindFrom = b.from;
67711
68171
  }
67712
- out.push({ path: path25, type, bindFrom });
68172
+ out.push({ path: path27, type, bindFrom });
67713
68173
  if (Array.isArray(n.children)) {
67714
68174
  for (let i = 0; i < n.children.length; i++) {
67715
- collectLayoutNodeInfos(n.children[i], `${path25}.children[${i}]`, out);
68175
+ collectLayoutNodeInfos(n.children[i], `${path27}.children[${i}]`, out);
67716
68176
  }
67717
68177
  }
67718
68178
  return out;
@@ -68134,7 +68594,7 @@ function extractNestedHrefBindFromProps(props2) {
68134
68594
  const bind2 = href.$bind;
68135
68595
  return bind2 && typeof bind2 === "object" ? bind2 : null;
68136
68596
  }
68137
- function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatStack = []) {
68597
+ function findMissingLinkHrefs(node, blockId, fields3, path27 = "layout", repeatStack = []) {
68138
68598
  const errors = [];
68139
68599
  if (!node || typeof node !== "object") return errors;
68140
68600
  const n = node;
@@ -68163,21 +68623,21 @@ function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatS
68163
68623
  if (isBoundToLinkField) {
68164
68624
  if (!hrefBind || !hrefFrom) {
68165
68625
  errors.push({
68166
- path: path25,
68167
- message: `Block "${blockId}": ${nodeType} node at ${path25} is bound to a link field but is missing props.href binding`,
68626
+ path: path27,
68627
+ message: `Block "${blockId}": ${nodeType} node at ${path27} is bound to a link field but is missing props.href binding`,
68168
68628
  suggestion: `Add props.href: { "$bind": { "from": "${bindFrom ?? "content.yourLinkField"}", "fallback": null, "transforms": [{ "id": "links.resolve" }] } }`
68169
68629
  });
68170
68630
  } else if (!bindingHasTransform(hrefBind, "links.resolve")) {
68171
68631
  errors.push({
68172
- path: path25,
68173
- message: `Block "${blockId}": ${nodeType} node at ${path25} has props.href binding but is missing transforms: [{id:"links.resolve"}]`,
68632
+ path: path27,
68633
+ message: `Block "${blockId}": ${nodeType} node at ${path27} has props.href binding but is missing transforms: [{id:"links.resolve"}]`,
68174
68634
  suggestion: `Set props.href.$bind.transforms to [{ "id": "links.resolve" }].`
68175
68635
  });
68176
68636
  }
68177
68637
  if (bindFrom && bindFieldType === "link" && !bindingHasTransform(bind2, "links.label")) {
68178
68638
  errors.push({
68179
- path: path25,
68180
- message: `Block "${blockId}": ${nodeType} node at ${path25} binds label from a link field but is missing links.label transform`,
68639
+ path: path27,
68640
+ message: `Block "${blockId}": ${nodeType} node at ${path27} binds label from a link field but is missing links.label transform`,
68181
68641
  suggestion: `Set node.$bind.transforms to [{ "id": "links.label" }] so the label renders as text.`
68182
68642
  });
68183
68643
  }
@@ -68190,7 +68650,7 @@ function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatS
68190
68650
  n.children[i],
68191
68651
  blockId,
68192
68652
  fields3,
68193
- `${path25}.children[${i}]`,
68653
+ `${path27}.children[${i}]`,
68194
68654
  nextRepeatStack
68195
68655
  )
68196
68656
  );
@@ -68198,7 +68658,7 @@ function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatS
68198
68658
  }
68199
68659
  return errors;
68200
68660
  }
68201
- function detectRedundantLinkLabels(node, blockId, fields3, path25 = "layout", repeatStack = []) {
68661
+ function detectRedundantLinkLabels(node, blockId, fields3, path27 = "layout", repeatStack = []) {
68202
68662
  const errors = [];
68203
68663
  if (!node || typeof node !== "object") return errors;
68204
68664
  const n = node;
@@ -68220,7 +68680,7 @@ function detectRedundantLinkLabels(node, blockId, fields3, path25 = "layout", re
68220
68680
  const redundancies = findRedundantLinkTextSiblings(
68221
68681
  children,
68222
68682
  nextRepeatStack,
68223
- path25
68683
+ path27
68224
68684
  );
68225
68685
  errors.push(
68226
68686
  ...redundancies.map((r) => ({
@@ -68237,7 +68697,7 @@ function detectRedundantLinkLabels(node, blockId, fields3, path25 = "layout", re
68237
68697
  n.children[i],
68238
68698
  blockId,
68239
68699
  fields3,
68240
- `${path25}.children[${i}]`,
68700
+ `${path27}.children[${i}]`,
68241
68701
  nextRepeatStack
68242
68702
  )
68243
68703
  );
@@ -68476,19 +68936,19 @@ function extractBlockIdFromSelector(selector) {
68476
68936
  const match = selector.match(/\[data-block=(["'])(custom\.[^"']+)\1\]/);
68477
68937
  return match?.[2] ?? null;
68478
68938
  }
68479
- function validateNodeType(nodeType, path25, ctx) {
68939
+ function validateNodeType(nodeType, path27, ctx) {
68480
68940
  if (!ALLOWED_NODE_TYPES.includes(
68481
68941
  nodeType
68482
68942
  )) {
68483
68943
  return {
68484
- path: `${path25}.type`,
68485
- message: `Block "${ctx.blockId}": Unknown node type "${nodeType}" at ${path25}`,
68944
+ path: `${path27}.type`,
68945
+ message: `Block "${ctx.blockId}": Unknown node type "${nodeType}" at ${path27}`,
68486
68946
  suggestion: `ALLOWED: ${ALLOWED_NODE_TYPES.slice(0, 10).join(", ")}... FIX: Replace "${nodeType}" with a valid node type.`
68487
68947
  };
68488
68948
  }
68489
68949
  return null;
68490
68950
  }
68491
- function validateTransforms(transforms, path25, ctx) {
68951
+ function validateTransforms(transforms, path27, ctx) {
68492
68952
  const errors = [];
68493
68953
  for (let i = 0; i < transforms.length; i++) {
68494
68954
  const transform = transforms[i];
@@ -68497,7 +68957,7 @@ function validateTransforms(transforms, path25, ctx) {
68497
68957
  transform.id
68498
68958
  )) {
68499
68959
  errors.push({
68500
- path: `${path25}.transforms[${i}].id`,
68960
+ path: `${path27}.transforms[${i}].id`,
68501
68961
  message: `Block "${ctx.blockId}": Unknown transform "${transform.id}"`,
68502
68962
  suggestion: `ALLOWED: ${ALLOWED_TRANSFORM_IDS.slice(0, 8).join(", ")}... FIX: Replace with a valid transform ID or remove.`
68503
68963
  });
@@ -68506,7 +68966,7 @@ function validateTransforms(transforms, path25, ctx) {
68506
68966
  }
68507
68967
  return errors;
68508
68968
  }
68509
- function validateBinding(bind2, path25, ctx) {
68969
+ function validateBinding(bind2, path27, ctx) {
68510
68970
  const errors = [];
68511
68971
  if ("from" in bind2 && typeof bind2.from === "string") {
68512
68972
  const bindPath = bind2.from;
@@ -68514,7 +68974,7 @@ function validateBinding(bind2, path25, ctx) {
68514
68974
  const fieldId = bindPath.replace("content.", "").split(".")[0] ?? "";
68515
68975
  if (fieldId && !ctx.fieldIds.has(fieldId)) {
68516
68976
  errors.push({
68517
- path: `${path25}.from`,
68977
+ path: `${path27}.from`,
68518
68978
  message: `Block "${ctx.blockId}": $bind references unknown field "${fieldId}"`,
68519
68979
  suggestion: `DEFINED FIELDS: ${Array.from(ctx.fieldIds).join(", ")}. FIX: Add field { id: '${fieldId}', type: '...' } or use existing field.`
68520
68980
  });
@@ -68522,31 +68982,31 @@ function validateBinding(bind2, path25, ctx) {
68522
68982
  }
68523
68983
  }
68524
68984
  if ("transforms" in bind2 && Array.isArray(bind2.transforms)) {
68525
- errors.push(...validateTransforms(bind2.transforms, path25, ctx));
68985
+ errors.push(...validateTransforms(bind2.transforms, path27, ctx));
68526
68986
  }
68527
68987
  return errors;
68528
68988
  }
68529
- function validateLayoutDeep(node, blockId, fields3, path25 = "layout") {
68989
+ function validateLayoutDeep(node, blockId, fields3, path27 = "layout") {
68530
68990
  const ctx = {
68531
68991
  blockId,
68532
68992
  fieldIds: collectFieldIds(fields3)
68533
68993
  };
68534
- return validateLayoutNode(node, path25, ctx);
68994
+ return validateLayoutNode(node, path27, ctx);
68535
68995
  }
68536
- function validateLayoutNode(node, path25, ctx) {
68996
+ function validateLayoutNode(node, path27, ctx) {
68537
68997
  const errors = [];
68538
68998
  if (!node || typeof node !== "object") {
68539
68999
  return errors;
68540
69000
  }
68541
69001
  const n = node;
68542
69002
  if ("type" in n && typeof n.type === "string") {
68543
- const typeError = validateNodeType(n.type, path25, ctx);
69003
+ const typeError = validateNodeType(n.type, path27, ctx);
68544
69004
  if (typeError) errors.push(typeError);
68545
69005
  }
68546
69006
  if ("$bind" in n && n.$bind && typeof n.$bind === "object") {
68547
69007
  const bindErrors = validateBinding(
68548
69008
  n.$bind,
68549
- `${path25}.$bind`,
69009
+ `${path27}.$bind`,
68550
69010
  ctx
68551
69011
  );
68552
69012
  errors.push(...bindErrors);
@@ -68554,7 +69014,7 @@ function validateLayoutNode(node, path25, ctx) {
68554
69014
  if ("props" in n && n.props && typeof n.props === "object") {
68555
69015
  const propsErrors = validatePropsBindings(
68556
69016
  n.props,
68557
- `${path25}.props`,
69017
+ `${path27}.props`,
68558
69018
  ctx
68559
69019
  );
68560
69020
  errors.push(...propsErrors);
@@ -68563,7 +69023,7 @@ function validateLayoutNode(node, path25, ctx) {
68563
69023
  for (let i = 0; i < n.children.length; i++) {
68564
69024
  const childErrors = validateLayoutNode(
68565
69025
  n.children[i],
68566
- `${path25}.children[${i}]`,
69026
+ `${path27}.children[${i}]`,
68567
69027
  ctx
68568
69028
  );
68569
69029
  errors.push(...childErrors);
@@ -68571,17 +69031,17 @@ function validateLayoutNode(node, path25, ctx) {
68571
69031
  }
68572
69032
  return errors;
68573
69033
  }
68574
- function validatePropsBindings(props2, path25, ctx) {
69034
+ function validatePropsBindings(props2, path27, ctx) {
68575
69035
  const errors = [];
68576
69036
  for (const [key, value] of Object.entries(props2)) {
68577
69037
  if (value && typeof value === "object" && "$bind" in value) {
68578
69038
  const bind2 = value.$bind;
68579
- const bindErrors = validateBinding(bind2, `${path25}.${key}.$bind`, ctx);
69039
+ const bindErrors = validateBinding(bind2, `${path27}.${key}.$bind`, ctx);
68580
69040
  errors.push(...bindErrors);
68581
69041
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
68582
69042
  const nestedErrors = validatePropsBindings(
68583
69043
  value,
68584
- `${path25}.${key}`,
69044
+ `${path27}.${key}`,
68585
69045
  ctx
68586
69046
  );
68587
69047
  errors.push(...nestedErrors);
@@ -68714,7 +69174,7 @@ function collectUsedFieldRefs(node) {
68714
69174
  visit(node, []);
68715
69175
  return { topLevel, nestedByRepeater, itemNameByRepeater };
68716
69176
  }
68717
- function findMissingBindings(node, blockId, path25 = "layout") {
69177
+ function findMissingBindings(node, blockId, path27 = "layout") {
68718
69178
  const errors = [];
68719
69179
  if (!node || typeof node !== "object") {
68720
69180
  return errors;
@@ -68724,15 +69184,15 @@ function findMissingBindings(node, blockId, path25 = "layout") {
68724
69184
  if ("$repeat" in n && n.$repeat && typeof n.$repeat === "object") {
68725
69185
  if (nodeType && CONTENT_NODE_TYPES.includes(nodeType)) {
68726
69186
  errors.push({
68727
- path: path25,
68728
- message: `Block "${blockId}": ${nodeType} node at ${path25} uses $repeat, but content nodes cannot be repeat containers`,
69187
+ path: path27,
69188
+ message: `Block "${blockId}": ${nodeType} node at ${path27} uses $repeat, but content nodes cannot be repeat containers`,
68729
69189
  suggestion: `Move $repeat to a container node (grid/stack/div) and put a ${nodeType} child inside with $bind.from like "item.field".`
68730
69190
  });
68731
69191
  }
68732
69192
  if (!Array.isArray(n.children) || n.children.length === 0) {
68733
69193
  errors.push({
68734
- path: path25,
68735
- message: `Block "${blockId}": node at ${path25} uses $repeat but has no children to repeat`,
69194
+ path: path27,
69195
+ message: `Block "${blockId}": node at ${path27} uses $repeat but has no children to repeat`,
68736
69196
  suggestion: 'Add one or more child nodes under children[] that bind to the repeat item (e.g., $bind.from: "item.text").'
68737
69197
  });
68738
69198
  }
@@ -68741,15 +69201,15 @@ function findMissingBindings(node, blockId, path25 = "layout") {
68741
69201
  const hasBind = "$bind" in n && n.$bind && typeof n.$bind === "object" && "from" in n.$bind;
68742
69202
  if (Array.isArray(n.children) && n.children.length > 0) {
68743
69203
  errors.push({
68744
- path: path25,
68745
- message: `Block "${blockId}": ${nodeType} node at ${path25} has children, but content nodes must have children: null`,
69204
+ path: path27,
69205
+ message: `Block "${blockId}": ${nodeType} node at ${path27} has children, but content nodes must have children: null`,
68746
69206
  suggestion: `Replace this ${nodeType} with a container node (div/stack/inline) and put the ${nodeType} nodes inside it.`
68747
69207
  });
68748
69208
  }
68749
69209
  if (!hasBind) {
68750
69210
  errors.push({
68751
- path: `${path25}`,
68752
- message: `Block "${blockId}": ${nodeType} node at ${path25} has no $bind - it won't display any content`,
69211
+ path: `${path27}`,
69212
+ message: `Block "${blockId}": ${nodeType} node at ${path27} has no $bind - it won't display any content`,
68753
69213
  suggestion: `Add $bind: { from: "content.fieldName" } to connect this ${nodeType} to a field. Example: { "type": "${nodeType}", "$bind": { "from": "content.headline" } }`
68754
69214
  });
68755
69215
  }
@@ -68759,7 +69219,7 @@ function findMissingBindings(node, blockId, path25 = "layout") {
68759
69219
  const childErrors = findMissingBindings(
68760
69220
  n.children[i],
68761
69221
  blockId,
68762
- `${path25}.children[${i}]`
69222
+ `${path27}.children[${i}]`
68763
69223
  );
68764
69224
  errors.push(...childErrors);
68765
69225
  }
@@ -68776,13 +69236,13 @@ function getMaxDepth(node, currentDepth = 0) {
68776
69236
  );
68777
69237
  }
68778
69238
  var CONTAINER_NODE_TYPES = ["section", "stack", "grid", "div", "inline"];
68779
- function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path25 = "layout") {
69239
+ function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path27 = "layout") {
68780
69240
  if (!node || typeof node !== "object") return [];
68781
69241
  const n = node;
68782
69242
  const truncatedPaths = [];
68783
69243
  if (currentDepth === maxAllowedDepth && n.children === null) {
68784
69244
  if (CONTAINER_NODE_TYPES.includes(n.type || "")) {
68785
- truncatedPaths.push(`${path25} (${n.type ?? "node"} at depth ${currentDepth})`);
69245
+ truncatedPaths.push(`${path27} (${n.type ?? "node"} at depth ${currentDepth})`);
68786
69246
  }
68787
69247
  }
68788
69248
  if (n.children && Array.isArray(n.children)) {
@@ -68792,7 +69252,7 @@ function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path
68792
69252
  child,
68793
69253
  maxAllowedDepth,
68794
69254
  currentDepth + 1,
68795
- `${path25}.children[${i}]`
69255
+ `${path27}.children[${i}]`
68796
69256
  )
68797
69257
  );
68798
69258
  });
@@ -68812,8 +69272,8 @@ function formatValidationFeedback(errors, output) {
68812
69272
  `The layout reached the maximum depth of ${MAX_LAYOUT_DEPTH} levels.`
68813
69273
  );
68814
69274
  lines.push("These container nodes at the depth limit have no children:");
68815
- for (const path25 of truncatedPaths) {
68816
- lines.push(` \u26A0\uFE0F ${path25}`);
69275
+ for (const path27 of truncatedPaths) {
69276
+ lines.push(` \u26A0\uFE0F ${path27}`);
68817
69277
  }
68818
69278
  lines.push("");
68819
69279
  lines.push(
@@ -69275,11 +69735,11 @@ var pass3bOutputSchema = z.object({
69275
69735
  customCssAtRules: z.array(llmMediaAtRuleSchema).nullable(),
69276
69736
  rationale: z.string()
69277
69737
  });
69278
- function getNodeAtPath(layout, path25) {
69279
- if (path25 === "" || path25 === "root" || path25 === "layout") {
69738
+ function getNodeAtPath(layout, path27) {
69739
+ if (path27 === "" || path27 === "root" || path27 === "layout") {
69280
69740
  return layout;
69281
69741
  }
69282
- let normalizedPath = path25;
69742
+ let normalizedPath = path27;
69283
69743
  if (normalizedPath.startsWith("layout.")) {
69284
69744
  normalizedPath = normalizedPath.slice(7);
69285
69745
  }
@@ -70977,6 +71437,26 @@ var eventPricingInputSchema = z.unknown().superRefine((pricing, ctx) => {
70977
71437
  }
70978
71438
  return result.pricing;
70979
71439
  });
71440
+ var eventPaymentTermsInputSchema = z.unknown().superRefine((paymentTerms, ctx) => {
71441
+ const result = classifySdkEventPaymentTerms(paymentTerms);
71442
+ if (!result.ok) {
71443
+ result.issues.forEach((validationIssue) => {
71444
+ ctx.addIssue({
71445
+ code: "custom",
71446
+ path: [...validationIssue.path],
71447
+ message: validationIssue.message
71448
+ });
71449
+ });
71450
+ }
71451
+ }).transform((paymentTerms) => {
71452
+ const result = classifySdkEventPaymentTerms(paymentTerms);
71453
+ if (!result.ok) {
71454
+ throw new Error(
71455
+ "Unreachable invalid event paymentTerms after Zod validation"
71456
+ );
71457
+ }
71458
+ return result.paymentTerms;
71459
+ });
70980
71460
  var eventUpsertInputSchema = z.object({
70981
71461
  identifier: z.string().min(1).optional(),
70982
71462
  title: z.string().min(1, "title is required"),
@@ -70986,6 +71466,7 @@ var eventUpsertInputSchema = z.object({
70986
71466
  schedule: eventScheduleInputSchema,
70987
71467
  capacity: z.number().int().positive().nullable().optional(),
70988
71468
  pricing: eventPricingInputSchema.optional(),
71469
+ paymentTerms: eventPaymentTermsInputSchema.optional(),
70989
71470
  venueRef: z.string().nullable().optional(),
70990
71471
  categoryRef: z.string().nullable().optional(),
70991
71472
  content: z.record(z.string(), z.unknown()).optional(),
@@ -71069,6 +71550,7 @@ var getCommand5 = createGetCommand({
71069
71550
  schedule: event.schedule,
71070
71551
  capacity: event.capacity,
71071
71552
  pricing: event.pricing,
71553
+ paymentTerms: event.paymentTerms,
71072
71554
  venueRef: event.venueRef,
71073
71555
  categoryRef: event.categoryRef,
71074
71556
  formRef: event.formRef,
@@ -71463,8 +71945,485 @@ async function migrateEntries(options) {
71463
71945
  legacyTitlesMigratedToDataTitle
71464
71946
  };
71465
71947
  }
71948
+ var LEGACY_DATA_FIELDS = /* @__PURE__ */ new Set([
71949
+ "title",
71950
+ "slug",
71951
+ "routeSlug",
71952
+ "path",
71953
+ "summary",
71954
+ "body",
71955
+ "image",
71956
+ "cardTitleOverride",
71957
+ "presentation"
71958
+ ]);
71959
+ function isRecord21(value) {
71960
+ return typeof value === "object" && value !== null && !Array.isArray(value);
71961
+ }
71962
+ function hasMeaningfulValue(value) {
71963
+ if (value === void 0 || value === null) return false;
71964
+ if (typeof value === "string") return value.trim().length > 0;
71965
+ if (Array.isArray(value)) return value.length > 0;
71966
+ if (isRecord21(value)) return Object.keys(value).length > 0;
71967
+ return true;
71968
+ }
71969
+ function normalizeComparable(value) {
71970
+ if (value === void 0 || value === null) return null;
71971
+ if (Array.isArray(value)) return value.map(normalizeComparable);
71972
+ if (!isRecord21(value)) return value;
71973
+ const normalized = {};
71974
+ for (const key of Object.keys(value).sort()) {
71975
+ const normalizedValue = normalizeComparable(value[key]);
71976
+ if (normalizedValue !== null) {
71977
+ normalized[key] = normalizedValue;
71978
+ }
71979
+ }
71980
+ return normalized;
71981
+ }
71982
+ function valuesMatch(a, b) {
71983
+ return equal(normalizeComparable(a), normalizeComparable(b));
71984
+ }
71985
+ function slugFromPath(value) {
71986
+ const trimmed = value.trim().replace(/\/+$/, "");
71987
+ const parts = trimmed.split("/").filter(Boolean);
71988
+ return parts.at(-1) ?? trimmed;
71989
+ }
71990
+ function legacySlugCandidates(legacy) {
71991
+ const candidates = /* @__PURE__ */ new Set();
71992
+ const data = isRecord21(legacy.entry.data) ? legacy.entry.data : {};
71993
+ for (const value of [
71994
+ legacy.entry.slug,
71995
+ data.slug,
71996
+ data.routeSlug,
71997
+ data.path,
71998
+ legacy.entry.identifier,
71999
+ legacy.fileBaseIdentifier
72000
+ ]) {
72001
+ if (typeof value !== "string" || value.trim().length === 0) continue;
72002
+ candidates.add(value.includes("/") ? slugFromPath(value) : value.trim());
72003
+ }
72004
+ return [...candidates];
72005
+ }
72006
+ async function readLegacyEventEntries(contentDir) {
72007
+ const legacyDir = path5.join(contentDir, "entries", CANONICAL_EVENT_ENTRY_TYPE);
72008
+ const files = await listFiles(legacyDir, ".json");
72009
+ files.sort();
72010
+ const entries = [];
72011
+ for (const filePath of files) {
72012
+ const raw = await readJsonFile(filePath);
72013
+ if (!isRecord21(raw)) {
72014
+ entries.push({
72015
+ tag: "invalid",
72016
+ filePath,
72017
+ reason: "Legacy event entry file must be a JSON object."
72018
+ });
72019
+ continue;
72020
+ }
72021
+ if (!isRecord21(raw.data)) {
72022
+ entries.push({
72023
+ tag: "invalid",
72024
+ filePath,
72025
+ reason: "Legacy event entry file must include an object data field."
72026
+ });
72027
+ continue;
72028
+ }
72029
+ const identifier = typeof raw.identifier === "string" && raw.identifier.trim() ? raw.identifier : path5.basename(filePath, ".json");
72030
+ entries.push({
72031
+ tag: "valid",
72032
+ legacy: {
72033
+ filePath,
72034
+ fileBaseIdentifier: path5.basename(filePath, ".json"),
72035
+ entry: { ...raw, identifier, data: raw.data }
72036
+ }
72037
+ });
72038
+ }
72039
+ return entries;
72040
+ }
72041
+ async function readCanonicalEventsWithPaths(contentDir) {
72042
+ const eventsDir = path5.join(contentDir, "events");
72043
+ const files = await listFiles(eventsDir, ".json");
72044
+ files.sort();
72045
+ const events = [];
72046
+ for (const filePath of files) {
72047
+ const event = await readJsonFile(filePath);
72048
+ events.push({ event, filePath });
72049
+ }
72050
+ return events;
72051
+ }
72052
+ function findCandidateEvents(legacy, eventsByIdentifier, eventsBySlug) {
72053
+ const byIdentifier = eventsByIdentifier.get(legacy.entry.identifier);
72054
+ if (byIdentifier) return [byIdentifier];
72055
+ const candidates = /* @__PURE__ */ new Map();
72056
+ for (const slug of legacySlugCandidates(legacy)) {
72057
+ for (const event of eventsBySlug.get(slug) ?? []) {
72058
+ candidates.set(event.identifier, event);
72059
+ }
72060
+ }
72061
+ return [...candidates.values()];
72062
+ }
72063
+ function mergeValue(input) {
72064
+ if (!hasMeaningfulValue(input.incoming)) {
72065
+ return { tag: "ignored" };
72066
+ }
72067
+ if (!hasMeaningfulValue(input.current)) {
72068
+ return { tag: "changed", event: input.set(input.incoming), field: input.path };
72069
+ }
72070
+ if (valuesMatch(input.current, input.incoming)) {
72071
+ return { tag: "unchanged" };
72072
+ }
72073
+ return { tag: "conflict", field: input.path };
72074
+ }
72075
+ function mergeLegacyEventIntoCanonical(legacy, event) {
72076
+ const data = legacy.entry.data;
72077
+ const unmappableFields = [];
72078
+ for (const key of Object.keys(data)) {
72079
+ if (!LEGACY_DATA_FIELDS.has(key) && hasMeaningfulValue(data[key])) {
72080
+ unmappableFields.push(`data.${key}`);
72081
+ }
72082
+ }
72083
+ if (legacy.entry.blocks && Object.keys(legacy.entry.blocks).length > 0) {
72084
+ unmappableFields.push("blocks");
72085
+ }
72086
+ if (unmappableFields.length > 0) {
72087
+ return { tag: "unmappable", fields: unmappableFields.sort() };
72088
+ }
72089
+ let mergedEvent = event;
72090
+ const mergedFields = [];
72091
+ const conflicts = [];
72092
+ const compareOnlyFields = [
72093
+ ["title", event.title, data.title],
72094
+ ["slug", event.slug, legacy.entry.slug ?? data.slug ?? data.routeSlug ?? data.path]
72095
+ ];
72096
+ for (const [fieldPath, current, incoming] of compareOnlyFields) {
72097
+ if (!hasMeaningfulValue(incoming)) continue;
72098
+ const normalizedIncoming = fieldPath === "slug" && typeof incoming === "string" ? slugFromPath(incoming) : incoming;
72099
+ if (!valuesMatch(current, normalizedIncoming)) {
72100
+ conflicts.push(fieldPath);
72101
+ }
72102
+ }
72103
+ const mergeTargets = [
72104
+ {
72105
+ path: "content.summary",
72106
+ current: event.content?.summary,
72107
+ incoming: data.summary,
72108
+ set: (value) => ({ ...mergedEvent, content: { ...mergedEvent.content, summary: value } })
72109
+ },
72110
+ {
72111
+ path: "content.body",
72112
+ current: event.content?.body,
72113
+ incoming: data.body,
72114
+ set: (value) => ({
72115
+ ...mergedEvent,
72116
+ content: { ...mergedEvent.content, body: value }
72117
+ })
72118
+ },
72119
+ {
72120
+ path: "content.image",
72121
+ current: event.content?.image,
72122
+ incoming: data.image,
72123
+ set: (value) => ({
72124
+ ...mergedEvent,
72125
+ content: { ...mergedEvent.content, image: value }
72126
+ })
72127
+ },
72128
+ {
72129
+ path: "presentation.cardTitleOverride",
72130
+ current: event.presentation?.cardTitleOverride,
72131
+ incoming: data.cardTitleOverride,
72132
+ set: (value) => ({
72133
+ ...mergedEvent,
72134
+ presentation: {
72135
+ ...mergedEvent.presentation,
72136
+ cardTitleOverride: value
72137
+ }
72138
+ })
72139
+ }
72140
+ ];
72141
+ for (const target of mergeTargets) {
72142
+ const result = mergeValue({ ...target, event: mergedEvent });
72143
+ if (result.tag === "changed") {
72144
+ mergedEvent = result.event;
72145
+ mergedFields.push(result.field);
72146
+ } else if (result.tag === "conflict") {
72147
+ conflicts.push(result.field);
72148
+ }
72149
+ }
72150
+ if (hasMeaningfulValue(data.presentation)) {
72151
+ if (!isRecord21(data.presentation)) {
72152
+ return { tag: "unmappable", fields: ["data.presentation"] };
72153
+ }
72154
+ for (const [key, value] of Object.entries(data.presentation)) {
72155
+ const fieldPath = `presentation.${key}`;
72156
+ const result = mergeValue({
72157
+ event: mergedEvent,
72158
+ path: fieldPath,
72159
+ current: mergedEvent.presentation?.[key],
72160
+ incoming: value,
72161
+ set: (nextValue) => ({
72162
+ ...mergedEvent,
72163
+ presentation: { ...mergedEvent.presentation, [key]: nextValue }
72164
+ })
72165
+ });
72166
+ if (result.tag === "changed") {
72167
+ mergedEvent = result.event;
72168
+ mergedFields.push(result.field);
72169
+ } else if (result.tag === "conflict") {
72170
+ conflicts.push(result.field);
72171
+ }
72172
+ }
72173
+ }
72174
+ return {
72175
+ tag: "merged",
72176
+ event: mergedEvent,
72177
+ fields: mergedFields,
72178
+ conflicts
72179
+ };
72180
+ }
72181
+ async function planEventMigration(contentDir) {
72182
+ const legacyReadResults = await readLegacyEventEntries(contentDir);
72183
+ const invalidLegacyItems = legacyReadResults.filter((result) => result.tag === "invalid").map((result) => ({
72184
+ tag: "invalidLegacyShape",
72185
+ legacyFilePath: result.filePath,
72186
+ reason: result.reason
72187
+ }));
72188
+ const legacyEntries = legacyReadResults.filter((result) => result.tag === "valid").map((result) => result.legacy);
72189
+ const canonicalEvents = await readCanonicalEventsWithPaths(contentDir);
72190
+ const eventFilePaths = new Map(canonicalEvents.map(({ event, filePath }) => [event.identifier, filePath]));
72191
+ const eventsByIdentifier = new Map(canonicalEvents.map(({ event }) => [event.identifier, event]));
72192
+ const eventsBySlug = /* @__PURE__ */ new Map();
72193
+ for (const { event } of canonicalEvents) {
72194
+ const existing = eventsBySlug.get(event.slug) ?? [];
72195
+ eventsBySlug.set(event.slug, [...existing, event]);
72196
+ }
72197
+ const matches = legacyEntries.map((legacy) => ({
72198
+ legacy,
72199
+ candidates: findCandidateEvents(legacy, eventsByIdentifier, eventsBySlug)
72200
+ }));
72201
+ const eventMatchCounts = /* @__PURE__ */ new Map();
72202
+ for (const match of matches) {
72203
+ if (match.candidates.length === 1) {
72204
+ const candidate = match.candidates[0];
72205
+ if (!candidate) continue;
72206
+ eventMatchCounts.set(candidate.identifier, (eventMatchCounts.get(candidate.identifier) ?? 0) + 1);
72207
+ }
72208
+ }
72209
+ const items = [...invalidLegacyItems];
72210
+ for (const match of matches) {
72211
+ if (match.candidates.length === 0) {
72212
+ items.push({
72213
+ tag: "orphanedLegacy",
72214
+ legacyFilePath: match.legacy.filePath,
72215
+ legacyIdentifier: match.legacy.entry.identifier,
72216
+ reason: "No canonical content/events/*.json payload matched by identifier, slug, or route slug."
72217
+ });
72218
+ continue;
72219
+ }
72220
+ if (match.candidates.length > 1) {
72221
+ items.push({
72222
+ tag: "ambiguousMatch",
72223
+ legacyFilePath: match.legacy.filePath,
72224
+ candidateEventIdentifiers: match.candidates.map((event2) => event2.identifier).sort()
72225
+ });
72226
+ continue;
72227
+ }
72228
+ const event = match.candidates[0];
72229
+ if (!event) {
72230
+ items.push({
72231
+ tag: "orphanedLegacy",
72232
+ legacyFilePath: match.legacy.filePath,
72233
+ legacyIdentifier: match.legacy.entry.identifier,
72234
+ reason: "No canonical content/events/*.json payload matched by identifier, slug, or route slug."
72235
+ });
72236
+ continue;
72237
+ }
72238
+ if ((eventMatchCounts.get(event.identifier) ?? 0) > 1) {
72239
+ items.push({
72240
+ tag: "ambiguousMatch",
72241
+ legacyFilePath: match.legacy.filePath,
72242
+ candidateEventIdentifiers: [event.identifier]
72243
+ });
72244
+ continue;
72245
+ }
72246
+ const mergePlan = mergeLegacyEventIntoCanonical(match.legacy, event);
72247
+ if (mergePlan.tag === "unmappable") {
72248
+ items.push({
72249
+ tag: "unmappableLegacyFields",
72250
+ legacyFilePath: match.legacy.filePath,
72251
+ eventIdentifier: event.identifier,
72252
+ fields: mergePlan.fields
72253
+ });
72254
+ continue;
72255
+ }
72256
+ if (mergePlan.conflicts.length > 0) {
72257
+ items.push({
72258
+ tag: "conflict",
72259
+ legacyFilePath: match.legacy.filePath,
72260
+ eventIdentifier: event.identifier,
72261
+ conflicts: mergePlan.conflicts
72262
+ });
72263
+ continue;
72264
+ }
72265
+ const eventFilePath = eventFilePaths.get(event.identifier) ?? path5.join(contentDir, "events", `${event.identifier}.json`);
72266
+ if (mergePlan.fields.length === 0) {
72267
+ items.push({
72268
+ tag: "archiveLegacyOnly",
72269
+ legacyFilePath: match.legacy.filePath,
72270
+ eventFilePath,
72271
+ eventIdentifier: event.identifier,
72272
+ reason: "Legacy event entry copy already matches canonical event payload."
72273
+ });
72274
+ } else {
72275
+ items.push({
72276
+ tag: "mergeLegacyIntoEvent",
72277
+ legacyFilePath: match.legacy.filePath,
72278
+ eventFilePath,
72279
+ eventIdentifier: event.identifier,
72280
+ mergedEvent: mergePlan.event,
72281
+ mergedFields: mergePlan.fields
72282
+ });
72283
+ }
72284
+ }
72285
+ const blockers = items.filter(isBlockedPlanItem);
72286
+ if (blockers.length > 0) {
72287
+ return { tag: "blocked", contentDir, items, blockers };
72288
+ }
72289
+ return { tag: "writable", contentDir, items: items.filter(isWritablePlanItem) };
72290
+ }
72291
+ function isWritablePlanItem(item) {
72292
+ return item.tag === "mergeLegacyIntoEvent" || item.tag === "archiveLegacyOnly";
72293
+ }
72294
+ function isBlockedPlanItem(item) {
72295
+ return !isWritablePlanItem(item);
72296
+ }
72297
+ async function archiveLegacyFile(contentDir, legacyFilePath) {
72298
+ const archiveDir = path5.join(contentDir, ".legacy", "entries", CANONICAL_EVENT_ENTRY_TYPE);
72299
+ await ensureDir(archiveDir);
72300
+ const destinationPath = path5.join(archiveDir, path5.basename(legacyFilePath));
72301
+ if (!await fileExists(destinationPath)) {
72302
+ await fs5.rename(legacyFilePath, destinationPath);
72303
+ return;
72304
+ }
72305
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
72306
+ const ext = path5.extname(destinationPath);
72307
+ const base = destinationPath.slice(0, -ext.length);
72308
+ await fs5.rename(legacyFilePath, `${base}.${timestamp}${ext}`);
72309
+ }
72310
+ async function migrateEvents(options) {
72311
+ const plan = await planEventMigration(options.contentDir);
72312
+ const summary = {
72313
+ merged: 0,
72314
+ archiveOnly: 0,
72315
+ conflicts: 0,
72316
+ ambiguous: 0,
72317
+ unmappable: 0,
72318
+ orphaned: 0,
72319
+ invalid: 0
72320
+ };
72321
+ let eventsToWrite = 0;
72322
+ let legacyFilesToArchive = 0;
72323
+ for (const item of plan.items) {
72324
+ switch (item.tag) {
72325
+ case "mergeLegacyIntoEvent":
72326
+ summary.merged += 1;
72327
+ if (plan.tag === "writable" && !options.dryRun) {
72328
+ await writeJsonFile(item.eventFilePath, item.mergedEvent);
72329
+ await archiveLegacyFile(options.contentDir, item.legacyFilePath);
72330
+ }
72331
+ if (plan.tag === "writable") {
72332
+ eventsToWrite += 1;
72333
+ legacyFilesToArchive += 1;
72334
+ }
72335
+ break;
72336
+ case "archiveLegacyOnly":
72337
+ summary.archiveOnly += 1;
72338
+ if (plan.tag === "writable" && !options.dryRun) {
72339
+ await archiveLegacyFile(options.contentDir, item.legacyFilePath);
72340
+ }
72341
+ if (plan.tag === "writable") {
72342
+ legacyFilesToArchive += 1;
72343
+ }
72344
+ break;
72345
+ case "conflict":
72346
+ summary.conflicts += 1;
72347
+ break;
72348
+ case "ambiguousMatch":
72349
+ summary.ambiguous += 1;
72350
+ break;
72351
+ case "unmappableLegacyFields":
72352
+ summary.unmappable += 1;
72353
+ break;
72354
+ case "orphanedLegacy":
72355
+ summary.orphaned += 1;
72356
+ break;
72357
+ case "invalidLegacyShape":
72358
+ summary.invalid += 1;
72359
+ break;
72360
+ }
72361
+ }
72362
+ return {
72363
+ status: plan.tag,
72364
+ legacyFilesFound: plan.items.length,
72365
+ eventsToWrite,
72366
+ legacyFilesToArchive,
72367
+ ...summary,
72368
+ dryRun: options.dryRun ?? false,
72369
+ items: plan.items
72370
+ };
72371
+ }
71466
72372
 
71467
72373
  // src/cli/commands/migrate.ts
72374
+ function formatEventMigrationItem(item) {
72375
+ switch (item.tag) {
72376
+ case "mergeLegacyIntoEvent":
72377
+ return [
72378
+ "merge",
72379
+ path5.basename(item.legacyFilePath),
72380
+ item.eventIdentifier,
72381
+ item.mergedFields.join(", ")
72382
+ ];
72383
+ case "archiveLegacyOnly":
72384
+ return [
72385
+ "archive",
72386
+ path5.basename(item.legacyFilePath),
72387
+ item.eventIdentifier,
72388
+ item.reason
72389
+ ];
72390
+ case "conflict":
72391
+ return [
72392
+ "conflict",
72393
+ path5.basename(item.legacyFilePath),
72394
+ item.eventIdentifier,
72395
+ item.conflicts.join(", ")
72396
+ ];
72397
+ case "ambiguousMatch":
72398
+ return [
72399
+ "ambiguous",
72400
+ path5.basename(item.legacyFilePath),
72401
+ item.candidateEventIdentifiers.join(", "),
72402
+ "Multiple canonical events matched this legacy entry."
72403
+ ];
72404
+ case "unmappableLegacyFields":
72405
+ return [
72406
+ "unmappable",
72407
+ path5.basename(item.legacyFilePath),
72408
+ item.eventIdentifier ?? "",
72409
+ item.fields.join(", ")
72410
+ ];
72411
+ case "orphanedLegacy":
72412
+ return [
72413
+ "orphaned",
72414
+ path5.basename(item.legacyFilePath),
72415
+ item.legacyIdentifier,
72416
+ item.reason
72417
+ ];
72418
+ case "invalidLegacyShape":
72419
+ return [
72420
+ "invalid",
72421
+ path5.basename(item.legacyFilePath),
72422
+ "",
72423
+ item.reason
72424
+ ];
72425
+ }
72426
+ }
71468
72427
  var migrateCommand = new Command("migrate").description("Migrate local SDK content formats").addCommand(
71469
72428
  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(
71470
72429
  "after",
@@ -71495,6 +72454,13 @@ Examples:
71495
72454
  try {
71496
72455
  const cliConfig = await loadCliConfig();
71497
72456
  const contentDir = path5.resolve(options.contentDir ?? cliConfig.contentDir);
72457
+ if (type === "event") {
72458
+ process.exitCode = 1;
72459
+ output.result(false, "`event` entries use the canonical events migration.", {
72460
+ suggestion: 'Run "riverbankcms migrate events" to fold content/entries/event/*.json into content/events/*.json.'
72461
+ });
72462
+ return;
72463
+ }
71498
72464
  const confirmed = await confirmAction(
71499
72465
  options.dryRun ? "Preview entry migrations?" : "Migrate local entries to the new file format?",
71500
72466
  { yes: options.yes },
@@ -71531,6 +72497,86 @@ Examples:
71531
72497
  handleCommandError(error, output, { target: "local" });
71532
72498
  }
71533
72499
  })
72500
+ ).addCommand(
72501
+ 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(
72502
+ "after",
72503
+ `
72504
+ Description:
72505
+ Folds legacy event entry files into canonical SDK event payloads:
72506
+ content/entries/event/*.json -> content/events/*.json
72507
+
72508
+ Safe migrated legacy files are archived to:
72509
+ content/.legacy/entries/event/*.json
72510
+
72511
+ The migration stops before writing when it finds divergent copy,
72512
+ ambiguous matches, unmappable fields, or orphaned legacy event entries.
72513
+
72514
+ Examples:
72515
+ $ riverbankcms migrate events --dry-run
72516
+ $ riverbankcms migrate events --yes
72517
+ `
72518
+ ).action(async (options, command) => {
72519
+ const { output, envTargets } = getOutputContext(command);
72520
+ if (envTargets.length > 1) {
72521
+ return output.error("Migrate is local-only and does not support --env=both", {
72522
+ suggestion: "Use --env=local (default)"
72523
+ });
72524
+ }
72525
+ try {
72526
+ const cliConfig = await loadCliConfig();
72527
+ const contentDir = path5.resolve(options.contentDir ?? cliConfig.contentDir);
72528
+ const confirmed = await confirmAction(
72529
+ options.dryRun ? "Preview event entry migration?" : "Migrate legacy event entries into canonical event files?",
72530
+ { yes: options.yes },
72531
+ false
72532
+ );
72533
+ if (!confirmed) {
72534
+ output.info("Migration cancelled.");
72535
+ return;
72536
+ }
72537
+ const result = await migrateEvents({
72538
+ contentDir,
72539
+ dryRun: options.dryRun
72540
+ });
72541
+ if (result.status === "blocked") {
72542
+ process.exitCode = 1;
72543
+ output.result(false, "Event migration blocked; no files were written or archived.", {
72544
+ conflicts: result.conflicts,
72545
+ ambiguous: result.ambiguous,
72546
+ unmappable: result.unmappable,
72547
+ orphaned: result.orphaned,
72548
+ invalid: result.invalid
72549
+ });
72550
+ } else if (options.dryRun) {
72551
+ output.info("[DRY RUN] Event migration preview:");
72552
+ } else {
72553
+ output.success("Event entries migrated successfully");
72554
+ }
72555
+ output.table(
72556
+ ["Metric", "Count"],
72557
+ [
72558
+ ["Legacy event files found", String(result.legacyFilesFound)],
72559
+ ["Events to write", String(result.eventsToWrite)],
72560
+ ["Legacy files to archive", String(result.legacyFilesToArchive)],
72561
+ ["Merge plans", String(result.merged)],
72562
+ ["Archive-only plans", String(result.archiveOnly)],
72563
+ ["Conflicts", String(result.conflicts)],
72564
+ ["Ambiguous matches", String(result.ambiguous)],
72565
+ ["Unmappable files", String(result.unmappable)],
72566
+ ["Orphaned files", String(result.orphaned)],
72567
+ ["Invalid files", String(result.invalid)]
72568
+ ]
72569
+ );
72570
+ if (result.items.length > 0) {
72571
+ output.table(
72572
+ ["Action", "Legacy File", "Event", "Details"],
72573
+ result.items.map(formatEventMigrationItem)
72574
+ );
72575
+ }
72576
+ } catch (error) {
72577
+ handleCommandError(error, output, { target: "local" });
72578
+ }
72579
+ })
71534
72580
  );
71535
72581
 
71536
72582
  // src/cli/commands/style.ts