@riverbankcms/sdk 0.84.2 → 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.
@@ -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));
@@ -43007,11 +43007,11 @@ siteBannerSettingsSchema.superRefine((value, ctx) => {
43007
43007
  return;
43008
43008
  }
43009
43009
  const analysis = analyzeSiteBannerBody(value.body);
43010
- for (const issue4 of analysis.issues) {
43010
+ for (const issue5 of analysis.issues) {
43011
43011
  ctx.addIssue({
43012
43012
  code: z.ZodIssueCode.custom,
43013
43013
  path: ["body"],
43014
- message: siteBannerBodyIssueMessage(issue4)
43014
+ message: siteBannerBodyIssueMessage(issue5)
43015
43015
  });
43016
43016
  }
43017
43017
  });
@@ -43045,8 +43045,8 @@ function analyzeSiteBannerBody(body) {
43045
43045
  issues
43046
43046
  };
43047
43047
  }
43048
- function siteBannerBodyIssueMessage(issue4) {
43049
- switch (issue4) {
43048
+ function siteBannerBodyIssueMessage(issue5) {
43049
+ switch (issue5) {
43050
43050
  case "empty":
43051
43051
  return "Banner message is required when the banner is enabled.";
43052
43052
  case "too-many-paragraphs":
@@ -43554,8 +43554,8 @@ var TEMPLATE_BINDING_META_PATHS = [
43554
43554
  "createdAt",
43555
43555
  "updatedAt"
43556
43556
  ];
43557
- function describeInvalidTemplateBindingMetaPath(path25) {
43558
- 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(", ")}`;
43559
43559
  }
43560
43560
 
43561
43561
  // ../content-model/src/routeTemplate.ts
@@ -43729,7 +43729,7 @@ var fieldBindingSchema = z.object({
43729
43729
  var metaBindingSchema = z.object({
43730
43730
  source: z.literal("meta"),
43731
43731
  path: z.enum(TEMPLATE_BINDING_META_PATHS, {
43732
- error: (issue4) => describeInvalidTemplateBindingMetaPath(String(issue4.input))
43732
+ error: (issue5) => describeInvalidTemplateBindingMetaPath(String(issue5.input))
43733
43733
  })
43734
43734
  });
43735
43735
  var literalBindingSchema = z.object({
@@ -43740,7 +43740,7 @@ var transformBindingSchema = z.object({
43740
43740
  source: z.literal("transform"),
43741
43741
  path: z.string().min(1, "Transform path is required"),
43742
43742
  transform: z.enum(BINDING_TRANSFORM_VALUES, {
43743
- error: (issue4) => describeInvalidBindingTransform(String(issue4.input))
43743
+ error: (issue5) => describeInvalidBindingTransform(String(issue5.input))
43744
43744
  })
43745
43745
  });
43746
43746
  var baseBindingSchema = z.discriminatedUnion("source", [
@@ -43944,7 +43944,7 @@ var contentConfigSchema = contentConfigBaseSchema.superRefine((data, ctx) => {
43944
43944
  });
43945
43945
  }
43946
43946
  const paths = data.pages.map((p) => p.path);
43947
- const duplicatePaths = paths.filter((path25, i) => paths.indexOf(path25) !== i);
43947
+ const duplicatePaths = paths.filter((path27, i) => paths.indexOf(path27) !== i);
43948
43948
  if (duplicatePaths.length > 0) {
43949
43949
  ctx.addIssue({
43950
43950
  code: z.ZodIssueCode.custom,
@@ -44001,18 +44001,18 @@ function validateLayoutNodeTypes(layout) {
44001
44001
  errors
44002
44002
  };
44003
44003
  }
44004
- function validateNodeTypesRecursive(node, path25, errors) {
44004
+ function validateNodeTypesRecursive(node, path27, errors) {
44005
44005
  if (!ALLOWED_NODE_TYPES_SET.has(node.type)) {
44006
44006
  errors.push({
44007
- path: `${path25}.type`,
44007
+ path: `${path27}.type`,
44008
44008
  type: "invalid_node_type",
44009
44009
  value: node.type,
44010
- 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.`
44011
44011
  });
44012
44012
  }
44013
44013
  if (node.children && Array.isArray(node.children)) {
44014
44014
  node.children.forEach((child, index) => {
44015
- validateNodeTypesRecursive(child, `${path25}.children[${index}]`, errors);
44015
+ validateNodeTypesRecursive(child, `${path27}.children[${index}]`, errors);
44016
44016
  });
44017
44017
  }
44018
44018
  }
@@ -44024,45 +44024,45 @@ function validateTransformIds(layout) {
44024
44024
  errors
44025
44025
  };
44026
44026
  }
44027
- function validateTransformIdsRecursive(node, path25, errors) {
44027
+ function validateTransformIdsRecursive(node, path27, errors) {
44028
44028
  if (node.$bind?.transforms && Array.isArray(node.$bind.transforms)) {
44029
- validateTransformList(node.$bind.transforms, `${path25}.$bind.transforms`, errors);
44029
+ validateTransformList(node.$bind.transforms, `${path27}.$bind.transforms`, errors);
44030
44030
  }
44031
44031
  if (node.$repeat?.collection?.transforms && Array.isArray(node.$repeat.collection.transforms)) {
44032
- validateTransformList(node.$repeat.collection.transforms, `${path25}.$repeat.collection.transforms`, errors);
44032
+ validateTransformList(node.$repeat.collection.transforms, `${path27}.$repeat.collection.transforms`, errors);
44033
44033
  }
44034
44034
  if (node.$when?.when?.transforms && Array.isArray(node.$when.when.transforms)) {
44035
- validateTransformList(node.$when.when.transforms, `${path25}.$when.when.transforms`, errors);
44035
+ validateTransformList(node.$when.when.transforms, `${path27}.$when.when.transforms`, errors);
44036
44036
  }
44037
44037
  if (node.$scopes && Array.isArray(node.$scopes)) {
44038
44038
  node.$scopes.forEach((scope, index) => {
44039
44039
  if (scope.from?.transforms && Array.isArray(scope.from.transforms)) {
44040
- validateTransformList(scope.from.transforms, `${path25}.$scopes[${index}].from.transforms`, errors);
44040
+ validateTransformList(scope.from.transforms, `${path27}.$scopes[${index}].from.transforms`, errors);
44041
44041
  }
44042
44042
  });
44043
44043
  }
44044
44044
  if (node.props) {
44045
- validatePropsTransforms(node.props, `${path25}.props`, errors);
44045
+ validatePropsTransforms(node.props, `${path27}.props`, errors);
44046
44046
  }
44047
44047
  if (node.children && Array.isArray(node.children)) {
44048
44048
  node.children.forEach((child, index) => {
44049
- validateTransformIdsRecursive(child, `${path25}.children[${index}]`, errors);
44049
+ validateTransformIdsRecursive(child, `${path27}.children[${index}]`, errors);
44050
44050
  });
44051
44051
  }
44052
44052
  }
44053
- function validateTransformList(transforms, path25, errors) {
44053
+ function validateTransformList(transforms, path27, errors) {
44054
44054
  transforms.forEach((transform, index) => {
44055
44055
  if (!ALLOWED_TRANSFORM_IDS_SET.has(transform.id)) {
44056
44056
  errors.push({
44057
- path: `${path25}[${index}].id`,
44057
+ path: `${path27}[${index}].id`,
44058
44058
  type: "invalid_transform_id",
44059
44059
  value: transform.id,
44060
- 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.`
44061
44061
  });
44062
44062
  }
44063
44063
  });
44064
44064
  }
44065
- function validatePropsTransforms(props2, path25, errors) {
44065
+ function validatePropsTransforms(props2, path27, errors) {
44066
44066
  for (const [key, value] of Object.entries(props2)) {
44067
44067
  if (isBindingObject(value)) {
44068
44068
  const binding = value;
@@ -44070,16 +44070,16 @@ function validatePropsTransforms(props2, path25, errors) {
44070
44070
  binding.$bind.transforms.forEach((transform, index) => {
44071
44071
  if (!ALLOWED_TRANSFORM_IDS_SET.has(transform.id)) {
44072
44072
  errors.push({
44073
- path: `${path25}.${key}.$bind.transforms[${index}].id`,
44073
+ path: `${path27}.${key}.$bind.transforms[${index}].id`,
44074
44074
  type: "invalid_transform_id",
44075
44075
  value: transform.id,
44076
- 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.`
44077
44077
  });
44078
44078
  }
44079
44079
  });
44080
44080
  }
44081
44081
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
44082
- validatePropsTransforms(value, `${path25}.${key}`, errors);
44082
+ validatePropsTransforms(value, `${path27}.${key}`, errors);
44083
44083
  }
44084
44084
  }
44085
44085
  }
@@ -44624,8 +44624,8 @@ async function readApiResponse(response, requestInfo, options = {}) {
44624
44624
  function createHttpClient(config2) {
44625
44625
  const baseUrl = `${config2.dashboardUrl}/api/sdk/${config2.siteId}`;
44626
44626
  const timeout = config2.timeout ?? 3e4;
44627
- async function request(method, path25, options) {
44628
- let url = `${baseUrl}${path25}`;
44627
+ async function request(method, path27, options) {
44628
+ let url = `${baseUrl}${path27}`;
44629
44629
  if (options?.params && Object.keys(options.params).length > 0) {
44630
44630
  const searchParams = new URLSearchParams(options.params);
44631
44631
  url = `${url}?${searchParams.toString()}`;
@@ -44648,7 +44648,7 @@ function createHttpClient(config2) {
44648
44648
  } catch (error) {
44649
44649
  const requestInfo2 = buildRequestInfo({
44650
44650
  method,
44651
- path: path25,
44651
+ path: path27,
44652
44652
  url,
44653
44653
  baseUrl,
44654
44654
  dashboardUrl: config2.dashboardUrl,
@@ -44673,7 +44673,7 @@ function createHttpClient(config2) {
44673
44673
  }
44674
44674
  const requestInfo = buildRequestInfo({
44675
44675
  method,
44676
- path: path25,
44676
+ path: path27,
44677
44677
  url,
44678
44678
  baseUrl,
44679
44679
  dashboardUrl: config2.dashboardUrl,
@@ -44703,17 +44703,17 @@ function createHttpClient(config2) {
44703
44703
  return json.data;
44704
44704
  }
44705
44705
  return {
44706
- async get(path25, params) {
44707
- return request("GET", path25, { params });
44706
+ async get(path27, params) {
44707
+ return request("GET", path27, { params });
44708
44708
  },
44709
- async post(path25, body) {
44710
- return request("POST", path25, { body });
44709
+ async post(path27, body) {
44710
+ return request("POST", path27, { body });
44711
44711
  },
44712
- async patch(path25, body) {
44713
- return request("PATCH", path25, { body });
44712
+ async patch(path27, body) {
44713
+ return request("PATCH", path27, { body });
44714
44714
  },
44715
- async delete(path25, body) {
44716
- await request("DELETE", path25, { body });
44715
+ async delete(path27, body) {
44716
+ await request("DELETE", path27, { body });
44717
44717
  }
44718
44718
  };
44719
44719
  }
@@ -46158,12 +46158,12 @@ function collectPushConfigSyncWarnings(sync) {
46158
46158
  async function pushToDashboard(output, dashboardUrl, siteId, apiKey, config2, options) {
46159
46159
  const normalizedDashboardUrl = dashboardUrl.replace(/\/+$/, "");
46160
46160
  const baseUrl = `${normalizedDashboardUrl}/api`;
46161
- const path25 = `/sites/${siteId}/sdk-config`;
46162
- const pushUrl = `${baseUrl}${path25}`;
46161
+ const path27 = `/sites/${siteId}/sdk-config`;
46162
+ const pushUrl = `${baseUrl}${path27}`;
46163
46163
  output.info(`Pushing config to ${pushUrl}...`);
46164
46164
  const requestInfo = {
46165
46165
  method: "POST",
46166
- path: path25,
46166
+ path: path27,
46167
46167
  url: pushUrl,
46168
46168
  baseUrl,
46169
46169
  dashboardUrl: normalizedDashboardUrl,
@@ -46233,9 +46233,9 @@ async function pushConfigAction(output, options) {
46233
46233
  const parseResult = riverbankSiteConfigSchema.safeParse(rawConfig);
46234
46234
  if (!parseResult.success) {
46235
46235
  output.error("Invalid config", {
46236
- issues: parseResult.error.issues.map((issue4) => ({
46237
- path: issue4.path.join("."),
46238
- message: issue4.message
46236
+ issues: parseResult.error.issues.map((issue5) => ({
46237
+ path: issue5.path.join("."),
46238
+ message: issue5.message
46239
46239
  }))
46240
46240
  });
46241
46241
  }
@@ -46942,23 +46942,7 @@ async function writeEvents(contentDir, pulledEvents, options) {
46942
46942
  const eventsMeta = {};
46943
46943
  for (const event of pulledEvents.events) {
46944
46944
  const filePath = path5.join(eventsDir, `${event.identifier}.json`);
46945
- const eventPayload = {
46946
- identifier: event.identifier,
46947
- title: event.title,
46948
- slug: event.slug,
46949
- status: event.status,
46950
- visibility: event.visibility,
46951
- schedule: event.schedule,
46952
- capacity: event.capacity,
46953
- pricing: event.pricing,
46954
- venueRef: event.venueRef,
46955
- categoryRef: event.categoryRef,
46956
- content: event.content,
46957
- formRef: event.formRef,
46958
- settings: event.settings,
46959
- presentation: event.presentation,
46960
- tags: event.tags
46961
- };
46945
+ const eventPayload = toWritableLocalEvent(event);
46962
46946
  stripEnvSpecificMediaFieldsInPlace(eventPayload);
46963
46947
  await writeJsonFile(filePath, eventPayload);
46964
46948
  filePaths.push(filePath);
@@ -46978,6 +46962,26 @@ async function writeEvents(contentDir, pulledEvents, options) {
46978
46962
  }
46979
46963
  return { filePaths, metaPath };
46980
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
+ }
46981
46985
  async function writeCourses(contentDir, pulledCourses, options) {
46982
46986
  const coursesDir = path5.join(contentDir, "courses");
46983
46987
  const metaDir = path5.join(contentDir, ".meta");
@@ -47315,7 +47319,7 @@ async function readSettings(contentDir) {
47315
47319
  throw new Error(
47316
47320
  `${filePath}: invalid settings.json
47317
47321
  ` + parsed.error.issues.map(
47318
- (issue4) => ` - ${issue4.path.join(".") || "(root)"}: ${issue4.message}`
47322
+ (issue5) => ` - ${issue5.path.join(".") || "(root)"}: ${issue5.message}`
47319
47323
  ).join("\n")
47320
47324
  );
47321
47325
  }
@@ -49033,11 +49037,11 @@ function findChangedFields(local, remote, prefix = "") {
49033
49037
  const changes = [];
49034
49038
  const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(remote)]);
49035
49039
  for (const key of allKeys) {
49036
- const path25 = prefix ? `${prefix}.${key}` : key;
49040
+ const path27 = prefix ? `${prefix}.${key}` : key;
49037
49041
  const localVal = local[key];
49038
49042
  const remoteVal = remote[key];
49039
49043
  if (!equal(localVal, remoteVal)) {
49040
- changes.push(path25);
49044
+ changes.push(path27);
49041
49045
  }
49042
49046
  }
49043
49047
  return changes;
@@ -50107,11 +50111,11 @@ function findChangedFieldsWithValues(local, remote, prefix = "") {
50107
50111
  const changes = [];
50108
50112
  const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(remote)]);
50109
50113
  for (const key of allKeys) {
50110
- const path25 = prefix ? `${prefix}.${key}` : key;
50114
+ const path27 = prefix ? `${prefix}.${key}` : key;
50111
50115
  const localVal = local[key];
50112
50116
  const remoteVal = remote[key];
50113
50117
  if (!equal(localVal, remoteVal)) {
50114
- changes.push({ path: path25, before: remoteVal, after: localVal });
50118
+ changes.push({ path: path27, before: remoteVal, after: localVal });
50115
50119
  }
50116
50120
  }
50117
50121
  return changes;
@@ -50528,6 +50532,117 @@ function maskPullDiffForScope(diff, pullScope) {
50528
50532
  }
50529
50533
  return diff;
50530
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
+ }
50531
50646
  function findChangedTopLevelKeys(a, b) {
50532
50647
  const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
50533
50648
  const changed = [];
@@ -50879,6 +50994,17 @@ async function fetchAllContentPaginated(client, contentTypes, output, baseConten
50879
50994
  }
50880
50995
  };
50881
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
+ }
50882
51008
  function createScopedPullContent(meta, overrides) {
50883
51009
  return {
50884
51010
  entries: {},
@@ -51011,6 +51137,30 @@ function shouldPromptForOverwrite(opts) {
51011
51137
  if (opts.force || opts.yes) return false;
51012
51138
  return true;
51013
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
+ }
51014
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", `
51015
51165
  Examples:
51016
51166
  $ riverbankcms pull # Pull all content
@@ -51102,6 +51252,20 @@ Media Sync:
51102
51252
  });
51103
51253
  return;
51104
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
+ });
51105
51269
  output.info(`[DRY RUN] Fetching content from ${envLabel}...`);
51106
51270
  if (options.withTheme && pullScope2 !== "all") {
51107
51271
  output.warn('--with-theme only applies when pulling all content (use "riverbankcms pull theme" instead)');
@@ -51308,13 +51472,7 @@ Media Sync:
51308
51472
  { entries: { [type]: pulled.entries } }
51309
51473
  );
51310
51474
  } else {
51311
- let result = await client.pull.all();
51312
- if (result.meta.truncated) {
51313
- output.warn("Content was truncated due to size limits.");
51314
- output.info("Fetching complete data via pagination...");
51315
- const contentTypes = Object.keys(result.entries);
51316
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51317
- }
51475
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51318
51476
  remoteContent = createScopedPullContent(result.meta, { entries: result.entries });
51319
51477
  }
51320
51478
  break;
@@ -51353,13 +51511,7 @@ Media Sync:
51353
51511
  `[DRY RUN] Would also pull theme to ${path5.join(path5.basename(contentDir), "themes", `${themeName}.json`)}`
51354
51512
  );
51355
51513
  }
51356
- let result = await client.pull.all();
51357
- if (result.meta.truncated) {
51358
- output.warn("Content was truncated due to size limits.");
51359
- output.info("Fetching complete data via pagination...");
51360
- const contentTypes = Object.keys(result.entries);
51361
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51362
- }
51514
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51363
51515
  remoteContent = result;
51364
51516
  break;
51365
51517
  }
@@ -51468,6 +51620,20 @@ Media Sync:
51468
51620
  });
51469
51621
  return;
51470
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
+ });
51471
51637
  if (shouldPromptForOverwrite({
51472
51638
  pullScope,
51473
51639
  contentDirExists: dirExists,
@@ -51577,13 +51743,7 @@ Media Sync:
51577
51743
  });
51578
51744
  } else {
51579
51745
  output.info("Pulling all entries");
51580
- let result = await client.pull.all();
51581
- if (result.meta.truncated) {
51582
- output.warn("Content was truncated due to size limits.");
51583
- output.info("Fetching complete data via pagination...");
51584
- const contentTypes = Object.keys(result.entries);
51585
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51586
- }
51746
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51587
51747
  const mediaContent = createScopedPullContent(result.meta, { entries: result.entries });
51588
51748
  await applyMediaIdentifiers(mediaContent);
51589
51749
  await syncMediaIfRequested(mediaContent);
@@ -51730,13 +51890,7 @@ Media Sync:
51730
51890
  case "all":
51731
51891
  default: {
51732
51892
  output.info("Pulling all content");
51733
- let result = await client.pull.all();
51734
- if (result.meta.truncated) {
51735
- output.warn("Content was truncated due to size limits.");
51736
- output.info("Fetching complete data via pagination...");
51737
- const contentTypes = Object.keys(result.entries);
51738
- result = await fetchAllContentPaginated(client, contentTypes, output, result);
51739
- }
51893
+ const result = await pullAllContentWithCanonicalEntryPolicy(client, output);
51740
51894
  result.settingsWarnings?.forEach((warning) => output.warn(warning));
51741
51895
  await applyMediaIdentifiers(result);
51742
51896
  await syncMediaIfRequested(result);
@@ -52118,8 +52272,8 @@ function normalizeLocalContentShape(content) {
52118
52272
  var identifierRegex = /^[a-z0-9][a-z0-9-]*$/;
52119
52273
  var currencyRegex = /^[A-Z]{3}$/;
52120
52274
  var isoDateTimeRegex = /^\d{4}-\d{2}-\d{2}T.+/;
52121
- function issue2(path25, message) {
52122
- return { path: path25, message };
52275
+ function issue2(path27, message) {
52276
+ return { path: path27, message };
52123
52277
  }
52124
52278
  function isRecord15(value) {
52125
52279
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -52136,27 +52290,27 @@ function isWholeMinuteIsoDateTime(value) {
52136
52290
  return Number.isFinite(epochMs) && epochMs % 6e4 === 0;
52137
52291
  }
52138
52292
  function validateTicketType(raw, index, currency) {
52139
- const path25 = ["ticketTypes", String(index)];
52140
- 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")];
52141
52295
  const issues = [];
52142
52296
  const identifier = raw.identifier;
52143
52297
  if (typeof identifier !== "string" || !identifierRegex.test(identifier)) {
52144
52298
  issues.push(
52145
52299
  issue2(
52146
- [...path25, "identifier"],
52300
+ [...path27, "identifier"],
52147
52301
  "Ticket identifier must use lowercase letters, numbers, and hyphens"
52148
52302
  )
52149
52303
  );
52150
52304
  }
52151
52305
  const name = raw.name;
52152
52306
  if (typeof name !== "string" || name.trim().length === 0) {
52153
- issues.push(issue2([...path25, "name"], "Ticket name is required"));
52307
+ issues.push(issue2([...path27, "name"], "Ticket name is required"));
52154
52308
  }
52155
52309
  const priceAmount = raw.priceAmount;
52156
52310
  if (!isWholeNumber(priceAmount) || priceAmount < 0) {
52157
52311
  issues.push(
52158
52312
  issue2(
52159
- [...path25, "priceAmount"],
52313
+ [...path27, "priceAmount"],
52160
52314
  "Ticket priceAmount must be a non-negative integer"
52161
52315
  )
52162
52316
  );
@@ -52165,7 +52319,7 @@ function validateTicketType(raw, index, currency) {
52165
52319
  if (priceCurrency !== void 0 && priceCurrency !== null && priceCurrency !== currency) {
52166
52320
  issues.push(
52167
52321
  issue2(
52168
- [...path25, "priceCurrency"],
52322
+ [...path27, "priceCurrency"],
52169
52323
  "Ticket priceCurrency must match pricing.priceCurrency"
52170
52324
  )
52171
52325
  );
@@ -52174,7 +52328,7 @@ function validateTicketType(raw, index, currency) {
52174
52328
  if (sortOrder !== void 0 && (!isWholeNumber(sortOrder) || sortOrder < 0)) {
52175
52329
  issues.push(
52176
52330
  issue2(
52177
- [...path25, "sortOrder"],
52331
+ [...path27, "sortOrder"],
52178
52332
  "Ticket sortOrder must be a non-negative integer"
52179
52333
  )
52180
52334
  );
@@ -52183,7 +52337,7 @@ function validateTicketType(raw, index, currency) {
52183
52337
  if (capacityLimit2 !== void 0 && capacityLimit2 !== null && (!isWholeNumber(capacityLimit2) || capacityLimit2 < 1)) {
52184
52338
  issues.push(
52185
52339
  issue2(
52186
- [...path25, "capacityLimit"],
52340
+ [...path27, "capacityLimit"],
52187
52341
  "Ticket capacityLimit must be a positive integer"
52188
52342
  )
52189
52343
  );
@@ -52192,7 +52346,7 @@ function validateTicketType(raw, index, currency) {
52192
52346
  if (attendanceScope !== void 0 && attendanceScope !== "in_person" && attendanceScope !== "online" && attendanceScope !== "both") {
52193
52347
  issues.push(
52194
52348
  issue2(
52195
- [...path25, "attendanceScope"],
52349
+ [...path27, "attendanceScope"],
52196
52350
  "Ticket attendanceScope must be in_person, online, or both"
52197
52351
  )
52198
52352
  );
@@ -52201,7 +52355,7 @@ function validateTicketType(raw, index, currency) {
52201
52355
  if (saleStartsAt !== void 0 && saleStartsAt !== null && (typeof saleStartsAt !== "string" || !isWholeMinuteIsoDateTime(saleStartsAt))) {
52202
52356
  issues.push(
52203
52357
  issue2(
52204
- [...path25, "saleStartsAt"],
52358
+ [...path27, "saleStartsAt"],
52205
52359
  "Ticket saleStartsAt must be an ISO datetime aligned to a whole minute"
52206
52360
  )
52207
52361
  );
@@ -52210,7 +52364,7 @@ function validateTicketType(raw, index, currency) {
52210
52364
  if (saleEndsAt !== void 0 && saleEndsAt !== null && (typeof saleEndsAt !== "string" || !isWholeMinuteIsoDateTime(saleEndsAt))) {
52211
52365
  issues.push(
52212
52366
  issue2(
52213
- [...path25, "saleEndsAt"],
52367
+ [...path27, "saleEndsAt"],
52214
52368
  "Ticket saleEndsAt must be an ISO datetime aligned to a whole minute"
52215
52369
  )
52216
52370
  );
@@ -52218,7 +52372,7 @@ function validateTicketType(raw, index, currency) {
52218
52372
  if (typeof saleStartsAt === "string" && typeof saleEndsAt === "string" && Date.parse(saleEndsAt) <= Date.parse(saleStartsAt)) {
52219
52373
  issues.push(
52220
52374
  issue2(
52221
- [...path25, "saleEndsAt"],
52375
+ [...path27, "saleEndsAt"],
52222
52376
  "Ticket saleEndsAt must be after saleStartsAt"
52223
52377
  )
52224
52378
  );
@@ -52227,7 +52381,7 @@ function validateTicketType(raw, index, currency) {
52227
52381
  if (cmsTicketTypeId !== void 0 && cmsTicketTypeId !== null && (typeof cmsTicketTypeId !== "string" || cmsTicketTypeId.length === 0)) {
52228
52382
  issues.push(
52229
52383
  issue2(
52230
- [...path25, "cmsTicketTypeId"],
52384
+ [...path27, "cmsTicketTypeId"],
52231
52385
  "Ticket cmsTicketTypeId must be a non-empty string"
52232
52386
  )
52233
52387
  );
@@ -52405,11 +52559,239 @@ function classifySdkEventPricing(rawInput) {
52405
52559
  }
52406
52560
  }
52407
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
+
52408
52790
  // src/cli/commands/push/pushAllExtras.ts
52409
52791
  function nullishToNull(value) {
52410
52792
  return value == null ? null : value;
52411
52793
  }
52412
- function isRecord16(value) {
52794
+ function isRecord17(value) {
52413
52795
  return typeof value === "object" && value !== null && !Array.isArray(value);
52414
52796
  }
52415
52797
  function stringValue(value, fallback) {
@@ -52424,8 +52806,13 @@ function normalizeEventPricingForCompare(pricing) {
52424
52806
  if (result.ok) return result.pricing;
52425
52807
  return { kind: "free" };
52426
52808
  }
52809
+ function normalizeEventPaymentTermsForCompare(paymentTerms) {
52810
+ const result = classifySdkEventPaymentTerms(paymentTerms);
52811
+ if (result.ok) return result.paymentTerms;
52812
+ return void 0;
52813
+ }
52427
52814
  function normalizeVenueAddress(value) {
52428
- const obj = isRecord16(value) ? value : {};
52815
+ const obj = isRecord17(value) ? value : {};
52429
52816
  return {
52430
52817
  line1: nullishToNull(typeof obj.line1 === "string" ? obj.line1 : void 0),
52431
52818
  line2: nullishToNull(typeof obj.line2 === "string" ? obj.line2 : void 0),
@@ -52442,7 +52829,7 @@ function normalizeVenueAddress(value) {
52442
52829
  };
52443
52830
  }
52444
52831
  function normalizeVenueLocation(value) {
52445
- if (!isRecord16(value)) return null;
52832
+ if (!isRecord17(value)) return null;
52446
52833
  const obj = value;
52447
52834
  const lat = typeof obj.lat === "number" ? obj.lat : null;
52448
52835
  const lng = typeof obj.lng === "number" ? obj.lng : null;
@@ -52450,7 +52837,7 @@ function normalizeVenueLocation(value) {
52450
52837
  return { lat, lng };
52451
52838
  }
52452
52839
  function normalizeVenueForCompare(venue) {
52453
- const obj = isRecord16(venue) ? venue : {};
52840
+ const obj = isRecord17(venue) ? venue : {};
52454
52841
  return {
52455
52842
  slug: String(obj.slug),
52456
52843
  title: String(obj.title),
@@ -52471,7 +52858,7 @@ function normalizeVenueForCompare(venue) {
52471
52858
  };
52472
52859
  }
52473
52860
  function normalizeEventCategoryForCompare(category) {
52474
- const obj = isRecord16(category) ? category : {};
52861
+ const obj = isRecord17(category) ? category : {};
52475
52862
  return {
52476
52863
  identifier: String(obj.identifier),
52477
52864
  name: String(obj.name),
@@ -52483,8 +52870,8 @@ function normalizeEventCategoryForCompare(category) {
52483
52870
  };
52484
52871
  }
52485
52872
  function normalizeRemoteEventForCompare(event) {
52486
- const obj = isRecord16(event) ? event : {};
52487
- const schedule = isRecord16(obj.schedule) ? obj.schedule : {};
52873
+ const obj = isRecord17(event) ? event : {};
52874
+ const schedule = isRecord17(obj.schedule) ? obj.schedule : {};
52488
52875
  return {
52489
52876
  identifier: String(obj.identifier),
52490
52877
  title: String(obj.title),
@@ -52503,6 +52890,7 @@ function normalizeRemoteEventForCompare(event) {
52503
52890
  typeof obj.capacity === "number" ? obj.capacity : void 0
52504
52891
  ),
52505
52892
  pricing: normalizeEventPricingForCompare(obj.pricing),
52893
+ paymentTerms: normalizeEventPaymentTermsForCompare(obj.paymentTerms),
52506
52894
  venueRef: nullishToNull(
52507
52895
  typeof obj.venueRef === "string" ? obj.venueRef : void 0
52508
52896
  ),
@@ -52512,14 +52900,14 @@ function normalizeRemoteEventForCompare(event) {
52512
52900
  formRef: nullishToNull(
52513
52901
  typeof obj.formRef === "string" ? obj.formRef : void 0
52514
52902
  ),
52515
- content: isRecord16(obj.content) ? obj.content : {},
52516
- settings: isRecord16(obj.settings) ? obj.settings : {},
52517
- 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,
52518
52906
  tags: Array.isArray(obj.tags) ? obj.tags : []
52519
52907
  };
52520
52908
  }
52521
52909
  function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52522
- const local = isRecord16(localEvent) ? localEvent : {};
52910
+ const local = isRecord17(localEvent) ? localEvent : {};
52523
52911
  const base = remoteEvent ? normalizeRemoteEventForCompare(remoteEvent) : normalizeRemoteEventForCompare({
52524
52912
  identifier: local.identifier,
52525
52913
  title: local.title,
@@ -52528,6 +52916,7 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52528
52916
  visibility: local.visibility ?? "private",
52529
52917
  schedule: local.schedule ?? {},
52530
52918
  pricing: local.pricing ?? {},
52919
+ paymentTerms: local.paymentTerms,
52531
52920
  capacity: local.capacity ?? null,
52532
52921
  venueRef: local.venueRef ?? null,
52533
52922
  categoryRef: local.categoryRef ?? null,
@@ -52537,7 +52926,7 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52537
52926
  presentation: local.presentation ?? null,
52538
52927
  tags: local.tags ?? []
52539
52928
  });
52540
- const schedule = isRecord16(local.schedule) ? local.schedule : {};
52929
+ const schedule = isRecord17(local.schedule) ? local.schedule : {};
52541
52930
  return {
52542
52931
  ...base,
52543
52932
  identifier: stringValue(local.identifier, base.identifier),
@@ -52558,6 +52947,7 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52558
52947
  typeof local.capacity === "number" ? local.capacity : void 0
52559
52948
  ),
52560
52949
  pricing: local.pricing === void 0 ? base.pricing : normalizeEventPricingForCompare(local.pricing),
52950
+ paymentTerms: local.paymentTerms === void 0 ? base.paymentTerms : normalizeEventPaymentTermsForCompare(local.paymentTerms),
52561
52951
  venueRef: local.venueRef === void 0 ? base.venueRef : nullishToNull(
52562
52952
  typeof local.venueRef === "string" ? local.venueRef : void 0
52563
52953
  ),
@@ -52567,9 +52957,9 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
52567
52957
  formRef: local.formRef === void 0 ? base.formRef : nullishToNull(
52568
52958
  typeof local.formRef === "string" ? local.formRef : void 0
52569
52959
  ),
52570
- content: local.content === void 0 ? base.content : isRecord16(local.content) ? local.content : {},
52571
- settings: local.settings === void 0 ? base.settings : isRecord16(local.settings) ? local.settings : {},
52572
- presentation: local.presentation === void 0 ? base.presentation : isRecord16(local.presentation) ? local.presentation : null,
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,
52573
52963
  tags: local.tags === void 0 ? base.tags : Array.isArray(local.tags) ? local.tags : []
52574
52964
  };
52575
52965
  }
@@ -52581,7 +52971,7 @@ function toIsoStringOrOriginal(value) {
52581
52971
  function normalizeCourseSessions(value) {
52582
52972
  if (!Array.isArray(value)) return [];
52583
52973
  return value.map((session) => {
52584
- const obj = isRecord16(session) ? session : {};
52974
+ const obj = isRecord17(session) ? session : {};
52585
52975
  return {
52586
52976
  startsAt: toIsoStringOrOriginal(obj.startsAt),
52587
52977
  endsAt: toIsoStringOrOriginal(obj.endsAt)
@@ -52593,18 +52983,18 @@ function normalizeCourseSessions(value) {
52593
52983
  }
52594
52984
  function normalizeCourseProgram(value) {
52595
52985
  if (value == null) return null;
52596
- if (!isRecord16(value)) {
52986
+ if (!isRecord17(value)) {
52597
52987
  return { identifier: null, data: {} };
52598
52988
  }
52599
52989
  return {
52600
52990
  identifier: nullishToNull(
52601
52991
  typeof value.identifier === "string" ? value.identifier : void 0
52602
52992
  ),
52603
- data: isRecord16(value.data) ? value.data : {}
52993
+ data: isRecord17(value.data) ? value.data : {}
52604
52994
  };
52605
52995
  }
52606
52996
  function normalizeRemoteCourseForCompare(course) {
52607
- const obj = isRecord16(course) ? course : {};
52997
+ const obj = isRecord17(course) ? course : {};
52608
52998
  return {
52609
52999
  identifier: String(obj.identifier),
52610
53000
  title: String(obj.title),
@@ -52639,7 +53029,7 @@ function normalizeRemoteCourseForCompare(course) {
52639
53029
  };
52640
53030
  }
52641
53031
  function normalizeLocalCourseAgainstRemoteForCompare(localCourse, remoteCourse) {
52642
- const local = isRecord16(localCourse) ? localCourse : {};
53032
+ const local = isRecord17(localCourse) ? localCourse : {};
52643
53033
  const base = remoteCourse ? normalizeRemoteCourseForCompare(remoteCourse) : normalizeRemoteCourseForCompare({
52644
53034
  identifier: local.identifier,
52645
53035
  title: local.title,
@@ -52660,11 +53050,11 @@ function normalizeLocalCourseAgainstRemoteForCompare(localCourse, remoteCourse)
52660
53050
  });
52661
53051
  const status = local.status === void 0 ? base.status : local.status === "active" || local.status === "cancelled" || local.status === "completed" ? local.status : "draft";
52662
53052
  const visibility = local.visibility === void 0 ? base.visibility : local.visibility === "public" || local.visibility === "private" || local.visibility === "unlisted" ? local.visibility : "public";
52663
- const program2 = local.program === void 0 ? base.program : local.program === null ? null : isRecord16(local.program) ? {
53053
+ const program2 = local.program === void 0 ? base.program : local.program === null ? null : isRecord17(local.program) ? {
52664
53054
  identifier: local.program.identifier === void 0 ? base.program?.identifier ?? null : nullishToNull(
52665
53055
  typeof local.program.identifier === "string" ? local.program.identifier : void 0
52666
53056
  ),
52667
- data: isRecord16(local.program.data) ? local.program.data : base.program?.data ?? {}
53057
+ data: isRecord17(local.program.data) ? local.program.data : base.program?.data ?? {}
52668
53058
  } : base.program;
52669
53059
  return {
52670
53060
  ...base,
@@ -53333,9 +53723,24 @@ var fixedPriceIntentSchema = z.object({
53333
53723
  kind: z.literal("fixed_price"),
53334
53724
  price: moneyAmountSchema
53335
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();
53336
53740
  var ticketTypesPricingIntentSchema = z.object({
53337
53741
  kind: z.literal("ticket_types"),
53338
- currency: currencySchema.optional()
53742
+ currency: currencySchema.optional(),
53743
+ ticketTypes: z.array(inlineEventTicketTypeSchema).readonly().optional()
53339
53744
  }).strict();
53340
53745
  var manualPaymentPricingIntentSchema = z.object({
53341
53746
  kind: z.literal("manual_payment"),
@@ -53780,6 +54185,7 @@ var upsertEventSeriesCommandSchema = z.object({
53780
54185
  occurrences: z.array(eventOccurrenceSchema).min(1).readonly(),
53781
54186
  content: contentSummarySchema.optional(),
53782
54187
  settings: unknownRecordSchema.optional(),
54188
+ paymentTerms: z.unknown().optional(),
53783
54189
  presentation: unknownRecordSchema.nullable().optional(),
53784
54190
  tags: z.array(z.string()).readonly().optional(),
53785
54191
  staffRefs: z.array(staffRefSchema).readonly().optional()
@@ -54899,7 +55305,7 @@ function getSiteCommandLifecycleIntent(command) {
54899
55305
  init_src();
54900
55306
 
54901
55307
  // ../site-commands/src/guards.ts
54902
- function isRecord17(value) {
55308
+ function isRecord18(value) {
54903
55309
  return typeof value === "object" && value !== null;
54904
55310
  }
54905
55311
 
@@ -55159,13 +55565,13 @@ function collectOfferingRequires(input, intervals, intervalPath) {
55159
55565
  function optionalRef(ref, field) {
55160
55566
  return ref ? [{ ref, field }] : [];
55161
55567
  }
55162
- function collectVenueRefsFromIntervals(intervals, path25) {
55163
- 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`));
55164
55570
  }
55165
- function collectNavigationRefs(items, path25) {
55571
+ function collectNavigationRefs(items, path27) {
55166
55572
  return items.flatMap((item, index) => {
55167
- if (!isRecord17(item)) return [];
55168
- const itemPath = `${path25}[${index}]`;
55573
+ if (!isRecord18(item)) return [];
55574
+ const itemPath = `${path27}[${index}]`;
55169
55575
  const refs = [];
55170
55576
  if (typeof item.pageRef === "string") {
55171
55577
  refs.push({ ref: item.pageRef, field: `${itemPath}.pageRef` });
@@ -55179,26 +55585,26 @@ function collectNavigationRefs(items, path25) {
55179
55585
  return refs;
55180
55586
  });
55181
55587
  }
55182
- function collectBlockRefs(blocks, path25) {
55588
+ function collectBlockRefs(blocks, path27) {
55183
55589
  return blocks.flatMap((block, index) => {
55184
- if (!isRecord17(block)) return [];
55185
- const blockPath = `${path25}[${index}]`;
55590
+ if (!isRecord18(block)) return [];
55591
+ const blockPath = `${path27}[${index}]`;
55186
55592
  return [
55187
55593
  ...collectNestedRefs(block.props, `${blockPath}.props`),
55188
55594
  ...collectNestedRefs(block.children, `${blockPath}.children`)
55189
55595
  ];
55190
55596
  });
55191
55597
  }
55192
- function collectNestedRefs(value, path25) {
55598
+ function collectNestedRefs(value, path27) {
55193
55599
  if (typeof value === "string") {
55194
55600
  const parsed = parseResourceRef(value);
55195
- return parsed.ok ? [{ ref: value, field: path25 }] : [];
55601
+ return parsed.ok ? [{ ref: value, field: path27 }] : [];
55196
55602
  }
55197
55603
  if (Array.isArray(value)) {
55198
- return value.flatMap((item, index) => collectNestedRefs(item, `${path25}[${index}]`));
55604
+ return value.flatMap((item, index) => collectNestedRefs(item, `${path27}[${index}]`));
55199
55605
  }
55200
- if (!isRecord17(value)) return [];
55201
- 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}`));
55202
55608
  }
55203
55609
 
55204
55610
  // ../site-commands/src/staticExecutionGaps.ts
@@ -55281,7 +55687,7 @@ function parseCommandBatch(input) {
55281
55687
  if (unknownTypeErrors.length > 0) return err(unknownTypeErrors);
55282
55688
  const parsed = siteCommandBatchSchema.safeParse(input);
55283
55689
  if (!parsed.success) {
55284
- return err(parsed.error.issues.map((issue4) => invalidPayloadError(input, issue4)));
55690
+ return err(parsed.error.issues.map((issue5) => invalidPayloadError(input, issue5)));
55285
55691
  }
55286
55692
  return ok(parsed.data);
55287
55693
  }
@@ -55453,9 +55859,9 @@ function deriveIdempotencyKey(input) {
55453
55859
  ].join("|"));
55454
55860
  }
55455
55861
  function findUnknownCommandTypes(input) {
55456
- if (!isRecord17(input) || !Array.isArray(input.commands)) return [];
55862
+ if (!isRecord18(input) || !Array.isArray(input.commands)) return [];
55457
55863
  return input.commands.flatMap((command, commandIndex) => {
55458
- if (!isRecord17(command) || typeof command.type !== "string") return [];
55864
+ if (!isRecord18(command) || typeof command.type !== "string") return [];
55459
55865
  if (commandTypeSet.has(command.type)) return [];
55460
55866
  return [{
55461
55867
  code: "unknown_command_type",
@@ -55465,32 +55871,32 @@ function findUnknownCommandTypes(input) {
55465
55871
  }];
55466
55872
  });
55467
55873
  }
55468
- function invalidPayloadError(input, issue4) {
55469
- const commandIndex = commandIndexForIssuePath(issue4.path);
55874
+ function invalidPayloadError(input, issue5) {
55875
+ const commandIndex = commandIndexForIssuePath(issue5.path);
55470
55876
  const commandType = commandTypeForIssue(input, commandIndex);
55471
- const field = formatIssuePath(issue4.path);
55877
+ const field = formatIssuePath(issue5.path);
55472
55878
  return {
55473
55879
  code: "invalid_command_payload",
55474
55880
  commandIndex,
55475
55881
  commandType,
55476
55882
  field,
55477
- message: `${field}: ${issue4.message}`
55883
+ message: `${field}: ${issue5.message}`
55478
55884
  };
55479
55885
  }
55480
- function commandIndexForIssuePath(path25) {
55481
- 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;
55482
55888
  }
55483
55889
  function commandTypeForIssue(input, commandIndex) {
55484
- if (!isRecord17(input) || !isUnknownArray3(input.commands)) return null;
55890
+ if (!isRecord18(input) || !isUnknownArray3(input.commands)) return null;
55485
55891
  const command = input.commands[commandIndex];
55486
- return isRecord17(command) && typeof command.type === "string" ? command.type : null;
55892
+ return isRecord18(command) && typeof command.type === "string" ? command.type : null;
55487
55893
  }
55488
55894
  function isUnknownArray3(value) {
55489
55895
  return Array.isArray(value);
55490
55896
  }
55491
- function formatIssuePath(path25) {
55492
- if (path25.length === 0) return "<root>";
55493
- return path25.reduce((formatted, segment) => {
55897
+ function formatIssuePath(path27) {
55898
+ if (path27.length === 0) return "<root>";
55899
+ return path27.reduce((formatted, segment) => {
55494
55900
  if (typeof segment === "number") return `${formatted}[${segment}]`;
55495
55901
  if (formatted.length === 0) return String(segment);
55496
55902
  return `${formatted}.${String(segment)}`;
@@ -55728,11 +56134,12 @@ function indexOfferingCommands(batch) {
55728
56134
  function checkTicketPricedEventsHaveTickets(indexes) {
55729
56135
  return indexes.events.flatMap((event) => {
55730
56136
  const tickets = indexes.ticketsByEventRef.get(event.ref) ?? [];
55731
- 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 [];
55732
56139
  return [commandInvariantViolation(
55733
56140
  event.ref,
55734
56141
  "input.pricing",
55735
- "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."
55736
56143
  )];
55737
56144
  });
55738
56145
  }
@@ -55740,7 +56147,10 @@ function checkTicketQuantitiesWithinCapacity(indexes) {
55740
56147
  return indexes.events.flatMap((event) => {
55741
56148
  const capacity2 = limitedCapacityQuantity(event.input.capacity);
55742
56149
  if (capacity2 === void 0) return [];
55743
- 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);
55744
56154
  if (ticketQuantityTotal <= capacity2) return [];
55745
56155
  return [commandInvariantViolation(
55746
56156
  event.ref,
@@ -56155,8 +56565,8 @@ init_src();
56155
56565
  var timeRegex = /^([01]\d|2[0-3]):([0-5]\d)(:([0-5]\d))?$/;
56156
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)$/;
56157
56567
  var localDateTimeRegex = /^(\d{4})-(\d{2})-(\d{2})T([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?(\.\d{1,3})?$/;
56158
- function issue3(path25, message) {
56159
- return { path: path25, message };
56568
+ function issue4(path27, message) {
56569
+ return { path: path27, message };
56160
56570
  }
56161
56571
  function isValidDateParts(year, month, day) {
56162
56572
  const date = new Date(Date.UTC(year, month - 1, day));
@@ -56220,22 +56630,22 @@ function maxDurationMessage(options) {
56220
56630
  function classifyCanonicalSchedule(input, options) {
56221
56631
  const issues = [];
56222
56632
  if (options.requireCanonicalFields && input.recurrenceRule === void 0) {
56223
- issues.push(issue3(["recurrenceRule"], "recurrenceRule is required"));
56633
+ issues.push(issue4(["recurrenceRule"], "recurrenceRule is required"));
56224
56634
  }
56225
56635
  if (input.defaultStartTime !== void 0 && input.defaultStartTime !== null && !timeRegex.test(input.defaultStartTime)) {
56226
- issues.push(issue3(["defaultStartTime"], "Invalid time format (HH:MM or HH:MM:SS)"));
56636
+ issues.push(issue4(["defaultStartTime"], "Invalid time format (HH:MM or HH:MM:SS)"));
56227
56637
  }
56228
56638
  if (options.requireCanonicalFields && !input.defaultStartTime) {
56229
- issues.push(issue3(["defaultStartTime"], "defaultStartTime is required"));
56639
+ issues.push(issue4(["defaultStartTime"], "defaultStartTime is required"));
56230
56640
  }
56231
56641
  if (options.requireCanonicalFields && input.durationMinutes === void 0) {
56232
- issues.push(issue3(["durationMinutes"], "durationMinutes is required"));
56642
+ issues.push(issue4(["durationMinutes"], "durationMinutes is required"));
56233
56643
  }
56234
56644
  if (input.durationMinutes !== void 0 && input.durationMinutes !== null) {
56235
56645
  if (input.durationMinutes < 1) {
56236
- issues.push(issue3(["durationMinutes"], "durationMinutes must be at least 1"));
56646
+ issues.push(issue4(["durationMinutes"], "durationMinutes must be at least 1"));
56237
56647
  } else if (exceedsMaxDuration(input.durationMinutes, options)) {
56238
- issues.push(issue3(["durationMinutes"], maxDurationMessage(options)));
56648
+ issues.push(issue4(["durationMinutes"], maxDurationMessage(options)));
56239
56649
  }
56240
56650
  }
56241
56651
  if (issues.length > 0) return { ok: false, issues };
@@ -56260,34 +56670,34 @@ function classifySdkEventSchedule(input, options = {}) {
56260
56670
  return classifyCanonicalSchedule(input, options);
56261
56671
  }
56262
56672
  if (hasStartsAt && hasCanonicalStart) {
56263
- 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"));
56264
56674
  }
56265
56675
  if (input.recurrenceRule) {
56266
- 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"));
56267
56677
  }
56268
56678
  if (!hasStartsAt) {
56269
- issues.push(issue3(["startsAt"], "startsAt is required when endsAt is provided"));
56679
+ issues.push(issue4(["startsAt"], "startsAt is required when endsAt is provided"));
56270
56680
  }
56271
56681
  if (!hasEndsAt && !hasDateTimeDuration) {
56272
- issues.push(issue3(["endsAt"], "Provide either endsAt or durationMinutes with startsAt"));
56682
+ issues.push(issue4(["endsAt"], "Provide either endsAt or durationMinutes with startsAt"));
56273
56683
  }
56274
56684
  if (hasEndsAt && hasDateTimeDuration) {
56275
- 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"));
56276
56686
  }
56277
56687
  const startsAt = typeof input.startsAt === "string" ? parseSdkEventDateTime(input.startsAt) : null;
56278
56688
  const endsAt = typeof input.endsAt === "string" ? parseSdkEventDateTime(input.endsAt) : null;
56279
56689
  if (hasStartsAt && !startsAt) {
56280
- 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"));
56281
56691
  }
56282
56692
  if (hasEndsAt && !endsAt) {
56283
- 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"));
56284
56694
  }
56285
56695
  if (startsAt && endsAt) {
56286
56696
  const durationMinutes = durationMinutesBetween(startsAt, endsAt);
56287
56697
  if (durationMinutes === null) {
56288
- 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"));
56289
56699
  } else if (exceedsMaxDuration(durationMinutes, options)) {
56290
- issues.push(issue3(["endsAt"], maxDurationMessage(options)));
56700
+ issues.push(issue4(["endsAt"], maxDurationMessage(options)));
56291
56701
  }
56292
56702
  if (issues.length === 0 && durationMinutes !== null) {
56293
56703
  return {
@@ -56306,9 +56716,9 @@ function classifySdkEventSchedule(input, options = {}) {
56306
56716
  }
56307
56717
  if (startsAt && hasDateTimeDuration && input.durationMinutes !== void 0 && input.durationMinutes !== null) {
56308
56718
  if (input.durationMinutes < 1) {
56309
- issues.push(issue3(["durationMinutes"], "durationMinutes must be at least 1"));
56719
+ issues.push(issue4(["durationMinutes"], "durationMinutes must be at least 1"));
56310
56720
  } else if (exceedsMaxDuration(input.durationMinutes, options)) {
56311
- issues.push(issue3(["durationMinutes"], maxDurationMessage(options)));
56721
+ issues.push(issue4(["durationMinutes"], maxDurationMessage(options)));
56312
56722
  }
56313
56723
  if (issues.length === 0) {
56314
56724
  const endsAtMs = startsAt.epochMs + input.durationMinutes * 6e4;
@@ -56591,10 +57001,10 @@ function eventSeriesCommand(event) {
56591
57001
  categoryIdentifier: event.categoryRef ?? void 0,
56592
57002
  formIdentifier: event.formRef ?? void 0,
56593
57003
  capacity: capacity(event.capacity),
56594
- pricing: pricing.value,
56595
- priceDisplay: event.pricing?.priceDisplay ?? void 0,
56596
- acceptsPasses: event.pricing?.acceptsPasses ?? void 0,
56597
- acceptsMemberships: event.pricing?.acceptsMemberships ?? void 0,
57004
+ pricing: pricing.value.pricing,
57005
+ priceDisplay: pricing.value.priceDisplay ?? void 0,
57006
+ acceptsPasses: pricing.value.acceptsPasses,
57007
+ acceptsMemberships: pricing.value.acceptsMemberships,
56598
57008
  occurrences: [occurrence.value],
56599
57009
  content: event.content ? {
56600
57010
  summary: event.content.summary ?? void 0,
@@ -56602,6 +57012,7 @@ function eventSeriesCommand(event) {
56602
57012
  image: event.content.image ?? void 0
56603
57013
  } : void 0,
56604
57014
  settings: event.settings,
57015
+ paymentTerms: event.paymentTerms,
56605
57016
  presentation: event.presentation,
56606
57017
  tags: event.tags
56607
57018
  }
@@ -56685,20 +57096,36 @@ function eventPricing(event) {
56685
57096
  }
56686
57097
  switch (pricing.pricing.kind) {
56687
57098
  case "free":
56688
- 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
+ });
56689
57105
  case "fixed_price":
56690
57106
  return ok({
56691
- kind: "fixed_price",
56692
- price: {
56693
- amountCents: pricing.pricing.priceAmount,
56694
- currency: pricing.pricing.priceCurrency
56695
- }
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
56696
57117
  });
56697
57118
  case "ticket_types":
56698
- return unsupported(
56699
- event.identifier,
56700
- `Event ${event.identifier} uses ticket-type pricing; command-backed event pushes do not support ticket types yet.`
56701
- );
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
+ });
56702
57129
  default:
56703
57130
  return assertNever(pricing.pricing);
56704
57131
  }
@@ -56756,6 +57183,9 @@ function eventSeriesUpsertInput(command) {
56756
57183
  schedule: scheduleFromOccurrence(occurrence),
56757
57184
  capacity: capacityLimit(command.input.capacity),
56758
57185
  pricing: eventPricingInput(command.input),
57186
+ ...command.input.paymentTerms === void 0 ? {} : {
57187
+ paymentTerms: command.input.paymentTerms
57188
+ },
56759
57189
  venueRef: command.input.venueIdentifier ?? (command.input.venueRef ? refSlug(command.input.venueRef) : null),
56760
57190
  categoryRef: command.input.categoryIdentifier ?? (command.input.categoryRef ? refSlug(command.input.categoryRef) : null),
56761
57191
  content: eventContentInput(command.input.content),
@@ -56769,8 +57199,8 @@ function eventContentInput(content) {
56769
57199
  if (!content) return void 0;
56770
57200
  return {
56771
57201
  ...content.summary ? { summary: content.summary } : {},
56772
- ...typeof content.body === "string" || isRecord18(content.body) ? { body: content.body } : {},
56773
- ...typeof content.image === "string" || isRecord18(content.image) ? { image: content.image } : {}
57202
+ ...typeof content.body === "string" || isRecord19(content.body) ? { body: content.body } : {},
57203
+ ...typeof content.image === "string" || isRecord19(content.image) ? { image: content.image } : {}
56774
57204
  };
56775
57205
  }
56776
57206
  function courseUpsertInput(command) {
@@ -56817,9 +57247,19 @@ function eventPricingInput(input) {
56817
57247
  acceptsMemberships: input.acceptsMemberships ?? false
56818
57248
  };
56819
57249
  case "ticket_types":
56820
- throw new Error(
56821
- "Unsupported ticket-type event command reached SDK mapper."
56822
- );
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
+ };
56823
57263
  case "manual_payment":
56824
57264
  case "external":
56825
57265
  throw new Error(
@@ -56941,7 +57381,7 @@ function toUtcIso(date, time) {
56941
57381
  const normalizedTime = time.length === 5 ? `${time}:00` : time;
56942
57382
  return (/* @__PURE__ */ new Date(`${date}T${normalizedTime}Z`)).toISOString();
56943
57383
  }
56944
- function isRecord18(value) {
57384
+ function isRecord19(value) {
56945
57385
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
56946
57386
  }
56947
57387
  function unsupported(identifier, message) {
@@ -57783,15 +58223,15 @@ function validateBlockContent(data, manifest, customFields) {
57783
58223
  validator.parse(data);
57784
58224
  } catch (error) {
57785
58225
  if (error instanceof ZodError) {
57786
- for (const issue4 of error.issues) {
57787
- const fieldPath = issue4.path.join(".");
57788
- if (issue4.code === "invalid_type" && issue4.received === "undefined") {
58226
+ for (const issue5 of error.issues) {
58227
+ const fieldPath = issue5.path.join(".");
58228
+ if (issue5.code === "invalid_type" && issue5.received === "undefined") {
57789
58229
  continue;
57790
58230
  }
57791
58231
  warnings.push({
57792
58232
  type: "invalid_content",
57793
58233
  field: fieldPath || "(root)",
57794
- message: `Invalid content${fieldPath ? ` in "${fieldPath}"` : ""}: ${issue4.message}`
58234
+ message: `Invalid content${fieldPath ? ` in "${fieldPath}"` : ""}: ${issue5.message}`
57795
58235
  });
57796
58236
  }
57797
58237
  }
@@ -59227,7 +59667,7 @@ async function handleThemePushForAllScope(params) {
59227
59667
  }
59228
59668
  const validation = themeSchema2.safeParse(localTheme.theme);
59229
59669
  if (!validation.success) {
59230
- 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");
59231
59671
  output.warn(
59232
59672
  `Skipping theme push - invalid theme at content/themes/${themeName}.json:
59233
59673
  ${errors}`
@@ -59893,7 +60333,7 @@ function firstNestedContainerChange(localChanges, remoteChanges) {
59893
60333
  }
59894
60334
  function firstSameFieldConflictPath(localChanges, remoteChanges) {
59895
60335
  const remotePaths = new Set(remoteChanges.keys());
59896
- return [...localChanges.keys()].filter((path25) => remotePaths.has(path25)).sort()[0] ?? null;
60336
+ return [...localChanges.keys()].filter((path27) => remotePaths.has(path27)).sort()[0] ?? null;
59897
60337
  }
59898
60338
  function unsupportedNestedMerge(subject, fieldPath) {
59899
60339
  return {
@@ -59975,37 +60415,37 @@ function valueKind(value) {
59975
60415
  if (typeof value === "object") return "object";
59976
60416
  return "scalar";
59977
60417
  }
59978
- function entryChange(path25, value, containerKind) {
60418
+ function entryChange(path27, value, containerKind) {
59979
60419
  switch (containerKind) {
59980
60420
  case "array":
59981
- if (Array.isArray(value)) return { path: path25, value, containerKind };
60421
+ if (Array.isArray(value)) return { path: path27, value, containerKind };
59982
60422
  break;
59983
60423
  case "object":
59984
60424
  if (value && typeof value === "object" && !Array.isArray(value)) {
59985
- return { path: path25, value, containerKind };
60425
+ return { path: path27, value, containerKind };
59986
60426
  }
59987
60427
  break;
59988
60428
  case "null":
59989
- if (value === null || value === void 0) return { path: path25, value, containerKind };
60429
+ if (value === null || value === void 0) return { path: path27, value, containerKind };
59990
60430
  break;
59991
60431
  case "scalar":
59992
- if (isScalarEntryChangeValue(value)) return { path: path25, value, containerKind };
60432
+ if (isScalarEntryChangeValue(value)) return { path: path27, value, containerKind };
59993
60433
  break;
59994
60434
  default:
59995
60435
  assertNever(containerKind);
59996
60436
  }
59997
- throw new Error(`Invalid entry merge change at ${path25}.`);
60437
+ throw new Error(`Invalid entry merge change at ${path27}.`);
59998
60438
  }
59999
60439
  function isScalarEntryChangeValue(value) {
60000
60440
  return value === void 0 || value === null || ["boolean", "number", "string"].includes(typeof value);
60001
60441
  }
60002
- function expectStringValue(path25, value) {
60442
+ function expectStringValue(path27, value) {
60003
60443
  if (typeof value === "string") return value;
60004
- throw new Error(`Entry merge expected ${path25} to be a string.`);
60444
+ throw new Error(`Entry merge expected ${path27} to be a string.`);
60005
60445
  }
60006
- function expectBooleanValue(path25, value) {
60446
+ function expectBooleanValue(path27, value) {
60007
60447
  if (typeof value === "boolean") return value;
60008
- throw new Error(`Entry merge expected ${path25} to be a boolean.`);
60448
+ throw new Error(`Entry merge expected ${path27} to be a boolean.`);
60009
60449
  }
60010
60450
  function expectStatusValue(value) {
60011
60451
  if (value === "draft" || value === "published") return value;
@@ -60643,6 +61083,19 @@ async function executePushForEnv(output, target, scope, type, identifier, option
60643
61083
  }
60644
61084
  const pushScope = parsedPushScope;
60645
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
+ }
60646
61099
  const deleteOrphanedEnabled = options.deleteOrphaned ?? false;
60647
61100
  let deleteMissingEnabled = options.deleteMissing ?? false;
60648
61101
  if (deleteMissingEnabled) {
@@ -60713,7 +61166,7 @@ ${available.map((t) => ` - ${t.name} (content/themes/${t.name}.json)`).join("\n
60713
61166
  }
60714
61167
  const validation = themeSchema.safeParse(localTheme.theme);
60715
61168
  if (!validation.success) {
60716
- 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");
60717
61170
  output.error(
60718
61171
  `Invalid theme file at content/themes/${themeName}.json:
60719
61172
  ${errors}`
@@ -60901,8 +61354,16 @@ ${errors}`
60901
61354
  });
60902
61355
  return { success: false };
60903
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
+ }
60904
61364
  output.info("Reading local content...");
60905
- const localContent = normalizeLocalContentShape(await readAllContent(contentDir));
61365
+ const rawLocalContent = normalizeLocalContentShape(await readAllContent(contentDir));
61366
+ const localContent = shouldExcludeCanonicalEntries(canonicalEntrySyncDecision) ? stripCanonicalEventEntriesFromLocalContent(rawLocalContent).content : rawLocalContent;
60906
61367
  if (options.mergeRemote) {
60907
61368
  return planAndReportRemoteEntryMerge({
60908
61369
  output,
@@ -60944,7 +61405,7 @@ ${errors}`
60944
61405
  return { success: true };
60945
61406
  }
60946
61407
  output.info("Fetching remote content for comparison...");
60947
- const remoteContent = await client.pull.all();
61408
+ const remoteContent = stripCanonicalEventEntriesFromPulledContent(await client.pull.all()).content;
60948
61409
  if (remoteContent.meta.truncated) {
60949
61410
  output.warn("Warning: Remote content was truncated due to size limits.");
60950
61411
  output.warn(
@@ -61227,7 +61688,7 @@ ${errors}`
61227
61688
  if (metadataFlags.shouldUpdateMetadata && !skipMeta) {
61228
61689
  try {
61229
61690
  output.info("Updating local metadata...");
61230
- const freshRemote = await client.pull.all();
61691
+ const freshRemote = stripCanonicalEventEntriesFromPulledContent(await client.pull.all()).content;
61231
61692
  const entriesForMeta = {};
61232
61693
  if (metadataFlags.willUpdateEntries && freshRemote.meta.entries) {
61233
61694
  for (const [key, meta] of Object.entries(freshRemote.meta.entries)) {
@@ -63006,7 +63467,7 @@ var THEME_FIELD_CATEGORY_MAP = {
63006
63467
  };
63007
63468
 
63008
63469
  // src/cli/init-docs/zod-to-markdown.ts
63009
- function isRecord19(value) {
63470
+ function isRecord20(value) {
63010
63471
  return typeof value === "object" && value !== null && !Array.isArray(value);
63011
63472
  }
63012
63473
  function isZodTypeAny(value) {
@@ -63134,7 +63595,7 @@ function extractLiteralValue(schema) {
63134
63595
  const typeName = getTypeName(schema);
63135
63596
  if (typeName !== ZodTypeName.ZodLiteral) return void 0;
63136
63597
  const def = schema._def;
63137
- if (!isRecord19(def)) return void 0;
63598
+ if (!isRecord20(def)) return void 0;
63138
63599
  return String(def.value);
63139
63600
  }
63140
63601
  function extractSchemaInfo(schema, skipFields = []) {
@@ -63204,7 +63665,7 @@ function extractFieldInfo(name, schema) {
63204
63665
  }
63205
63666
  if (typeName === ZodTypeName.ZodRecord) {
63206
63667
  const def = inner._def;
63207
- const valueSchema = isRecord19(def) ? def.valueType : void 0;
63668
+ const valueSchema = isRecord20(def) ? def.valueType : void 0;
63208
63669
  if (!isZodTypeAny(valueSchema)) {
63209
63670
  info.recordValueType = "unknown";
63210
63671
  return info;
@@ -63219,7 +63680,7 @@ function extractFieldInfo(name, schema) {
63219
63680
  }
63220
63681
  } else if (getTypeName(valueInner) === ZodTypeName.ZodRecord) {
63221
63682
  const nestedDef = valueInner._def;
63222
- const nestedValueSchema = isRecord19(nestedDef) ? nestedDef.valueType : void 0;
63683
+ const nestedValueSchema = isRecord20(nestedDef) ? nestedDef.valueType : void 0;
63223
63684
  if (!isZodTypeAny(nestedValueSchema)) {
63224
63685
  info.recordValueType = "record<string, unknown>";
63225
63686
  return info;
@@ -63230,7 +63691,7 @@ function extractFieldInfo(name, schema) {
63230
63691
  }
63231
63692
  if (typeName === ZodTypeName.ZodUnion || typeName === ZodTypeName.ZodDiscriminatedUnion) {
63232
63693
  const def = inner._def;
63233
- const optionsValue = isRecord19(def) ? def.options : void 0;
63694
+ const optionsValue = isRecord20(def) ? def.options : void 0;
63234
63695
  const options = Array.isArray(optionsValue) ? optionsValue.filter(isZodTypeAny) : [];
63235
63696
  const optionTypes = options.map((opt) => {
63236
63697
  const { inner: optInner } = unwrapSchema(opt);
@@ -64395,7 +64856,7 @@ var SimpleCache = class {
64395
64856
  };
64396
64857
 
64397
64858
  // src/version.ts
64398
- var SDK_VERSION = "0.84.2";
64859
+ var SDK_VERSION = "0.85.0";
64399
64860
 
64400
64861
  // src/client/error.ts
64401
64862
  var RiverbankApiError = class _RiverbankApiError extends Error {
@@ -65339,14 +65800,14 @@ function createRiverbankClient(config2) {
65339
65800
  );
65340
65801
  }
65341
65802
  async function getPageWithResilienceInternal(params) {
65342
- const { siteId, path: path25, preview = false, signal } = params;
65343
- const cacheKey = `page:${siteId}:${path25}:${preview}`;
65803
+ const { siteId, path: path27, preview = false, signal } = params;
65804
+ const cacheKey = `page:${siteId}:${path27}:${preview}`;
65344
65805
  return resilientFetch(
65345
65806
  cacheKey,
65346
65807
  async (sig) => {
65347
65808
  return await apiClient({
65348
65809
  endpoint: "getContentByPath",
65349
- params: { siteId, path: path25, preview: String(preview) },
65810
+ params: { siteId, path: path27, preview: String(preview) },
65350
65811
  options: { signal: sig }
65351
65812
  });
65352
65813
  },
@@ -65354,7 +65815,7 @@ function createRiverbankClient(config2) {
65354
65815
  preview,
65355
65816
  signal,
65356
65817
  // Prebuild fallback only for published pages (not preview)
65357
- prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadPage(siteId, path25) : void 0
65818
+ prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadPage(siteId, path27) : void 0
65358
65819
  }
65359
65820
  );
65360
65821
  }
@@ -65796,17 +66257,17 @@ function createRiverbankClient(config2) {
65796
66257
  };
65797
66258
  },
65798
66259
  async checkRedirect(params) {
65799
- const { siteId, path: path25, signal } = params;
65800
- if (!siteId || !path25) {
66260
+ const { siteId, path: path27, signal } = params;
66261
+ if (!siteId || !path27) {
65801
66262
  throw new Error("checkRedirect() requires siteId and path");
65802
66263
  }
65803
- const cacheKey = `redirect:${siteId}:${path25}`;
66264
+ const cacheKey = `redirect:${siteId}:${path27}`;
65804
66265
  return resilientFetchData(
65805
66266
  cacheKey,
65806
66267
  async (sig) => {
65807
66268
  return await apiClient({
65808
66269
  endpoint: "checkRedirect",
65809
- params: { site: siteId, path: path25 },
66270
+ params: { site: siteId, path: path27 },
65810
66271
  options: { signal: sig }
65811
66272
  });
65812
66273
  },
@@ -65883,13 +66344,13 @@ function pathToFilename(routePath) {
65883
66344
  return routePath.slice(1).replace(/[^a-zA-Z0-9\-\/]/g, "_").replace(/\//g, "-") + ".json";
65884
66345
  }
65885
66346
  function ensureDir4(dirPath) {
65886
- if (!fs10.existsSync(dirPath)) {
65887
- fs10.mkdirSync(dirPath, { recursive: true });
66347
+ if (!fs11.existsSync(dirPath)) {
66348
+ fs11.mkdirSync(dirPath, { recursive: true });
65888
66349
  }
65889
66350
  }
65890
66351
  function writeJsonFile3(filePath, data) {
65891
66352
  const content = JSON.stringify(data, null, 2);
65892
- fs10.writeFileSync(filePath, content, "utf-8");
66353
+ fs11.writeFileSync(filePath, content, "utf-8");
65893
66354
  return Buffer.byteLength(content, "utf-8");
65894
66355
  }
65895
66356
  function calculateChecksum(data) {
@@ -66216,7 +66677,7 @@ async function loadDeployConfig() {
66216
66677
  }
66217
66678
  async function checkWorkingDirectoryClean(git, prebuildOutput) {
66218
66679
  const status = await git.status();
66219
- 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));
66220
66681
  return {
66221
66682
  clean: dirtyFiles.length === 0,
66222
66683
  dirtyFiles
@@ -66487,9 +66948,9 @@ Examples:
66487
66948
  const parseResult = verifyConfigSchema.safeParse(rawConfig);
66488
66949
  if (!parseResult.success) {
66489
66950
  return output.error("Invalid config format", {
66490
- issues: parseResult.error.issues.map((issue4) => ({
66491
- path: issue4.path.join("."),
66492
- message: issue4.message
66951
+ issues: parseResult.error.issues.map((issue5) => ({
66952
+ path: issue5.path.join("."),
66953
+ message: issue5.message
66493
66954
  })),
66494
66955
  suggestion: "Ensure your config exports a valid riverbank config object"
66495
66956
  });
@@ -66747,25 +67208,25 @@ function mapMediaGuardDiagnosticsToAuditIssues(diagnostics) {
66747
67208
  }
66748
67209
  }));
66749
67210
  }
66750
- function extractEmbedReferences(data, path25 = []) {
67211
+ function extractEmbedReferences(data, path27 = []) {
66751
67212
  const refs = [];
66752
67213
  if (!data || typeof data !== "object") return refs;
66753
67214
  if (Array.isArray(data)) {
66754
67215
  data.forEach((item, index) => {
66755
- refs.push(...extractEmbedReferences(item, [...path25, String(index)]));
67216
+ refs.push(...extractEmbedReferences(item, [...path27, String(index)]));
66756
67217
  });
66757
67218
  return refs;
66758
67219
  }
66759
67220
  const obj = data;
66760
67221
  if (obj.kind === "embed" && typeof obj.contentType === "string" && typeof obj.identifier === "string") {
66761
67222
  refs.push({
66762
- path: path25.join("."),
67223
+ path: path27.join("."),
66763
67224
  contentType: obj.contentType,
66764
67225
  identifier: obj.identifier
66765
67226
  });
66766
67227
  }
66767
67228
  for (const [key, value] of Object.entries(obj)) {
66768
- refs.push(...extractEmbedReferences(value, [...path25, key]));
67229
+ refs.push(...extractEmbedReferences(value, [...path27, key]));
66769
67230
  }
66770
67231
  return refs;
66771
67232
  }
@@ -67017,8 +67478,8 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
67017
67478
  client
67018
67479
  });
67019
67480
  const mediaIssues = mapMediaGuardDiagnosticsToAuditIssues(mediaGuardResult.diagnostics);
67020
- errors.push(...mediaIssues.filter((issue4) => issue4.severity === "error"));
67021
- 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"));
67022
67483
  }
67023
67484
  if (!isJsonOutput) {
67024
67485
  output.info("Checking for duplicate page paths...");
@@ -67042,8 +67503,8 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
67042
67503
  }
67043
67504
  errors.push(...auditEventReferences(localContent.events, auditCtx));
67044
67505
  const courseRefIssues = auditCourseReferences(localContent.courses, auditCtx);
67045
- errors.push(...courseRefIssues.filter((issue4) => issue4.severity === "error"));
67046
- 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"));
67047
67508
  const success = errors.length === 0;
67048
67509
  const result = { success, errors, warnings };
67049
67510
  if (isJsonOutput) {
@@ -67058,14 +67519,14 @@ async function executeAuditForEnv(output, target, options, isJsonOutput) {
67058
67519
  output.info("");
67059
67520
  if (errors.length > 0) {
67060
67521
  output.warn(`Found ${errors.length} error(s):`);
67061
- for (const issue4 of errors) {
67062
- output.info(` [ERROR] ${issue4.message}`);
67522
+ for (const issue5 of errors) {
67523
+ output.info(` [ERROR] ${issue5.message}`);
67063
67524
  }
67064
67525
  }
67065
67526
  if (warnings.length > 0) {
67066
67527
  output.warn(`Found ${warnings.length} warning(s):`);
67067
- for (const issue4 of warnings) {
67068
- output.info(` [WARN] ${issue4.message}`);
67528
+ for (const issue5 of warnings) {
67529
+ output.info(` [WARN] ${issue5.message}`);
67069
67530
  }
67070
67531
  }
67071
67532
  if (success && warnings.length === 0) {
@@ -67699,7 +68160,7 @@ function formatThemeSummaryForPrompt(summary) {
67699
68160
  }
67700
68161
 
67701
68162
  // src/manifest/validation/layout-utils.ts
67702
- function collectLayoutNodeInfos(node, path25 = "layout", out = []) {
68163
+ function collectLayoutNodeInfos(node, path27 = "layout", out = []) {
67703
68164
  if (!node || typeof node !== "object") return out;
67704
68165
  const n = node;
67705
68166
  const type = typeof n.type === "string" ? n.type : "unknown";
@@ -67708,10 +68169,10 @@ function collectLayoutNodeInfos(node, path25 = "layout", out = []) {
67708
68169
  const b = n.$bind;
67709
68170
  if (typeof b.from === "string") bindFrom = b.from;
67710
68171
  }
67711
- out.push({ path: path25, type, bindFrom });
68172
+ out.push({ path: path27, type, bindFrom });
67712
68173
  if (Array.isArray(n.children)) {
67713
68174
  for (let i = 0; i < n.children.length; i++) {
67714
- collectLayoutNodeInfos(n.children[i], `${path25}.children[${i}]`, out);
68175
+ collectLayoutNodeInfos(n.children[i], `${path27}.children[${i}]`, out);
67715
68176
  }
67716
68177
  }
67717
68178
  return out;
@@ -68133,7 +68594,7 @@ function extractNestedHrefBindFromProps(props2) {
68133
68594
  const bind2 = href.$bind;
68134
68595
  return bind2 && typeof bind2 === "object" ? bind2 : null;
68135
68596
  }
68136
- function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatStack = []) {
68597
+ function findMissingLinkHrefs(node, blockId, fields3, path27 = "layout", repeatStack = []) {
68137
68598
  const errors = [];
68138
68599
  if (!node || typeof node !== "object") return errors;
68139
68600
  const n = node;
@@ -68162,21 +68623,21 @@ function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatS
68162
68623
  if (isBoundToLinkField) {
68163
68624
  if (!hrefBind || !hrefFrom) {
68164
68625
  errors.push({
68165
- path: path25,
68166
- message: `Block "${blockId}": ${nodeType} node at ${path25} is bound to a link field but is missing props.href binding`,
68626
+ path: path27,
68627
+ message: `Block "${blockId}": ${nodeType} node at ${path27} is bound to a link field but is missing props.href binding`,
68167
68628
  suggestion: `Add props.href: { "$bind": { "from": "${bindFrom ?? "content.yourLinkField"}", "fallback": null, "transforms": [{ "id": "links.resolve" }] } }`
68168
68629
  });
68169
68630
  } else if (!bindingHasTransform(hrefBind, "links.resolve")) {
68170
68631
  errors.push({
68171
- path: path25,
68172
- 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"}]`,
68173
68634
  suggestion: `Set props.href.$bind.transforms to [{ "id": "links.resolve" }].`
68174
68635
  });
68175
68636
  }
68176
68637
  if (bindFrom && bindFieldType === "link" && !bindingHasTransform(bind2, "links.label")) {
68177
68638
  errors.push({
68178
- path: path25,
68179
- message: `Block "${blockId}": ${nodeType} node at ${path25} binds label from a link field but is missing links.label transform`,
68639
+ path: path27,
68640
+ message: `Block "${blockId}": ${nodeType} node at ${path27} binds label from a link field but is missing links.label transform`,
68180
68641
  suggestion: `Set node.$bind.transforms to [{ "id": "links.label" }] so the label renders as text.`
68181
68642
  });
68182
68643
  }
@@ -68189,7 +68650,7 @@ function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatS
68189
68650
  n.children[i],
68190
68651
  blockId,
68191
68652
  fields3,
68192
- `${path25}.children[${i}]`,
68653
+ `${path27}.children[${i}]`,
68193
68654
  nextRepeatStack
68194
68655
  )
68195
68656
  );
@@ -68197,7 +68658,7 @@ function findMissingLinkHrefs(node, blockId, fields3, path25 = "layout", repeatS
68197
68658
  }
68198
68659
  return errors;
68199
68660
  }
68200
- function detectRedundantLinkLabels(node, blockId, fields3, path25 = "layout", repeatStack = []) {
68661
+ function detectRedundantLinkLabels(node, blockId, fields3, path27 = "layout", repeatStack = []) {
68201
68662
  const errors = [];
68202
68663
  if (!node || typeof node !== "object") return errors;
68203
68664
  const n = node;
@@ -68219,7 +68680,7 @@ function detectRedundantLinkLabels(node, blockId, fields3, path25 = "layout", re
68219
68680
  const redundancies = findRedundantLinkTextSiblings(
68220
68681
  children,
68221
68682
  nextRepeatStack,
68222
- path25
68683
+ path27
68223
68684
  );
68224
68685
  errors.push(
68225
68686
  ...redundancies.map((r) => ({
@@ -68236,7 +68697,7 @@ function detectRedundantLinkLabels(node, blockId, fields3, path25 = "layout", re
68236
68697
  n.children[i],
68237
68698
  blockId,
68238
68699
  fields3,
68239
- `${path25}.children[${i}]`,
68700
+ `${path27}.children[${i}]`,
68240
68701
  nextRepeatStack
68241
68702
  )
68242
68703
  );
@@ -68475,19 +68936,19 @@ function extractBlockIdFromSelector(selector) {
68475
68936
  const match = selector.match(/\[data-block=(["'])(custom\.[^"']+)\1\]/);
68476
68937
  return match?.[2] ?? null;
68477
68938
  }
68478
- function validateNodeType(nodeType, path25, ctx) {
68939
+ function validateNodeType(nodeType, path27, ctx) {
68479
68940
  if (!ALLOWED_NODE_TYPES.includes(
68480
68941
  nodeType
68481
68942
  )) {
68482
68943
  return {
68483
- path: `${path25}.type`,
68484
- 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}`,
68485
68946
  suggestion: `ALLOWED: ${ALLOWED_NODE_TYPES.slice(0, 10).join(", ")}... FIX: Replace "${nodeType}" with a valid node type.`
68486
68947
  };
68487
68948
  }
68488
68949
  return null;
68489
68950
  }
68490
- function validateTransforms(transforms, path25, ctx) {
68951
+ function validateTransforms(transforms, path27, ctx) {
68491
68952
  const errors = [];
68492
68953
  for (let i = 0; i < transforms.length; i++) {
68493
68954
  const transform = transforms[i];
@@ -68496,7 +68957,7 @@ function validateTransforms(transforms, path25, ctx) {
68496
68957
  transform.id
68497
68958
  )) {
68498
68959
  errors.push({
68499
- path: `${path25}.transforms[${i}].id`,
68960
+ path: `${path27}.transforms[${i}].id`,
68500
68961
  message: `Block "${ctx.blockId}": Unknown transform "${transform.id}"`,
68501
68962
  suggestion: `ALLOWED: ${ALLOWED_TRANSFORM_IDS.slice(0, 8).join(", ")}... FIX: Replace with a valid transform ID or remove.`
68502
68963
  });
@@ -68505,7 +68966,7 @@ function validateTransforms(transforms, path25, ctx) {
68505
68966
  }
68506
68967
  return errors;
68507
68968
  }
68508
- function validateBinding(bind2, path25, ctx) {
68969
+ function validateBinding(bind2, path27, ctx) {
68509
68970
  const errors = [];
68510
68971
  if ("from" in bind2 && typeof bind2.from === "string") {
68511
68972
  const bindPath = bind2.from;
@@ -68513,7 +68974,7 @@ function validateBinding(bind2, path25, ctx) {
68513
68974
  const fieldId = bindPath.replace("content.", "").split(".")[0] ?? "";
68514
68975
  if (fieldId && !ctx.fieldIds.has(fieldId)) {
68515
68976
  errors.push({
68516
- path: `${path25}.from`,
68977
+ path: `${path27}.from`,
68517
68978
  message: `Block "${ctx.blockId}": $bind references unknown field "${fieldId}"`,
68518
68979
  suggestion: `DEFINED FIELDS: ${Array.from(ctx.fieldIds).join(", ")}. FIX: Add field { id: '${fieldId}', type: '...' } or use existing field.`
68519
68980
  });
@@ -68521,31 +68982,31 @@ function validateBinding(bind2, path25, ctx) {
68521
68982
  }
68522
68983
  }
68523
68984
  if ("transforms" in bind2 && Array.isArray(bind2.transforms)) {
68524
- errors.push(...validateTransforms(bind2.transforms, path25, ctx));
68985
+ errors.push(...validateTransforms(bind2.transforms, path27, ctx));
68525
68986
  }
68526
68987
  return errors;
68527
68988
  }
68528
- function validateLayoutDeep(node, blockId, fields3, path25 = "layout") {
68989
+ function validateLayoutDeep(node, blockId, fields3, path27 = "layout") {
68529
68990
  const ctx = {
68530
68991
  blockId,
68531
68992
  fieldIds: collectFieldIds(fields3)
68532
68993
  };
68533
- return validateLayoutNode(node, path25, ctx);
68994
+ return validateLayoutNode(node, path27, ctx);
68534
68995
  }
68535
- function validateLayoutNode(node, path25, ctx) {
68996
+ function validateLayoutNode(node, path27, ctx) {
68536
68997
  const errors = [];
68537
68998
  if (!node || typeof node !== "object") {
68538
68999
  return errors;
68539
69000
  }
68540
69001
  const n = node;
68541
69002
  if ("type" in n && typeof n.type === "string") {
68542
- const typeError = validateNodeType(n.type, path25, ctx);
69003
+ const typeError = validateNodeType(n.type, path27, ctx);
68543
69004
  if (typeError) errors.push(typeError);
68544
69005
  }
68545
69006
  if ("$bind" in n && n.$bind && typeof n.$bind === "object") {
68546
69007
  const bindErrors = validateBinding(
68547
69008
  n.$bind,
68548
- `${path25}.$bind`,
69009
+ `${path27}.$bind`,
68549
69010
  ctx
68550
69011
  );
68551
69012
  errors.push(...bindErrors);
@@ -68553,7 +69014,7 @@ function validateLayoutNode(node, path25, ctx) {
68553
69014
  if ("props" in n && n.props && typeof n.props === "object") {
68554
69015
  const propsErrors = validatePropsBindings(
68555
69016
  n.props,
68556
- `${path25}.props`,
69017
+ `${path27}.props`,
68557
69018
  ctx
68558
69019
  );
68559
69020
  errors.push(...propsErrors);
@@ -68562,7 +69023,7 @@ function validateLayoutNode(node, path25, ctx) {
68562
69023
  for (let i = 0; i < n.children.length; i++) {
68563
69024
  const childErrors = validateLayoutNode(
68564
69025
  n.children[i],
68565
- `${path25}.children[${i}]`,
69026
+ `${path27}.children[${i}]`,
68566
69027
  ctx
68567
69028
  );
68568
69029
  errors.push(...childErrors);
@@ -68570,17 +69031,17 @@ function validateLayoutNode(node, path25, ctx) {
68570
69031
  }
68571
69032
  return errors;
68572
69033
  }
68573
- function validatePropsBindings(props2, path25, ctx) {
69034
+ function validatePropsBindings(props2, path27, ctx) {
68574
69035
  const errors = [];
68575
69036
  for (const [key, value] of Object.entries(props2)) {
68576
69037
  if (value && typeof value === "object" && "$bind" in value) {
68577
69038
  const bind2 = value.$bind;
68578
- const bindErrors = validateBinding(bind2, `${path25}.${key}.$bind`, ctx);
69039
+ const bindErrors = validateBinding(bind2, `${path27}.${key}.$bind`, ctx);
68579
69040
  errors.push(...bindErrors);
68580
69041
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
68581
69042
  const nestedErrors = validatePropsBindings(
68582
69043
  value,
68583
- `${path25}.${key}`,
69044
+ `${path27}.${key}`,
68584
69045
  ctx
68585
69046
  );
68586
69047
  errors.push(...nestedErrors);
@@ -68713,7 +69174,7 @@ function collectUsedFieldRefs(node) {
68713
69174
  visit(node, []);
68714
69175
  return { topLevel, nestedByRepeater, itemNameByRepeater };
68715
69176
  }
68716
- function findMissingBindings(node, blockId, path25 = "layout") {
69177
+ function findMissingBindings(node, blockId, path27 = "layout") {
68717
69178
  const errors = [];
68718
69179
  if (!node || typeof node !== "object") {
68719
69180
  return errors;
@@ -68723,15 +69184,15 @@ function findMissingBindings(node, blockId, path25 = "layout") {
68723
69184
  if ("$repeat" in n && n.$repeat && typeof n.$repeat === "object") {
68724
69185
  if (nodeType && CONTENT_NODE_TYPES.includes(nodeType)) {
68725
69186
  errors.push({
68726
- path: path25,
68727
- 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`,
68728
69189
  suggestion: `Move $repeat to a container node (grid/stack/div) and put a ${nodeType} child inside with $bind.from like "item.field".`
68729
69190
  });
68730
69191
  }
68731
69192
  if (!Array.isArray(n.children) || n.children.length === 0) {
68732
69193
  errors.push({
68733
- path: path25,
68734
- 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`,
68735
69196
  suggestion: 'Add one or more child nodes under children[] that bind to the repeat item (e.g., $bind.from: "item.text").'
68736
69197
  });
68737
69198
  }
@@ -68740,15 +69201,15 @@ function findMissingBindings(node, blockId, path25 = "layout") {
68740
69201
  const hasBind = "$bind" in n && n.$bind && typeof n.$bind === "object" && "from" in n.$bind;
68741
69202
  if (Array.isArray(n.children) && n.children.length > 0) {
68742
69203
  errors.push({
68743
- path: path25,
68744
- 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`,
68745
69206
  suggestion: `Replace this ${nodeType} with a container node (div/stack/inline) and put the ${nodeType} nodes inside it.`
68746
69207
  });
68747
69208
  }
68748
69209
  if (!hasBind) {
68749
69210
  errors.push({
68750
- path: `${path25}`,
68751
- 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`,
68752
69213
  suggestion: `Add $bind: { from: "content.fieldName" } to connect this ${nodeType} to a field. Example: { "type": "${nodeType}", "$bind": { "from": "content.headline" } }`
68753
69214
  });
68754
69215
  }
@@ -68758,7 +69219,7 @@ function findMissingBindings(node, blockId, path25 = "layout") {
68758
69219
  const childErrors = findMissingBindings(
68759
69220
  n.children[i],
68760
69221
  blockId,
68761
- `${path25}.children[${i}]`
69222
+ `${path27}.children[${i}]`
68762
69223
  );
68763
69224
  errors.push(...childErrors);
68764
69225
  }
@@ -68775,13 +69236,13 @@ function getMaxDepth(node, currentDepth = 0) {
68775
69236
  );
68776
69237
  }
68777
69238
  var CONTAINER_NODE_TYPES = ["section", "stack", "grid", "div", "inline"];
68778
- function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path25 = "layout") {
69239
+ function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path27 = "layout") {
68779
69240
  if (!node || typeof node !== "object") return [];
68780
69241
  const n = node;
68781
69242
  const truncatedPaths = [];
68782
69243
  if (currentDepth === maxAllowedDepth && n.children === null) {
68783
69244
  if (CONTAINER_NODE_TYPES.includes(n.type || "")) {
68784
- truncatedPaths.push(`${path25} (${n.type ?? "node"} at depth ${currentDepth})`);
69245
+ truncatedPaths.push(`${path27} (${n.type ?? "node"} at depth ${currentDepth})`);
68785
69246
  }
68786
69247
  }
68787
69248
  if (n.children && Array.isArray(n.children)) {
@@ -68791,7 +69252,7 @@ function detectPotentialTruncation(node, maxAllowedDepth, currentDepth = 0, path
68791
69252
  child,
68792
69253
  maxAllowedDepth,
68793
69254
  currentDepth + 1,
68794
- `${path25}.children[${i}]`
69255
+ `${path27}.children[${i}]`
68795
69256
  )
68796
69257
  );
68797
69258
  });
@@ -68811,8 +69272,8 @@ function formatValidationFeedback(errors, output) {
68811
69272
  `The layout reached the maximum depth of ${MAX_LAYOUT_DEPTH} levels.`
68812
69273
  );
68813
69274
  lines.push("These container nodes at the depth limit have no children:");
68814
- for (const path25 of truncatedPaths) {
68815
- lines.push(` \u26A0\uFE0F ${path25}`);
69275
+ for (const path27 of truncatedPaths) {
69276
+ lines.push(` \u26A0\uFE0F ${path27}`);
68816
69277
  }
68817
69278
  lines.push("");
68818
69279
  lines.push(
@@ -69274,11 +69735,11 @@ var pass3bOutputSchema = z.object({
69274
69735
  customCssAtRules: z.array(llmMediaAtRuleSchema).nullable(),
69275
69736
  rationale: z.string()
69276
69737
  });
69277
- function getNodeAtPath(layout, path25) {
69278
- if (path25 === "" || path25 === "root" || path25 === "layout") {
69738
+ function getNodeAtPath(layout, path27) {
69739
+ if (path27 === "" || path27 === "root" || path27 === "layout") {
69279
69740
  return layout;
69280
69741
  }
69281
- let normalizedPath = path25;
69742
+ let normalizedPath = path27;
69282
69743
  if (normalizedPath.startsWith("layout.")) {
69283
69744
  normalizedPath = normalizedPath.slice(7);
69284
69745
  }
@@ -70976,6 +71437,26 @@ var eventPricingInputSchema = z.unknown().superRefine((pricing, ctx) => {
70976
71437
  }
70977
71438
  return result.pricing;
70978
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
+ });
70979
71460
  var eventUpsertInputSchema = z.object({
70980
71461
  identifier: z.string().min(1).optional(),
70981
71462
  title: z.string().min(1, "title is required"),
@@ -70985,6 +71466,7 @@ var eventUpsertInputSchema = z.object({
70985
71466
  schedule: eventScheduleInputSchema,
70986
71467
  capacity: z.number().int().positive().nullable().optional(),
70987
71468
  pricing: eventPricingInputSchema.optional(),
71469
+ paymentTerms: eventPaymentTermsInputSchema.optional(),
70988
71470
  venueRef: z.string().nullable().optional(),
70989
71471
  categoryRef: z.string().nullable().optional(),
70990
71472
  content: z.record(z.string(), z.unknown()).optional(),
@@ -71068,6 +71550,7 @@ var getCommand5 = createGetCommand({
71068
71550
  schedule: event.schedule,
71069
71551
  capacity: event.capacity,
71070
71552
  pricing: event.pricing,
71553
+ paymentTerms: event.paymentTerms,
71071
71554
  venueRef: event.venueRef,
71072
71555
  categoryRef: event.categoryRef,
71073
71556
  formRef: event.formRef,
@@ -71462,8 +71945,485 @@ async function migrateEntries(options) {
71462
71945
  legacyTitlesMigratedToDataTitle
71463
71946
  };
71464
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
+ }
71465
72372
 
71466
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
+ }
71467
72427
  var migrateCommand = new Command("migrate").description("Migrate local SDK content formats").addCommand(
71468
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(
71469
72429
  "after",
@@ -71494,6 +72454,13 @@ Examples:
71494
72454
  try {
71495
72455
  const cliConfig = await loadCliConfig();
71496
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
+ }
71497
72464
  const confirmed = await confirmAction(
71498
72465
  options.dryRun ? "Preview entry migrations?" : "Migrate local entries to the new file format?",
71499
72466
  { yes: options.yes },
@@ -71530,6 +72497,86 @@ Examples:
71530
72497
  handleCommandError(error, output, { target: "local" });
71531
72498
  }
71532
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
+ })
71533
72580
  );
71534
72581
 
71535
72582
  // src/cli/commands/style.ts