@riverbankcms/sdk 0.78.0 → 0.78.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +45 -43
  2. package/dist/{PreviewEditorSidebar-RIKFQ72L.mjs → PreviewEditorSidebar-4DXLYX2V.mjs} +29 -21
  3. package/dist/{PreviewEditorUI-XO7TUWKK.mjs → PreviewEditorUI-CS5P4N3P.mjs} +4 -4
  4. package/dist/SdkPreviewModeRuntime-IJDHTW4W.mjs +8 -0
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +36 -0
  6. package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
  7. package/dist/_dts/api/src/endpoints.d.ts +9 -0
  8. package/dist/_dts/api/src/index.d.ts +3 -3
  9. package/dist/_dts/api/src/public/types.d.ts +1 -1
  10. package/dist/_dts/api/src/request.d.ts +3 -11
  11. package/dist/_dts/api/src/sdkConfig/contracts.d.ts +1 -0
  12. package/dist/_dts/api/src/sdkContracts.d.ts +7 -1
  13. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +10 -0
  14. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +1 -0
  15. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +15 -19
  16. package/dist/_dts/api/src/types.d.ts +11 -26
  17. package/dist/_dts/block-form/src/fields/types.d.ts +6 -0
  18. package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterList.d.ts +3 -2
  19. package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterRow.d.ts +6 -3
  20. package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterRowActions.d.ts +8 -3
  21. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/index.d.ts +1 -1
  22. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/useLinearRepeaterDnd.d.ts +1 -0
  23. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/useRepeaterPointerDragCapability.d.ts +1 -0
  24. package/dist/_dts/block-form/src/widgets/RepeaterField/hooks/useResolvedItemLabel.d.ts +7 -0
  25. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/buildSummary.d.ts +1 -0
  26. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/index.d.ts +3 -1
  27. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/repeaterDndDomain.d.ts +1 -1
  28. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/repeaterLabelSource.d.ts +15 -0
  29. package/dist/_dts/block-form/src/widgets/RepeaterField/utils/repeaterRowActionsDomain.d.ts +50 -0
  30. package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +591 -0
  31. package/dist/_dts/blocks/src/system/blocks/blog-listing.d.ts +591 -0
  32. package/dist/_dts/blocks/src/system/blocks/cart.d.ts +591 -0
  33. package/dist/_dts/blocks/src/system/blocks/checkout.d.ts +591 -0
  34. package/dist/_dts/blocks/src/system/blocks/collection.d.ts +591 -0
  35. package/dist/_dts/blocks/src/system/blocks/faq.d.ts +591 -0
  36. package/dist/_dts/blocks/src/system/blocks/gifting.d.ts +591 -0
  37. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -0
  38. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -0
  39. package/dist/_dts/blocks/src/system/blocks/product-detail.d.ts +591 -0
  40. package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +591 -0
  41. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +591 -0
  42. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +3 -0
  43. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +164 -0
  44. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.d.ts +1 -1
  45. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +1 -1
  46. package/dist/_dts/content-editor/src/index.d.ts +1 -1
  47. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +2 -2
  48. package/dist/_dts/content-model/src/content-types/schema.d.ts +14 -0
  49. package/dist/_dts/content-model/src/templates/bindingTypeCompatibility.d.ts +3 -1
  50. package/dist/_dts/content-model/src/templates/bindingValidation.d.ts +10 -4
  51. package/dist/_dts/content-model/src/templates/fieldPaths.d.ts +20 -0
  52. package/dist/_dts/content-model/src/templates/manifestAdapter.d.ts +5 -2
  53. package/dist/_dts/core/src/branded.d.ts +108 -85
  54. package/dist/_dts/core/src/csv-types.d.ts +2 -2
  55. package/dist/_dts/core/src/editor-state.d.ts +7 -7
  56. package/dist/_dts/core/src/participants.d.ts +2 -2
  57. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +11 -0
  58. package/dist/_dts/editor-blocks/src/blockPayload.d.ts +1 -1
  59. package/dist/_dts/media-editor/src/MediaEditor.d.ts +3 -1
  60. package/dist/_dts/media-editor/src/MediaPreview.d.ts +3 -1
  61. package/dist/_dts/media-editor/src/fieldUi.d.ts +5 -0
  62. package/dist/_dts/media-editor/src/index.d.ts +1 -1
  63. package/dist/_dts/sdk/src/cli/commands/push/consts.d.ts +1 -1
  64. package/dist/_dts/sdk/src/cli/commands/push/metadata.d.ts +2 -0
  65. package/dist/_dts/sdk/src/cli/commands/push/stale.d.ts +3 -3
  66. package/dist/_dts/sdk/src/cli/commands/push-execute.d.ts +7 -0
  67. package/dist/_dts/sdk/src/cli/commands/push.d.ts +2 -0
  68. package/dist/_dts/sdk/src/cli/content/reader.d.ts +13 -0
  69. package/dist/_dts/sdk/src/cli/content/writer.d.ts +2 -1
  70. package/dist/_dts/sdk/src/cli/helpers.d.ts +2 -0
  71. package/dist/_dts/sdk/src/cli/site-commands/commandKeys.d.ts +6 -6
  72. package/dist/_dts/sdk/src/cli/site-commands/commandRuntime.d.ts +5 -0
  73. package/dist/_dts/sdk/src/cli/site-commands/commandSurfaceDispatch.d.ts +4 -0
  74. package/dist/_dts/sdk/src/cli/site-commands/pageCommands.d.ts +5 -2
  75. package/dist/_dts/sdk/src/cli/site-commands/pushExecution.d.ts +10 -1
  76. package/dist/_dts/sdk/src/cli/site-commands/pushExecutionTypes.d.ts +1 -1
  77. package/dist/_dts/sdk/src/client/management/types.d.ts +6 -0
  78. package/dist/_dts/sdk/src/client/types.d.ts +2 -2
  79. package/dist/_dts/sdk/src/config/content-types.d.ts +7 -0
  80. package/dist/_dts/sdk/src/config/field-definitions.d.ts +2 -0
  81. package/dist/_dts/sdk/src/version.d.ts +1 -1
  82. package/dist/_dts/site-commands/src/commands.d.ts +3 -0
  83. package/dist/{altcha-B5XGSXP5.mjs → altcha-EKUEQ4RP.mjs} +1 -1
  84. package/dist/{chunk-NIDXI46P.mjs → chunk-4QEGTLK6.mjs} +1 -1
  85. package/dist/{chunk-TXDES5P2.mjs → chunk-6HYXHRAI.mjs} +5 -5
  86. package/dist/{chunk-SVMMM2NA.mjs → chunk-CR5HKAGU.mjs} +24 -5
  87. package/dist/{chunk-OECWLDHN.mjs → chunk-MCRQMPET.mjs} +1030 -588
  88. package/dist/{chunk-SXOLGNMX.mjs → chunk-OKMBEAXY.mjs} +1 -1
  89. package/dist/{chunk-XGB3TDIC.mjs → chunk-R7POPVJR.mjs} +2 -8
  90. package/dist/{chunk-F7RTCZYN.mjs → chunk-RGTOD4AJ.mjs} +20 -14
  91. package/dist/cli/index.mjs +681 -225
  92. package/dist/cli/init-docs/content/cli-reference.md +3 -2
  93. package/dist/cli/init-docs/content/content-management.md +2 -2
  94. package/dist/cli/init-docs/content/workflow-preview-mode.md +68 -2
  95. package/dist/client/{accordion-EVDEOUPR.mjs → accordion-PLYNJIIM.mjs} +2 -2
  96. package/dist/client/analytics.mjs +1 -1
  97. package/dist/client/{bookingForm-DIHBLC64.mjs → bookingForm-BXAP6AO7.mjs} +55 -48
  98. package/dist/client/bookings.mjs +62 -55
  99. package/dist/client/{carousel-FEBQHIWI.mjs → carousel-TRBXDHGF.mjs} +3 -3
  100. package/dist/client/{cart-7CKSXAE4.mjs → cart-Z7H3HJRS.mjs} +7 -7
  101. package/dist/client/{checkout-WKYCANLV.mjs → checkout-WAFCUBIX.mjs} +7 -7
  102. package/dist/client/{chunk-OFMSCGNY.mjs → chunk-75OUS5MT.mjs} +2 -2
  103. package/dist/client/{chunk-IVNCUVAV.mjs → chunk-AUJ5DBZJ.mjs} +18 -18
  104. package/dist/client/{chunk-36WJCERQ.mjs → chunk-CE7IBGVW.mjs} +3 -1
  105. package/dist/client/{chunk-RZDWX7QW.mjs → chunk-CWGTG37I.mjs} +1 -1
  106. package/dist/client/{chunk-YDSEG6GZ.mjs → chunk-DNRGY432.mjs} +2 -2
  107. package/dist/client/{chunk-RV6FX7UH.mjs → chunk-FUXW6VW2.mjs} +9 -9
  108. package/dist/client/{chunk-65F47D7Y.mjs → chunk-JGXPTEI2.mjs} +43 -36
  109. package/dist/client/{chunk-GUK2FPXQ.mjs → chunk-JRDUHZCT.mjs} +37 -15
  110. package/dist/client/{chunk-VPPMNXCF.mjs → chunk-UVQEJJTN.mjs} +2 -2
  111. package/dist/client/{chunk-F7LHOKEH.mjs → chunk-XSV6KW4D.mjs} +1 -1
  112. package/dist/client/{chunk-PD6NBCEY.mjs → chunk-ZFHRN6W2.mjs} +1 -1
  113. package/dist/client/{chunk-2SAVKN2M.mjs → chunk-ZI3LLBPZ.mjs} +2 -2
  114. package/dist/client/client.mjs +249 -160
  115. package/dist/client/{courseRegistration-5QF2PHKM.mjs → courseRegistration-AHFQHWIJ.mjs} +10 -10
  116. package/dist/client/{eventCalendar-4ZOSETDU.mjs → eventCalendar-LDXTV5R7.mjs} +9 -9
  117. package/dist/client/{eventCombined-WQGU7JUX.mjs → eventCombined-A4JGTNJO.mjs} +9 -9
  118. package/dist/client/{eventDetails-AYWVUJ5Y.mjs → eventDetails-4YXTZ7EG.mjs} +9 -9
  119. package/dist/client/{eventListing-NT7C6UT5.mjs → eventListing-P72TPFFM.mjs} +9 -9
  120. package/dist/client/{eventRegistration-OH24F4ZJ.mjs → eventRegistration-LSYJHGMT.mjs} +9 -9
  121. package/dist/client/{form-7L42SRBB.mjs → form-AOPYOKOW.mjs} +6 -3
  122. package/dist/client/{headerSection-OZRZNZ52.mjs → headerSection-5TFYDFVQ.mjs} +3 -3
  123. package/dist/client/hooks.mjs +78 -48
  124. package/dist/client/{locationMap-ZBXRPQ7C.mjs → locationMap-QSZ3ZVAZ.mjs} +3 -3
  125. package/dist/client/{newsletterForm-SNAGFF2I.mjs → newsletterForm-KTRHZY52.mjs} +2 -2
  126. package/dist/client/{productDetail-I46BOFGV.mjs → productDetail-N4E775RG.mjs} +7 -7
  127. package/dist/client/{productList-BOYHTYI6.mjs → productList-UGUQ2S45.mjs} +7 -7
  128. package/dist/client/rendering/client.mjs +173 -131
  129. package/dist/client/rendering/islands.mjs +19 -19
  130. package/dist/client/rendering.mjs +230 -150
  131. package/dist/client/{shop-XTXPZTKR.mjs → shop-VHSZEEQ2.mjs} +7 -7
  132. package/dist/preview-next/before-render.mjs +10 -1
  133. package/dist/preview-next/client/runtime.mjs +6 -6
  134. package/dist/preview-next/middleware.mjs +10 -1
  135. package/dist/preview-next/tailwind-sources.css +1 -0
  136. package/dist/sdk-runtime-WHPJEF5G.mjs +8 -0
  137. package/dist/server/components.mjs +101 -54
  138. package/dist/server/config-template-validation.mjs +221 -15
  139. package/dist/server/config-validation.mjs +76 -42
  140. package/dist/server/config.mjs +76 -42
  141. package/dist/server/data.mjs +77 -47
  142. package/dist/server/index.mjs +31 -10
  143. package/dist/server/next.mjs +133 -71
  144. package/dist/server/page-converter.mjs +60 -40
  145. package/dist/server/prebuild.mjs +1 -1
  146. package/dist/server/rendering/server.mjs +107 -60
  147. package/dist/server/rendering.mjs +111 -61
  148. package/dist/server/routing.mjs +93 -63
  149. package/dist/server/server.mjs +102 -57
  150. package/package.json +1 -1
  151. package/dist/SdkPreviewModeRuntime-LAGYMPNF.mjs +0 -8
  152. package/dist/sdk-runtime-ZJLKC6DR.mjs +0 -8
@@ -30,14 +30,42 @@ var __export = (target, all) => {
30
30
  __defProp(target, name, { get: all[name], enumerable: true });
31
31
  };
32
32
 
33
+ // ../core/src/result.ts
34
+ function ok(value) {
35
+ return { ok: true, value };
36
+ }
37
+ function err(error) {
38
+ return { ok: false, error };
39
+ }
40
+ var init_result = __esm({
41
+ "../core/src/result.ts"() {
42
+ }
43
+ });
44
+
33
45
  // ../core/src/branded.ts
34
- var asSiteId, asStorageBucketName, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds;
46
+ function parseUuidBrand(value, unsafeConstructor) {
47
+ if (typeof value !== "string") {
48
+ return err({ kind: "not_string" });
49
+ }
50
+ const normalized = value.trim().toLowerCase();
51
+ if (normalized.length === 0) {
52
+ return err({ kind: "empty_string" });
53
+ }
54
+ if (!UUID_PATTERN.test(normalized)) {
55
+ return err({ kind: "invalid_uuid" });
56
+ }
57
+ return ok(unsafeConstructor(normalized));
58
+ }
59
+ var UUID_PATTERN, unsafeAsSiteId, unsafeAsStorageBucketName, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, parseSiteId;
35
60
  var init_branded = __esm({
36
61
  "../core/src/branded.ts"() {
37
- asSiteId = (id) => id;
38
- asStorageBucketName = (value) => value;
62
+ init_result();
63
+ UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
64
+ unsafeAsSiteId = (id) => id;
65
+ unsafeAsStorageBucketName = (value) => value;
39
66
  unsafeAsPositiveByteCount = (value) => value;
40
67
  unsafeAsPositiveSeconds = (value) => value;
68
+ parseSiteId = (value) => parseUuidBrand(value, unsafeAsSiteId);
41
69
  }
42
70
  });
43
71
 
@@ -111,18 +139,6 @@ var init_booking_instalments = __esm({
111
139
  }
112
140
  });
113
141
 
114
- // ../core/src/result.ts
115
- function ok(value) {
116
- return { ok: true, value };
117
- }
118
- function err(error) {
119
- return { ok: false, error };
120
- }
121
- var init_result = __esm({
122
- "../core/src/result.ts"() {
123
- }
124
- });
125
-
126
142
  // ../core/src/booking-date-time.ts
127
143
  var init_booking_date_time = __esm({
128
144
  "../core/src/booking-date-time.ts"() {
@@ -449,15 +465,15 @@ var init_fileStorage = __esm({
449
465
  "../media-core/src/fileStorage.ts"() {
450
466
  init_src();
451
467
  FILE_STORAGE_BUCKETS = {
452
- publicSite: asStorageBucketName("media"),
453
- privateSite: asStorageBucketName("site-files-private"),
454
- temporary: asStorageBucketName("temp-uploads")
468
+ publicSite: unsafeAsStorageBucketName("media"),
469
+ privateSite: unsafeAsStorageBucketName("site-files-private"),
470
+ temporary: unsafeAsStorageBucketName("temp-uploads")
455
471
  };
456
472
  [
457
473
  FILE_STORAGE_BUCKETS.publicSite,
458
474
  // Existing site logo and font uploads predate the unified file buckets.
459
- asStorageBucketName("site-assets"),
460
- asStorageBucketName("site-fonts")
475
+ unsafeAsStorageBucketName("site-assets"),
476
+ unsafeAsStorageBucketName("site-fonts")
461
477
  ];
462
478
  PRIVATE_SITE_FILE_BUCKET_MIME_TYPES = [
463
479
  "application/pdf",
@@ -851,14 +867,14 @@ function rotateNormalizedPoint(point, rotation) {
851
867
  const x = point.x;
852
868
  const y = point.y;
853
869
  switch (rotation) {
870
+ case 0:
871
+ return { x, y };
854
872
  case 90:
855
873
  return { x: 1 - y, y: x };
856
874
  case 180:
857
875
  return { x: 1 - x, y: 1 - y };
858
876
  case 270:
859
877
  return { x: y, y: 1 - x };
860
- default:
861
- return { x, y };
862
878
  }
863
879
  }
864
880
  var init_rotation = __esm({
@@ -1301,6 +1317,8 @@ var init_schema2 = __esm({
1301
1317
  mediaPickerAutoOpen: z.boolean().optional(),
1302
1318
  showMediaPreview: z.boolean().optional(),
1303
1319
  showMediaOverlayActions: z.boolean().optional(),
1320
+ mediaPreviewMaxWidth: z.enum(["xs", "sm", "md", "none"]).optional(),
1321
+ preventMediaPreviewUpscale: z.boolean().optional(),
1304
1322
  mediaDelivery: mediaDeliverySchema.optional(),
1305
1323
  mediaDeliveryByVariant: z.record(z.string(), mediaDeliverySchema).optional(),
1306
1324
  // Optional input hints for validators/widgets
@@ -1550,6 +1568,9 @@ var init_schema2 = __esm({
1550
1568
  type: z.literal("repeater"),
1551
1569
  itemLabel: z.string().default("Item"),
1552
1570
  itemLabelSource: z.string().optional(),
1571
+ showSummary: z.boolean().optional(),
1572
+ summaryFields: z.string().array().optional(),
1573
+ summaryMaxChars: z.number().int().positive().optional(),
1553
1574
  minItems: z.number().int().min(0).default(0),
1554
1575
  maxItems: z.number().int().positive().optional(),
1555
1576
  // Monomorphic mode
@@ -11279,47 +11300,48 @@ function validateFieldDefinitions(fields3, fragmentId) {
11279
11300
  function prefixFieldId(field, scope) {
11280
11301
  const cloned = cloneFieldDefinition2(field);
11281
11302
  cloned.id = `${scope}.${field.id}`;
11282
- cloned.defaultValue = cloneUnknown(cloned.defaultValue);
11303
+ const defaultValue = cloned.defaultValue;
11304
+ cloned.defaultValue = cloneUnknown(defaultValue);
11283
11305
  cloned.visibleRoles = cloned.visibleRoles ? [...cloned.visibleRoles] : void 0;
11284
11306
  cloned.ui = cloneUnknown(cloned.ui);
11285
11307
  return cloned;
11286
11308
  }
11287
11309
  function cloneFieldDefinition2(field) {
11288
- switch (field.type) {
11289
- case "repeater":
11290
- if (field.polymorphic && field.itemTypes) {
11291
- return {
11292
- ...field,
11293
- polymorphic: true,
11294
- itemTypes: Object.fromEntries(
11295
- Object.entries(field.itemTypes).map(([key, itemType]) => [
11296
- key,
11297
- {
11298
- ...itemType,
11299
- fields: itemType.fields.map(cloneFieldDefinition2)
11300
- }
11301
- ])
11302
- )
11303
- };
11304
- } else if (field.schema) {
11305
- return {
11306
- ...field,
11307
- schema: {
11308
- fields: field.schema.fields.map(cloneFieldDefinition2)
11309
- }
11310
- };
11311
- }
11312
- return { ...field };
11313
- case "group":
11310
+ if (field.type === "repeater") {
11311
+ if (field.polymorphic && field.itemTypes) {
11312
+ return {
11313
+ ...field,
11314
+ polymorphic: true,
11315
+ itemTypes: Object.fromEntries(
11316
+ Object.entries(field.itemTypes).map(([key, itemType]) => [
11317
+ key,
11318
+ {
11319
+ ...itemType,
11320
+ fields: itemType.fields.map(cloneFieldDefinition2)
11321
+ }
11322
+ ])
11323
+ )
11324
+ };
11325
+ }
11326
+ if (field.schema) {
11314
11327
  return {
11315
11328
  ...field,
11316
11329
  schema: {
11317
11330
  fields: field.schema.fields.map(cloneFieldDefinition2)
11318
11331
  }
11319
11332
  };
11320
- default:
11321
- return { ...field };
11333
+ }
11334
+ return { ...field };
11322
11335
  }
11336
+ if (field.type === "group") {
11337
+ return {
11338
+ ...field,
11339
+ schema: {
11340
+ fields: field.schema.fields.map(cloneFieldDefinition2)
11341
+ }
11342
+ };
11343
+ }
11344
+ return { ...field };
11323
11345
  }
11324
11346
  function cloneUnknown(value) {
11325
11347
  if (value == null || typeof value !== "object") {
@@ -14247,7 +14269,8 @@ function createBlockManifestWithContentShape(config2, _contentShape) {
14247
14269
  return createBlockManifest(config2);
14248
14270
  }
14249
14271
  function normalizeBlockLayout(layout) {
14250
- return Array.isArray(layout) ? [...layout] : layout;
14272
+ const rawLayout = layout;
14273
+ return Array.isArray(rawLayout) ? rawLayout : rawLayout;
14251
14274
  }
14252
14275
  function deriveComponentName(id) {
14253
14276
  const base = id.replace(/^block\./, "");
@@ -14974,10 +14997,10 @@ function normalizeEventCategoryIds(value) {
14974
14997
  if (Array.isArray(value)) {
14975
14998
  return normalizeIdList(
14976
14999
  value.filter((entry) => typeof entry === "string")
14977
- ).map(asEventCategoryId);
15000
+ ).map(unsafeAsEventCategoryId);
14978
15001
  }
14979
15002
  if (typeof value === "string") {
14980
- return normalizeIdList(value.split(",")).map(asEventCategoryId);
15003
+ return normalizeIdList(value.split(",")).map(unsafeAsEventCategoryId);
14981
15004
  }
14982
15005
  return [];
14983
15006
  }
@@ -14990,7 +15013,7 @@ function normalizeEventVenueId(value) {
14990
15013
  return null;
14991
15014
  }
14992
15015
  const trimmed = value.trim();
14993
- return trimmed ? asVenueId(trimmed) : null;
15016
+ return trimmed ? unsafeAsVenueId(trimmed) : null;
14994
15017
  }
14995
15018
  function normalizeEventStaffMemberId(value) {
14996
15019
  if (typeof value !== "string") {
@@ -14999,7 +15022,7 @@ function normalizeEventStaffMemberId(value) {
14999
15022
  const trimmed = value.trim();
15000
15023
  return trimmed ? trimmed : null;
15001
15024
  }
15002
- var eventBlockKindValues, eventSurfacePresetValues, eventSurfaceScopeValues, eventScheduleScopeValues, asEventCategoryId, asVenueId;
15025
+ var eventBlockKindValues, eventSurfacePresetValues, eventSurfaceScopeValues, eventScheduleScopeValues, unsafeAsEventCategoryId, unsafeAsVenueId;
15003
15026
  var init_filtering = __esm({
15004
15027
  "../blocks/src/system/blocks/events/shared/filtering.ts"() {
15005
15028
  init_normalizeIds();
@@ -15017,8 +15040,8 @@ var init_filtering = __esm({
15017
15040
  "custom"
15018
15041
  ];
15019
15042
  eventScheduleScopeValues = ["any", "recurring", "oneOff"];
15020
- asEventCategoryId = (value) => value;
15021
- asVenueId = (value) => value;
15043
+ unsafeAsEventCategoryId = (value) => value;
15044
+ unsafeAsVenueId = (value) => value;
15022
15045
  }
15023
15046
  });
15024
15047
 
@@ -18949,7 +18972,16 @@ var ENDPOINT_DEFINITIONS = {
18949
18972
  revalidate: 60,
18950
18973
  tags: ["site-{siteId}", "content-{siteId}-{type}"],
18951
18974
  auth: "user",
18952
- responseKind: "json"
18975
+ responseKind: "json",
18976
+ errors: ["validation:invalid_input", "resource:not_found", "resource:conflict", "server:internal_error"]
18977
+ },
18978
+ reorderContentEntries: {
18979
+ path: "/sites/{siteId}/content/{type}/order",
18980
+ method: "POST",
18981
+ tags: ["site-{siteId}", "content-{siteId}-{type}"],
18982
+ auth: "user",
18983
+ responseKind: "json",
18984
+ errors: ["validation:invalid_input", "resource:not_found", "resource:conflict", "server:internal_error"]
18953
18985
  },
18954
18986
  getContentTemplate: {
18955
18987
  path: "/sites/{siteId}/content/types/{type}/template",
@@ -23895,7 +23927,7 @@ function normalizeStoredObjectChildren(children, value, ctx) {
23895
23927
  return normalized;
23896
23928
  }
23897
23929
  function normalizeStoredRepeaterItems(plan, value, ctx) {
23898
- if (!Array.isArray(value)) {
23930
+ if (!isUnknownArray(value)) {
23899
23931
  return value;
23900
23932
  }
23901
23933
  return value.map((item) => {
@@ -23942,7 +23974,7 @@ function normalizeObjectChildren(children, value, ctx) {
23942
23974
  return normalized;
23943
23975
  }
23944
23976
  function normalizeRepeaterItems(plan, value, ctx) {
23945
- if (!Array.isArray(value)) return value;
23977
+ if (!isUnknownArray(value)) return value;
23946
23978
  return value.map((item) => {
23947
23979
  if (!item || typeof item !== "object" || Array.isArray(item)) return item;
23948
23980
  const itemRecord = item;
@@ -24329,6 +24361,9 @@ function isEmptyValue(value) {
24329
24361
  function isPlainObject(value) {
24330
24362
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
24331
24363
  }
24364
+ function isUnknownArray(value) {
24365
+ return Array.isArray(value);
24366
+ }
24332
24367
  function isValidRichTextDoc(value) {
24333
24368
  const doc = richTextDoc(value);
24334
24369
  return Boolean(isPlainObject(doc) && doc.type === "doc");
@@ -25728,16 +25763,20 @@ var marqueeLoopTransform = {
25728
25763
  summary: "Repeat an array to a minimum length, then duplicate it for seamless marquee looping",
25729
25764
  schema: marqueeLoopOptionsSchema,
25730
25765
  run: (value, options) => {
25731
- if (!Array.isArray(value) || value.length === 0) return [];
25766
+ const items = toUnknownArray(value);
25767
+ if (items.length === 0) return [];
25732
25768
  const minItems = options?.minItems ?? 10;
25733
25769
  const base = [];
25734
25770
  while (base.length < minItems) {
25735
- base.push(...value);
25771
+ base.push(...items);
25736
25772
  if (base.length > 1e3) break;
25737
25773
  }
25738
25774
  return [...base, ...base];
25739
25775
  }
25740
25776
  };
25777
+ function toUnknownArray(value) {
25778
+ return Array.isArray(value) ? value : [];
25779
+ }
25741
25780
  var formattingTransforms = [
25742
25781
  uppercaseTransform,
25743
25782
  fallbackTransform,
@@ -36402,10 +36441,16 @@ var dashboardConfigSchema = z.object({
36402
36441
  }).strip();
36403
36442
  var fieldDefinitionInputSchema = unsafeRetypeZodSchema(fieldSchema);
36404
36443
  var sdkLoaderEndpointSchema = z.enum(SUPPORTED_LOADER_ENDPOINTS);
36444
+ var loaderFallbackScalarSchema = z.union([
36445
+ z.string(),
36446
+ z.number(),
36447
+ z.boolean(),
36448
+ z.null()
36449
+ ]);
36405
36450
  var loaderParamBindingSchema = z.object({
36406
36451
  $bind: z.object({
36407
36452
  from: z.string().min(1, "Binding path is required"),
36408
- fallback: z.string().optional()
36453
+ fallback: loaderFallbackScalarSchema.optional()
36409
36454
  })
36410
36455
  });
36411
36456
  var loaderParamValueSchema = z.union([
@@ -36551,9 +36596,13 @@ var sdkBlockFieldOptionsMapSchema = z.record(
36551
36596
  var sdkContentTypeTemplateConfigSchema = z.object({
36552
36597
  blocks: z.array(z.unknown())
36553
36598
  }).passthrough();
36599
+ var sdkContentTypeOrderingConfigSchema = z.object({
36600
+ mode: z.enum(["default", "manual"]).optional()
36601
+ }).optional();
36554
36602
  var sdkContentTypeConfigSchema = z.object({
36555
36603
  key: z.string().min(1),
36556
36604
  fields: z.array(z.unknown()),
36605
+ ordering: sdkContentTypeOrderingConfigSchema,
36557
36606
  template: sdkContentTypeTemplateConfigSchema.nullable().optional()
36558
36607
  }).passthrough();
36559
36608
  var sdkContentConfigSchema = z.object({
@@ -36659,9 +36708,9 @@ z.object({
36659
36708
 
36660
36709
  // ../api/src/sdkContracts.ts
36661
36710
  var ignoredDocumentSyncSectionWarnings = {
36662
- pages: "content.pages is ignored by push-config; use `riverbankcms push pages` to sync pages.",
36663
- entries: "content.entries is ignored by push-config; use `riverbankcms push entries` to sync content entries.",
36664
- navigationMenus: "content.navigationMenus is ignored by push-config; use `riverbankcms push navigation` to sync navigation menus."
36711
+ pages: "content.pages is ignored by push-config; put pages in content/pages/*.json and use `riverbankcms push pages` (or `riverbankcms push`) to sync them.",
36712
+ entries: "content.entries is ignored by push-config; put entries in content/entries/<type>/*.json and use `riverbankcms push entries` (or `riverbankcms push`) to sync them.",
36713
+ navigationMenus: "content.navigationMenus is ignored by push-config; put navigation in content/navigation.json and use `riverbankcms push navigation` (or `riverbankcms push`) to sync it."
36665
36714
  };
36666
36715
  function formatIgnoredDocumentSyncSectionWarning(section2) {
36667
36716
  return ignoredDocumentSyncSectionWarnings[section2];
@@ -36823,18 +36872,21 @@ function buildEndpointURL(baseURL, endpoint) {
36823
36872
  function isFormDataBody(value) {
36824
36873
  return typeof FormData !== "undefined" && value instanceof FormData;
36825
36874
  }
36875
+ function isUnknownArray2(value) {
36876
+ return Array.isArray(value);
36877
+ }
36826
36878
  function appendQueryParam(queryParams, key, value) {
36827
36879
  if (value === void 0 || value === null) {
36828
36880
  return;
36829
36881
  }
36830
- if (Array.isArray(value)) {
36882
+ if (isUnknownArray2(value)) {
36831
36883
  const stack2 = [...value].reverse();
36832
36884
  while (stack2.length > 0) {
36833
36885
  const item = stack2.pop();
36834
36886
  if (item === void 0 || item === null) {
36835
36887
  continue;
36836
36888
  }
36837
- if (Array.isArray(item)) {
36889
+ if (isUnknownArray2(item)) {
36838
36890
  stack2.push(...[...item].reverse());
36839
36891
  continue;
36840
36892
  }
@@ -36844,6 +36896,12 @@ function appendQueryParam(queryParams, key, value) {
36844
36896
  }
36845
36897
  queryParams.append(key, String(value));
36846
36898
  }
36899
+ function serializePathParam(endpoint, key, value) {
36900
+ if (typeof value === "string") {
36901
+ return value;
36902
+ }
36903
+ throw new Error(`Invalid path param for endpoint ${String(endpoint)}: ${key} must be a string`);
36904
+ }
36847
36905
  function invalidateCacheTags(tags2, params) {
36848
36906
  const resolved = getRevalidateTag();
36849
36907
  if (typeof window !== "undefined" || !resolved || !tags2) return;
@@ -36982,8 +37040,9 @@ function createRawCMSClient(headers = {}, baseUrl) {
36982
37040
  const bracePlaceholder = `{${key}}`;
36983
37041
  const colonPlaceholder = `:${key}`;
36984
37042
  if (originalPath.includes(bracePlaceholder) || originalPath.includes(colonPlaceholder)) {
36985
- url = url.replace(bracePlaceholder, value);
36986
- url = url.replace(colonPlaceholder, value);
37043
+ const stringValue = serializePathParam(endpoint, key, value);
37044
+ url = url.replace(bracePlaceholder, stringValue);
37045
+ url = url.replace(colonPlaceholder, stringValue);
36987
37046
  } else {
36988
37047
  unusedParams[key] = value;
36989
37048
  }
@@ -38029,6 +38088,9 @@ var templateConfigSchemaForward = z.object({
38029
38088
  })
38030
38089
  )
38031
38090
  }).optional();
38091
+ var contentTypeOrderingSchema = z.object({
38092
+ mode: z.enum(["default", "manual"]).optional()
38093
+ }).optional();
38032
38094
  var contentTypeConfigSchema = z.object({
38033
38095
  key: contentTypeKeySchema,
38034
38096
  name: z.string().min(1),
@@ -38038,6 +38100,7 @@ var contentTypeConfigSchema = z.object({
38038
38100
  // Fields are validated as unknown[] here - deep field validation happens in @riverbankcms/blocks
38039
38101
  fields: z.array(z.any()).min(1, "At least one field is required"),
38040
38102
  titleField: z.string().optional(),
38103
+ ordering: contentTypeOrderingSchema,
38041
38104
  isSingleton: z.boolean().optional().default(false),
38042
38105
  template: templateConfigSchemaForward
38043
38106
  }).refine(
@@ -38563,7 +38626,7 @@ var loaderParamBindingSchema2 = z.object({
38563
38626
  // Loader params are ultimately string-normalized for query strings, so fallbacks should
38564
38627
  // stay scalar. Use transforms (e.g. `value.jsonArray`) when you need to serialize
38565
38628
  // more complex values into a string.
38566
- fallback: z.union([z.string(), z.number(), z.boolean(), z.null()]).optional(),
38629
+ fallback: loaderFallbackScalarSchema.optional(),
38567
38630
  transforms: z.array(loaderTransformStepSchema).default([]),
38568
38631
  pick: z.enum(["value", "collection", "context"]).default("value"),
38569
38632
  coerce: z.enum(["number", "boolean", "string"]).optional()
@@ -39627,6 +39690,7 @@ function createPullOperations(http) {
39627
39690
  meta: {
39628
39691
  pulledAt: (/* @__PURE__ */ new Date()).toISOString(),
39629
39692
  entries: entriesResult?.meta?.entries,
39693
+ settingsUpdatedAt: settingsResult?.meta?.updatedAt,
39630
39694
  truncated: entriesResult?.meta?.truncated,
39631
39695
  truncationMessage: entriesResult?.meta?.truncationMessage
39632
39696
  }
@@ -39807,7 +39871,11 @@ function getEnv(name, fallback) {
39807
39871
  function loadEnvironment(remote) {
39808
39872
  const target = remote ? "remote" : "local";
39809
39873
  const prefix = getEnvPrefix(target);
39810
- const siteId = asSiteId(requireEnv(`${prefix}_SITE_ID`));
39874
+ const rawSiteId = requireEnv(`${prefix}_SITE_ID`);
39875
+ const siteId = parseSiteId(rawSiteId);
39876
+ if (!siteId.ok) {
39877
+ throw new Error(`Invalid site ID for ${prefix}_SITE_ID. Expected a UUID.`);
39878
+ }
39811
39879
  const dashboardUrl = requireEnv(`${prefix}_DASHBOARD_URL`);
39812
39880
  const managementApiKey = requireEnv(`${prefix}_MGMT_API_KEY`);
39813
39881
  const apiKey = getEnv(`${prefix}_API_KEY`);
@@ -39834,7 +39902,7 @@ function loadEnvironment(remote) {
39834
39902
  }
39835
39903
  }
39836
39904
  return {
39837
- siteId,
39905
+ siteId: siteId.value,
39838
39906
  dashboardUrl,
39839
39907
  managementApiKey,
39840
39908
  apiKey,
@@ -40136,7 +40204,8 @@ function mapEntryForOutput(entry) {
40136
40204
  data: entry.data,
40137
40205
  status: entry.status,
40138
40206
  hasUnpublishedChanges: entry.hasUnpublishedChanges,
40139
- title: entry.title
40207
+ title: entry.title,
40208
+ manualOrder: entry.manualOrder
40140
40209
  };
40141
40210
  if (entry.slug !== void 0) {
40142
40211
  result.slug = entry.slug;
@@ -41007,6 +41076,15 @@ function entryFilePath(input) {
41007
41076
  }
41008
41077
 
41009
41078
  // src/cli/content/writer.ts
41079
+ function isRecord7(value) {
41080
+ return typeof value === "object" && value !== null && !Array.isArray(value);
41081
+ }
41082
+ function parseThemeMeta(value) {
41083
+ if (!isRecord7(value) || typeof value.pulledAt !== "string" || !isRecord7(value.themes)) {
41084
+ return null;
41085
+ }
41086
+ return { pulledAt: value.pulledAt, themes: value.themes };
41087
+ }
41010
41088
  async function writeEntries(contentDir, pulledEntries, options) {
41011
41089
  const entriesDir = path5.join(contentDir, "entries");
41012
41090
  const metaDir = path5.join(contentDir, ".meta");
@@ -41038,23 +41116,33 @@ async function writeEntries(contentDir, pulledEntries, options) {
41038
41116
  const metaPath = path5.join(metaDir, `${contentType}.json`);
41039
41117
  if (!options?.skipMeta) {
41040
41118
  await ensureDir(metaDir);
41119
+ const nextMeta = {
41120
+ ...meta,
41121
+ manualOrder: entries.slice().sort((left, right) => {
41122
+ const leftOrder = left.manualOrder ?? Number.MAX_SAFE_INTEGER;
41123
+ const rightOrder = right.manualOrder ?? Number.MAX_SAFE_INTEGER;
41124
+ if (leftOrder !== rightOrder) return leftOrder - rightOrder;
41125
+ return left.identifier.localeCompare(right.identifier);
41126
+ }).map((entry) => entry.identifier)
41127
+ };
41041
41128
  if (options?.cleanupMissing === false) {
41042
41129
  try {
41043
41130
  const existing = JSON.parse(await fs5.readFile(metaPath, "utf-8"));
41044
41131
  await writeJsonFile(metaPath, {
41045
41132
  ...existing,
41046
- pulledAt: meta.pulledAt,
41133
+ pulledAt: nextMeta.pulledAt,
41134
+ manualOrder: nextMeta.manualOrder,
41047
41135
  entries: {
41048
41136
  ...existing.entries,
41049
- ...meta.entries
41137
+ ...nextMeta.entries
41050
41138
  }
41051
41139
  });
41052
41140
  } catch (error) {
41053
41141
  if (error.code !== "ENOENT") throw error;
41054
- await writeJsonFile(metaPath, meta);
41142
+ await writeJsonFile(metaPath, nextMeta);
41055
41143
  }
41056
41144
  } else {
41057
- await writeJsonFile(metaPath, meta);
41145
+ await writeJsonFile(metaPath, nextMeta);
41058
41146
  }
41059
41147
  }
41060
41148
  if (!options?.skipMeta && options?.entryBaseSnapshot) {
@@ -41137,11 +41225,19 @@ async function writeNavigation(contentDir, pulledNavigation, options) {
41137
41225
  }
41138
41226
  return { filePath, metaPath };
41139
41227
  }
41140
- async function writeSettings(contentDir, pulledSettings) {
41228
+ async function writeSettings(contentDir, pulledSettings, options) {
41141
41229
  await ensureDir(contentDir);
41142
41230
  const filePath = path5.join(contentDir, "settings.json");
41143
41231
  stripEnvSpecificMediaFieldsInPlace(pulledSettings.settings);
41144
41232
  await writeJsonFile(filePath, pulledSettings.settings);
41233
+ if (!options?.skipMeta) {
41234
+ const metaDir = path5.join(contentDir, ".meta");
41235
+ await ensureDir(metaDir);
41236
+ await writeJsonFile(path5.join(metaDir, "settings.json"), {
41237
+ pulledAt: pulledSettings.meta.pulledAt,
41238
+ updatedAt: pulledSettings.meta.updatedAt ?? null
41239
+ });
41240
+ }
41145
41241
  return filePath;
41146
41242
  }
41147
41243
  async function writeForms(contentDir, pulledForms, options) {
@@ -41204,7 +41300,7 @@ async function writePulledTheme(contentDir, pulledTheme, themeName = "current",
41204
41300
  };
41205
41301
  try {
41206
41302
  const content = await fs5.readFile(metaPath, "utf-8");
41207
- existingMeta = JSON.parse(content);
41303
+ existingMeta = parseThemeMeta(JSON.parse(content)) ?? existingMeta;
41208
41304
  } catch {
41209
41305
  }
41210
41306
  existingMeta.pulledAt = pulledTheme.meta.pulledAt;
@@ -41433,6 +41529,12 @@ async function updateMetadataAfterPush(contentDir, remoteContent) {
41433
41529
  menus: menusMeta
41434
41530
  });
41435
41531
  }
41532
+ if (remoteContent.settingsUpdatedAt !== void 0) {
41533
+ await writeJsonFile(path5.join(metaDir, "settings.json"), {
41534
+ pulledAt: now,
41535
+ updatedAt: remoteContent.settingsUpdatedAt
41536
+ });
41537
+ }
41436
41538
  if (remoteContent.forms && remoteContent.forms.length > 0) {
41437
41539
  const metaPath = path5.join(metaDir, "forms.json");
41438
41540
  const formsMeta = {};
@@ -41591,6 +41693,7 @@ async function readEntries(contentDir, contentType) {
41591
41693
  for (const item of items) {
41592
41694
  if (item.isDirectory()) {
41593
41695
  const entries = await readEntriesFromDirectory(path5.join(entriesDir, item.name));
41696
+ await applyManualOrderMetadata(contentDir, item.name, entries);
41594
41697
  if (entries.length > 0) {
41595
41698
  result.set(item.name, entries);
41596
41699
  }
@@ -41602,6 +41705,24 @@ async function readEntries(contentDir, contentType) {
41602
41705
  }
41603
41706
  return result;
41604
41707
  }
41708
+ async function applyManualOrderMetadata(contentDir, contentType, entries) {
41709
+ const meta = await readEntriesMeta(contentDir, contentType);
41710
+ const order = meta?.manualOrder;
41711
+ if (!order?.length) return;
41712
+ const orderByIdentifier = new Map(order.map((identifier, index) => [identifier, index]));
41713
+ for (const entry of entries) {
41714
+ const manualOrder = orderByIdentifier.get(entry.identifier);
41715
+ if (manualOrder !== void 0) {
41716
+ entry.manualOrder = manualOrder;
41717
+ }
41718
+ }
41719
+ entries.sort((left, right) => {
41720
+ const leftOrder = left.manualOrder ?? Number.MAX_SAFE_INTEGER;
41721
+ const rightOrder = right.manualOrder ?? Number.MAX_SAFE_INTEGER;
41722
+ if (leftOrder !== rightOrder) return leftOrder - rightOrder;
41723
+ return left.identifier.localeCompare(right.identifier);
41724
+ });
41725
+ }
41605
41726
  async function readPages(contentDir) {
41606
41727
  const pagesDir = path5.join(contentDir, "pages");
41607
41728
  const pages = [];
@@ -41798,6 +41919,10 @@ async function getContentSummary(contentDir) {
41798
41919
  courseCount: content.courses.length
41799
41920
  };
41800
41921
  }
41922
+ var settingsMetadataSchema = z.object({
41923
+ pulledAt: z.string(),
41924
+ updatedAt: z.string().nullable()
41925
+ });
41801
41926
  async function readEntriesMeta(contentDir, contentType) {
41802
41927
  const metaPath = path5.join(contentDir, ".meta", `${contentType}.json`);
41803
41928
  try {
@@ -41818,6 +41943,7 @@ async function readAllMeta(contentDir) {
41818
41943
  const skipFiles = [
41819
41944
  "pages.json",
41820
41945
  "navigation.json",
41946
+ "settings.json",
41821
41947
  "forms.json",
41822
41948
  "themes.json",
41823
41949
  "footer.json",
@@ -41838,6 +41964,22 @@ async function readAllMeta(contentDir) {
41838
41964
  }
41839
41965
  return metaMap;
41840
41966
  }
41967
+ async function readSettingsMeta(contentDir) {
41968
+ const metaPath = path5.join(contentDir, ".meta", "settings.json");
41969
+ try {
41970
+ const content = await fs5.readFile(metaPath, "utf-8");
41971
+ const parsed = settingsMetadataSchema.safeParse(JSON.parse(content));
41972
+ if (!parsed.success) {
41973
+ throw new Error("Invalid settings metadata in .meta/settings.json");
41974
+ }
41975
+ return parsed.data;
41976
+ } catch (error) {
41977
+ if (error.code === "ENOENT") {
41978
+ return null;
41979
+ }
41980
+ throw error;
41981
+ }
41982
+ }
41841
41983
  async function readPagesMeta(contentDir) {
41842
41984
  const metaPath = path5.join(contentDir, ".meta", "pages.json");
41843
41985
  try {
@@ -42324,9 +42466,9 @@ async function localMediaFileExists(filePath) {
42324
42466
  }
42325
42467
 
42326
42468
  // src/cli/media/identifiers.ts
42327
- var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
42469
+ var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
42328
42470
  var isMediaValue = (value) => {
42329
- if (!isRecord7(value)) return false;
42471
+ if (!isRecord8(value)) return false;
42330
42472
  const type = value.type;
42331
42473
  if (type !== "image" && type !== "video" && type !== "audio" && type !== "document" && type !== "spreadsheet" && type !== "archive") return false;
42332
42474
  return typeof value.identifier === "string" || typeof value.assetId === "string" || typeof value.storagePath === "string" || typeof value.src === "string";
@@ -42341,7 +42483,7 @@ var walkMediaValues = (value, location2, handler) => {
42341
42483
  });
42342
42484
  return;
42343
42485
  }
42344
- if (isRecord7(value)) {
42486
+ if (isRecord8(value)) {
42345
42487
  Object.entries(value).forEach(([key, entry]) => {
42346
42488
  walkMediaValues(entry, location2 ? `${location2}.${key}` : key, handler);
42347
42489
  });
@@ -42449,7 +42591,7 @@ var normalizeMediaValueToIdentifierOnly = (value, identifier, asset) => {
42449
42591
  };
42450
42592
 
42451
42593
  // src/cli/media/rich-text.ts
42452
- var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
42594
+ var isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
42453
42595
  function collectRichTextImageAttrs(value, out = [], location2 = "") {
42454
42596
  if (Array.isArray(value)) {
42455
42597
  value.forEach(
@@ -42457,8 +42599,8 @@ function collectRichTextImageAttrs(value, out = [], location2 = "") {
42457
42599
  );
42458
42600
  return out;
42459
42601
  }
42460
- if (!isRecord8(value)) return out;
42461
- if (value.type === "image" && isRecord8(value.attrs)) {
42602
+ if (!isRecord9(value)) return out;
42603
+ if (value.type === "image" && isRecord9(value.attrs)) {
42462
42604
  out.push({ attrs: value.attrs, location: location2 ? `${location2}.attrs` : "attrs" });
42463
42605
  }
42464
42606
  for (const [key, child] of Object.entries(value)) {
@@ -43462,7 +43604,8 @@ function calculateEntryDiffs(localEntries, remoteEntries, options) {
43462
43604
  for (const entry of entries) {
43463
43605
  typeMap.set(entry.identifier, {
43464
43606
  data: entry.data,
43465
- status: entry.status
43607
+ status: entry.status,
43608
+ manualOrder: entry.manualOrder
43466
43609
  });
43467
43610
  }
43468
43611
  remoteLookup.set(contentType, typeMap);
@@ -43501,6 +43644,9 @@ function calculateEntryDiffs(localEntries, remoteEntries, options) {
43501
43644
  remoteEntry.data
43502
43645
  ));
43503
43646
  }
43647
+ if (typeof localEntry.manualOrder === "number" && localEntry.manualOrder !== remoteEntry.manualOrder) {
43648
+ changes.push("manualOrder");
43649
+ }
43504
43650
  const statusChange2 = determineStatusChange(localEntry.status, remoteEntry.status);
43505
43651
  if (changes.length > 0) {
43506
43652
  typeDiffs.push({
@@ -45032,7 +45178,8 @@ async function fetchAllContentPaginated(client, contentTypes, output, baseConten
45032
45178
  ...baseContent?.courses ? { courses: baseContent.courses } : {},
45033
45179
  meta: {
45034
45180
  pulledAt: (/* @__PURE__ */ new Date()).toISOString(),
45035
- entries: allMeta
45181
+ entries: allMeta,
45182
+ settingsUpdatedAt: settingsResult.meta.updatedAt
45036
45183
  }
45037
45184
  };
45038
45185
  }
@@ -45117,7 +45264,8 @@ function mapManagementEntryToPulledEntry(entry) {
45117
45264
  status: entry.status,
45118
45265
  hasUnpublishedChanges: entry.hasUnpublishedChanges,
45119
45266
  slug: entry.slug,
45120
- title: entry.title
45267
+ title: entry.title,
45268
+ manualOrder: entry.manualOrder
45121
45269
  };
45122
45270
  }
45123
45271
  async function pullSingleEntry(client, contentType, identifier) {
@@ -45793,7 +45941,7 @@ Media Sync:
45793
45941
  const mediaContent = createScopedPullContent(result.meta, { settings: result.settings });
45794
45942
  await applyMediaIdentifiers(mediaContent);
45795
45943
  await syncMediaIfRequested(mediaContent);
45796
- const filePath = await writeSettings(contentDir, result);
45944
+ const filePath = await writeSettings(contentDir, result, { skipMeta });
45797
45945
  output.success("Pulled site settings", { file: filePath });
45798
45946
  break;
45799
45947
  }
@@ -45900,7 +46048,17 @@ Media Sync:
45900
46048
  );
45901
46049
  await writePages(contentDir, { pages: result.pages, meta: result.meta }, { skipMeta });
45902
46050
  await writeNavigation(contentDir, { menus: result.navigation, meta: result.meta }, { skipMeta });
45903
- await writeSettings(contentDir, { settings: result.settings, meta: result.meta });
46051
+ await writeSettings(
46052
+ contentDir,
46053
+ {
46054
+ settings: result.settings,
46055
+ meta: {
46056
+ pulledAt: result.meta.pulledAt,
46057
+ updatedAt: result.meta.settingsUpdatedAt ?? null
46058
+ }
46059
+ },
46060
+ { skipMeta }
46061
+ );
45904
46062
  await writeForms(contentDir, { forms: result.forms, meta: result.meta }, { skipMeta });
45905
46063
  if (result.venues) {
45906
46064
  await writeVenues(contentDir, { venues: result.venues, meta: result.meta }, { skipMeta });
@@ -45981,6 +46139,7 @@ var VALID_PUSH_SCOPES = [
45981
46139
  "pages",
45982
46140
  "navigation",
45983
46141
  "forms",
46142
+ "settings",
45984
46143
  "theme",
45985
46144
  "footer",
45986
46145
  "venues",
@@ -46134,6 +46293,22 @@ function filterLocalContent(localContent, scope, contentType, identifier) {
46134
46293
  }
46135
46294
  };
46136
46295
  }
46296
+ if (scope === "settings") {
46297
+ return {
46298
+ content: {
46299
+ ...localContent,
46300
+ entries: /* @__PURE__ */ new Map(),
46301
+ pages: [],
46302
+ navigation: null,
46303
+ forms: [],
46304
+ footer: null,
46305
+ venues: [],
46306
+ eventCategories: [],
46307
+ events: [],
46308
+ courses: []
46309
+ }
46310
+ };
46311
+ }
46137
46312
  if (scope === "venues") {
46138
46313
  return {
46139
46314
  content: {
@@ -46207,12 +46382,14 @@ function calculateMetadataUpdates(result) {
46207
46382
  const willUpdatePages = result.pages.failed === 0 && result.pages.created + result.pages.updated > 0;
46208
46383
  const willUpdateNavigation = result.navigation.failed === 0 && result.navigation.created + result.navigation.updated > 0;
46209
46384
  const willUpdateForms = result.forms.failed === 0 && result.forms.created + result.forms.updated > 0;
46210
- const shouldUpdateMetadata = willUpdateEntries || willUpdatePages || willUpdateNavigation || willUpdateForms;
46385
+ const willUpdateSettings = result.settings.failed === 0 && result.settings.updated > 0;
46386
+ const shouldUpdateMetadata = willUpdateEntries || willUpdatePages || willUpdateNavigation || willUpdateForms || willUpdateSettings;
46211
46387
  return {
46212
46388
  willUpdateEntries,
46213
46389
  willUpdatePages,
46214
46390
  willUpdateNavigation,
46215
46391
  willUpdateForms,
46392
+ willUpdateSettings,
46216
46393
  shouldUpdateMetadata
46217
46394
  };
46218
46395
  }
@@ -46236,11 +46413,11 @@ function normalizeLocalContentShape(content) {
46236
46413
  function nullishToNull(value) {
46237
46414
  return value == null ? null : value;
46238
46415
  }
46239
- function isRecord9(value) {
46416
+ function isRecord10(value) {
46240
46417
  return typeof value === "object" && value !== null && !Array.isArray(value);
46241
46418
  }
46242
46419
  function normalizeVenueAddress(value) {
46243
- const obj = isRecord9(value) ? value : {};
46420
+ const obj = isRecord10(value) ? value : {};
46244
46421
  return {
46245
46422
  line1: nullishToNull(typeof obj.line1 === "string" ? obj.line1 : void 0),
46246
46423
  line2: nullishToNull(typeof obj.line2 === "string" ? obj.line2 : void 0),
@@ -46257,7 +46434,7 @@ function normalizeVenueAddress(value) {
46257
46434
  };
46258
46435
  }
46259
46436
  function normalizeVenueLocation(value) {
46260
- if (!isRecord9(value)) return null;
46437
+ if (!isRecord10(value)) return null;
46261
46438
  const obj = value;
46262
46439
  const lat = typeof obj.lat === "number" ? obj.lat : null;
46263
46440
  const lng = typeof obj.lng === "number" ? obj.lng : null;
@@ -46265,7 +46442,7 @@ function normalizeVenueLocation(value) {
46265
46442
  return { lat, lng };
46266
46443
  }
46267
46444
  function normalizeVenueForCompare(venue) {
46268
- const obj = isRecord9(venue) ? venue : {};
46445
+ const obj = isRecord10(venue) ? venue : {};
46269
46446
  return {
46270
46447
  slug: String(obj.slug),
46271
46448
  title: String(obj.title),
@@ -46278,7 +46455,7 @@ function normalizeVenueForCompare(venue) {
46278
46455
  };
46279
46456
  }
46280
46457
  function normalizeEventCategoryForCompare(category) {
46281
- const obj = isRecord9(category) ? category : {};
46458
+ const obj = isRecord10(category) ? category : {};
46282
46459
  return {
46283
46460
  identifier: String(obj.identifier),
46284
46461
  name: String(obj.name),
@@ -46288,9 +46465,9 @@ function normalizeEventCategoryForCompare(category) {
46288
46465
  };
46289
46466
  }
46290
46467
  function normalizeRemoteEventForCompare(event) {
46291
- const obj = isRecord9(event) ? event : {};
46292
- const schedule = isRecord9(obj.schedule) ? obj.schedule : {};
46293
- const pricing = isRecord9(obj.pricing) ? obj.pricing : {};
46468
+ const obj = isRecord10(event) ? event : {};
46469
+ const schedule = isRecord10(obj.schedule) ? obj.schedule : {};
46470
+ const pricing = isRecord10(obj.pricing) ? obj.pricing : {};
46294
46471
  return {
46295
46472
  identifier: String(obj.identifier),
46296
46473
  title: String(obj.title),
@@ -46323,14 +46500,14 @@ function normalizeRemoteEventForCompare(event) {
46323
46500
  venueRef: nullishToNull(typeof obj.venueRef === "string" ? obj.venueRef : void 0),
46324
46501
  categoryRef: nullishToNull(typeof obj.categoryRef === "string" ? obj.categoryRef : void 0),
46325
46502
  formRef: nullishToNull(typeof obj.formRef === "string" ? obj.formRef : void 0),
46326
- content: isRecord9(obj.content) ? obj.content : {},
46327
- settings: isRecord9(obj.settings) ? obj.settings : {},
46328
- presentation: isRecord9(obj.presentation) ? obj.presentation : null,
46503
+ content: isRecord10(obj.content) ? obj.content : {},
46504
+ settings: isRecord10(obj.settings) ? obj.settings : {},
46505
+ presentation: isRecord10(obj.presentation) ? obj.presentation : null,
46329
46506
  tags: Array.isArray(obj.tags) ? obj.tags : []
46330
46507
  };
46331
46508
  }
46332
46509
  function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
46333
- const local = isRecord9(localEvent) ? localEvent : {};
46510
+ const local = isRecord10(localEvent) ? localEvent : {};
46334
46511
  const base = remoteEvent ? normalizeRemoteEventForCompare(remoteEvent) : normalizeRemoteEventForCompare({
46335
46512
  identifier: local.identifier,
46336
46513
  title: local.title,
@@ -46348,8 +46525,8 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
46348
46525
  presentation: local.presentation ?? null,
46349
46526
  tags: local.tags ?? []
46350
46527
  });
46351
- const schedule = isRecord9(local.schedule) ? local.schedule : {};
46352
- const pricing = isRecord9(local.pricing) ? local.pricing : {};
46528
+ const schedule = isRecord10(local.schedule) ? local.schedule : {};
46529
+ const pricing = isRecord10(local.pricing) ? local.pricing : {};
46353
46530
  return {
46354
46531
  ...base,
46355
46532
  identifier: String(local.identifier ?? base.identifier),
@@ -46375,9 +46552,9 @@ function normalizeLocalEventAgainstRemoteForCompare(localEvent, remoteEvent) {
46375
46552
  venueRef: local.venueRef === void 0 ? base.venueRef : nullishToNull(typeof local.venueRef === "string" ? local.venueRef : void 0),
46376
46553
  categoryRef: local.categoryRef === void 0 ? base.categoryRef : nullishToNull(typeof local.categoryRef === "string" ? local.categoryRef : void 0),
46377
46554
  formRef: local.formRef === void 0 ? base.formRef : nullishToNull(typeof local.formRef === "string" ? local.formRef : void 0),
46378
- content: local.content === void 0 ? base.content : isRecord9(local.content) ? local.content : {},
46379
- settings: local.settings === void 0 ? base.settings : isRecord9(local.settings) ? local.settings : {},
46380
- presentation: local.presentation === void 0 ? base.presentation : isRecord9(local.presentation) ? local.presentation : null,
46555
+ content: local.content === void 0 ? base.content : isRecord10(local.content) ? local.content : {},
46556
+ settings: local.settings === void 0 ? base.settings : isRecord10(local.settings) ? local.settings : {},
46557
+ presentation: local.presentation === void 0 ? base.presentation : isRecord10(local.presentation) ? local.presentation : null,
46381
46558
  tags: local.tags === void 0 ? base.tags : Array.isArray(local.tags) ? local.tags : []
46382
46559
  };
46383
46560
  }
@@ -46389,7 +46566,7 @@ function toIsoStringOrOriginal(value) {
46389
46566
  function normalizeCourseSessions(value) {
46390
46567
  if (!Array.isArray(value)) return [];
46391
46568
  return value.map((session) => {
46392
- const obj = isRecord9(session) ? session : {};
46569
+ const obj = isRecord10(session) ? session : {};
46393
46570
  return {
46394
46571
  startsAt: toIsoStringOrOriginal(obj.startsAt),
46395
46572
  endsAt: toIsoStringOrOriginal(obj.endsAt)
@@ -46401,18 +46578,18 @@ function normalizeCourseSessions(value) {
46401
46578
  }
46402
46579
  function normalizeCourseProgram(value) {
46403
46580
  if (value == null) return null;
46404
- if (!isRecord9(value)) {
46581
+ if (!isRecord10(value)) {
46405
46582
  return { identifier: null, data: {} };
46406
46583
  }
46407
46584
  return {
46408
46585
  identifier: nullishToNull(
46409
46586
  typeof value.identifier === "string" ? value.identifier : void 0
46410
46587
  ),
46411
- data: isRecord9(value.data) ? value.data : {}
46588
+ data: isRecord10(value.data) ? value.data : {}
46412
46589
  };
46413
46590
  }
46414
46591
  function normalizeRemoteCourseForCompare(course) {
46415
- const obj = isRecord9(course) ? course : {};
46592
+ const obj = isRecord10(course) ? course : {};
46416
46593
  return {
46417
46594
  identifier: String(obj.identifier),
46418
46595
  title: String(obj.title),
@@ -46435,7 +46612,7 @@ function normalizeRemoteCourseForCompare(course) {
46435
46612
  };
46436
46613
  }
46437
46614
  function normalizeLocalCourseAgainstRemoteForCompare(localCourse, remoteCourse) {
46438
- const local = isRecord9(localCourse) ? localCourse : {};
46615
+ const local = isRecord10(localCourse) ? localCourse : {};
46439
46616
  const base = remoteCourse ? normalizeRemoteCourseForCompare(remoteCourse) : normalizeRemoteCourseForCompare({
46440
46617
  identifier: local.identifier,
46441
46618
  title: local.title,
@@ -46456,11 +46633,11 @@ function normalizeLocalCourseAgainstRemoteForCompare(localCourse, remoteCourse)
46456
46633
  });
46457
46634
  const status = local.status === void 0 ? base.status : local.status === "active" || local.status === "cancelled" || local.status === "completed" ? local.status : "draft";
46458
46635
  const visibility = local.visibility === void 0 ? base.visibility : local.visibility === "public" || local.visibility === "private" || local.visibility === "unlisted" ? local.visibility : "public";
46459
- const program2 = local.program === void 0 ? base.program : local.program === null ? null : isRecord9(local.program) ? {
46636
+ const program2 = local.program === void 0 ? base.program : local.program === null ? null : isRecord10(local.program) ? {
46460
46637
  identifier: local.program.identifier === void 0 ? base.program?.identifier ?? null : nullishToNull(
46461
46638
  typeof local.program.identifier === "string" ? local.program.identifier : void 0
46462
46639
  ),
46463
- data: isRecord9(local.program.data) ? local.program.data : base.program?.data ?? {}
46640
+ data: isRecord10(local.program.data) ? local.program.data : base.program?.data ?? {}
46464
46641
  } : base.program;
46465
46642
  return {
46466
46643
  ...base,
@@ -46630,7 +46807,7 @@ function calculatePushAllExtraChanges(local, remote, options) {
46630
46807
  }
46631
46808
 
46632
46809
  // src/cli/commands/push/stale.ts
46633
- function checkForStaleContent(localContent, localMeta, pagesMeta, navigationMeta, formsMeta, remoteContent) {
46810
+ function checkForStaleContent(localContent, localMeta, pagesMeta, navigationMeta, formsMeta, remoteContent, settingsMeta = null) {
46634
46811
  const staleItems = [];
46635
46812
  for (const [contentType, localEntries] of localContent.entries) {
46636
46813
  const meta = localMeta.get(contentType);
@@ -46689,6 +46866,17 @@ function checkForStaleContent(localContent, localMeta, pagesMeta, navigationMeta
46689
46866
  }
46690
46867
  });
46691
46868
  }
46869
+ if (localContent.settings && settingsMeta?.updatedAt && remoteContent.meta.settingsUpdatedAt) {
46870
+ const remoteTime = remoteContent.meta.settingsUpdatedAt;
46871
+ if (new Date(remoteTime) > new Date(settingsMeta.updatedAt)) {
46872
+ staleItems.push({
46873
+ scope: "settings",
46874
+ identifier: "site",
46875
+ remoteUpdatedAt: remoteTime,
46876
+ display: `Settings: site (Remote updated: ${remoteTime})`
46877
+ });
46878
+ }
46879
+ }
46692
46880
  if (formsMeta) {
46693
46881
  localContent.forms.forEach((localForm) => {
46694
46882
  const remoteForm = remoteContent.forms.find((f) => f.slug === localForm.slug);
@@ -47408,6 +47596,7 @@ var upsertContentEntryCommandSchema = z.object({
47408
47596
  contentTypeKey: z.string().min(1),
47409
47597
  slug: z.string().min(1).optional(),
47410
47598
  title: z.string().min(1).optional(),
47599
+ manualOrder: z.number().int().min(0).optional(),
47411
47600
  data: unknownRecordSchema.optional(),
47412
47601
  linkedSubjectRef: contentEntryRefSchema.optional(),
47413
47602
  mediaRefs: z.array(mediaRefSchema).readonly().optional()
@@ -48625,19 +48814,17 @@ function getSiteCommandMetadata(type) {
48625
48814
  return siteCommandMetadata[type];
48626
48815
  }
48627
48816
  function getSiteCommandLifecycleIntent(command) {
48628
- switch (command.type) {
48629
- case "ensureTeamMemberProfile":
48630
- return command.input.publish ? "publish" : "mutation";
48631
- default:
48632
- return getSiteCommandMetadata(command.type).lifecycleIntent;
48817
+ if (command.type === "ensureTeamMemberProfile") {
48818
+ return command.input.publish ? "publish" : "mutation";
48633
48819
  }
48820
+ return getSiteCommandMetadata(command.type).lifecycleIntent;
48634
48821
  }
48635
48822
 
48636
48823
  // ../site-commands/src/planner.ts
48637
48824
  init_src();
48638
48825
 
48639
48826
  // ../site-commands/src/guards.ts
48640
- function isRecord10(value) {
48827
+ function isRecord11(value) {
48641
48828
  return typeof value === "object" && value !== null;
48642
48829
  }
48643
48830
 
@@ -48902,7 +49089,7 @@ function collectVenueRefsFromIntervals(intervals, path24) {
48902
49089
  }
48903
49090
  function collectNavigationRefs(items, path24) {
48904
49091
  return items.flatMap((item, index) => {
48905
- if (!isRecord10(item)) return [];
49092
+ if (!isRecord11(item)) return [];
48906
49093
  const itemPath = `${path24}[${index}]`;
48907
49094
  const refs = [];
48908
49095
  if (typeof item.pageRef === "string") {
@@ -48919,7 +49106,7 @@ function collectNavigationRefs(items, path24) {
48919
49106
  }
48920
49107
  function collectBlockRefs(blocks, path24) {
48921
49108
  return blocks.flatMap((block, index) => {
48922
- if (!isRecord10(block)) return [];
49109
+ if (!isRecord11(block)) return [];
48923
49110
  const blockPath = `${path24}[${index}]`;
48924
49111
  return [
48925
49112
  ...collectNestedRefs(block.props, `${blockPath}.props`),
@@ -48935,22 +49122,16 @@ function collectNestedRefs(value, path24) {
48935
49122
  if (Array.isArray(value)) {
48936
49123
  return value.flatMap((item, index) => collectNestedRefs(item, `${path24}[${index}]`));
48937
49124
  }
48938
- if (!isRecord10(value)) return [];
49125
+ if (!isRecord11(value)) return [];
48939
49126
  return Object.entries(value).flatMap(([key, child]) => collectNestedRefs(child, `${path24}.${key}`));
48940
49127
  }
48941
49128
 
48942
49129
  // ../site-commands/src/staticExecutionGaps.ts
48943
49130
  function staticExecutionGapsForCommand(command) {
48944
- switch (command.type) {
48945
- case "upsertEventSeries":
48946
- return eventSeriesStaticExecutionGaps(command);
48947
- case "upsertEventTicketType":
48948
- return eventTicketTypeStaticExecutionGaps(command);
48949
- case "upsertCourse":
48950
- return courseStaticExecutionGaps(command);
48951
- default:
48952
- return [];
48953
- }
49131
+ if (command.type === "upsertEventSeries") return eventSeriesStaticExecutionGaps(command);
49132
+ if (command.type === "upsertEventTicketType") return eventTicketTypeStaticExecutionGaps(command);
49133
+ if (command.type === "upsertCourse") return courseStaticExecutionGaps(command);
49134
+ return [];
48954
49135
  }
48955
49136
  function eventSeriesStaticExecutionGaps(command) {
48956
49137
  return [
@@ -49197,9 +49378,9 @@ function deriveIdempotencyKey(input) {
49197
49378
  ].join("|"));
49198
49379
  }
49199
49380
  function findUnknownCommandTypes(input) {
49200
- if (!isRecord10(input) || !Array.isArray(input.commands)) return [];
49381
+ if (!isRecord11(input) || !Array.isArray(input.commands)) return [];
49201
49382
  return input.commands.flatMap((command, commandIndex) => {
49202
- if (!isRecord10(command) || typeof command.type !== "string") return [];
49383
+ if (!isRecord11(command) || typeof command.type !== "string") return [];
49203
49384
  if (commandTypeSet.has(command.type)) return [];
49204
49385
  return [{
49205
49386
  code: "unknown_command_type",
@@ -49225,9 +49406,12 @@ function commandIndexForIssuePath(path24) {
49225
49406
  return path24[0] === "commands" && typeof path24[1] === "number" ? path24[1] : -1;
49226
49407
  }
49227
49408
  function commandTypeForIssue(input, commandIndex) {
49228
- if (!isRecord10(input) || !Array.isArray(input.commands)) return null;
49409
+ if (!isRecord11(input) || !isUnknownArray3(input.commands)) return null;
49229
49410
  const command = input.commands[commandIndex];
49230
- return isRecord10(command) && typeof command.type === "string" ? command.type : null;
49411
+ return isRecord11(command) && typeof command.type === "string" ? command.type : null;
49412
+ }
49413
+ function isUnknownArray3(value) {
49414
+ return Array.isArray(value);
49231
49415
  }
49232
49416
  function formatIssuePath(path24) {
49233
49417
  if (path24.length === 0) return "<root>";
@@ -49409,6 +49593,51 @@ function indexOfferingCommands(batch) {
49409
49593
  mutableTicketsByEventRef.set(command.input.eventRef, tickets);
49410
49594
  break;
49411
49595
  }
49596
+ case "configureSiteIdentity":
49597
+ case "configureBookingSettings":
49598
+ case "applySiteStyleSelection":
49599
+ case "upsertMediaAsset":
49600
+ case "upsertPage":
49601
+ case "upsertBlockTree":
49602
+ case "upsertPageBlock":
49603
+ case "patchPageBlockContent":
49604
+ case "deletePageBlock":
49605
+ case "reorderPageBlocks":
49606
+ case "upsertNavigationMenu":
49607
+ case "upsertForm":
49608
+ case "upsertFooterContent":
49609
+ case "upsertContentEntry":
49610
+ case "publishPage":
49611
+ case "unpublishPage":
49612
+ case "publishContentEntry":
49613
+ case "unpublishContentEntry":
49614
+ case "deleteContentEntry":
49615
+ case "upsertStaffMember":
49616
+ case "ensureTeamMemberProfile":
49617
+ case "upsertVenue":
49618
+ case "deleteVenue":
49619
+ case "upsertEventCategory":
49620
+ case "deleteEventCategory":
49621
+ case "deleteEventSeries":
49622
+ case "upsertCourse":
49623
+ case "deleteCourse":
49624
+ case "upsertBookingPassProduct":
49625
+ case "upsertBookingMembershipProduct":
49626
+ case "seedBookingCustomer":
49627
+ case "grantCustomerPass":
49628
+ case "grantCustomerMembership":
49629
+ case "seedAppointmentBooking":
49630
+ case "seedCourseEnrollment":
49631
+ case "seedEventRegistration":
49632
+ case "seedPassRedemption":
49633
+ case "seedPortalOrder":
49634
+ case "upsertAppointmentService":
49635
+ case "upsertBookableResource":
49636
+ case "assignAppointmentServiceResources":
49637
+ case "configureAppointmentAvailability":
49638
+ break;
49639
+ default:
49640
+ assertNeverCommand(command);
49412
49641
  }
49413
49642
  }
49414
49643
  const ticketsByEventRef = new Map(
@@ -49808,6 +50037,7 @@ function appliedSubjectFromOutcome(outcome) {
49808
50037
  case "failed":
49809
50038
  case "skipped_by_stop_policy":
49810
50039
  case "compile_failed":
50040
+ case "preflight_failed":
49811
50041
  return [];
49812
50042
  default:
49813
50043
  assertNever(outcome);
@@ -49817,6 +50047,7 @@ function failureFromOutcome(outcome) {
49817
50047
  switch (outcome.status) {
49818
50048
  case "failed":
49819
50049
  case "compile_failed":
50050
+ case "preflight_failed":
49820
50051
  return {
49821
50052
  identifier: outcome.identifier,
49822
50053
  message: outcome.message,
@@ -50199,8 +50430,8 @@ function eventContentInput(content) {
50199
50430
  if (!content) return void 0;
50200
50431
  return {
50201
50432
  ...content.summary ? { summary: content.summary } : {},
50202
- ...typeof content.body === "string" || isRecord11(content.body) ? { body: content.body } : {},
50203
- ...typeof content.image === "string" || isRecord11(content.image) ? { image: content.image } : {}
50433
+ ...typeof content.body === "string" || isRecord12(content.body) ? { body: content.body } : {},
50434
+ ...typeof content.image === "string" || isRecord12(content.image) ? { image: content.image } : {}
50204
50435
  };
50205
50436
  }
50206
50437
  function courseUpsertInput(command) {
@@ -50372,7 +50603,7 @@ function toUtcIso(date, time) {
50372
50603
  const normalizedTime = time.length === 5 ? `${time}:00` : time;
50373
50604
  return (/* @__PURE__ */ new Date(`${date}T${normalizedTime}Z`)).toISOString();
50374
50605
  }
50375
- function isRecord11(value) {
50606
+ function isRecord12(value) {
50376
50607
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
50377
50608
  }
50378
50609
  function unsupported(identifier, message) {
@@ -50393,12 +50624,12 @@ function courseSessionConflictMessage(error) {
50393
50624
  init_src();
50394
50625
 
50395
50626
  // src/cli/site-commands/commandKeys.ts
50396
- var asCliContentTypeKey = (value) => value;
50397
- var asCliEntryIdentifier = (value) => value;
50398
- var asCliPageIdentifier = (value) => value;
50399
- var asCliBlockIdentifier = (value) => value;
50400
- var asCliFormSlug = (value) => value;
50401
- var asCliNavigationMenuName = (value) => value;
50627
+ var unsafeAsCliContentTypeKey = (value) => value;
50628
+ var unsafeAsCliEntryIdentifier = (value) => value;
50629
+ var unsafeAsCliPageIdentifier = (value) => value;
50630
+ var unsafeAsCliBlockIdentifier = (value) => value;
50631
+ var unsafeAsCliFormSlug = (value) => value;
50632
+ var unsafeAsCliNavigationMenuName = (value) => value;
50402
50633
 
50403
50634
  // src/cli/site-commands/commandRuntimeCompat.ts
50404
50635
  init_src();
@@ -50411,6 +50642,7 @@ function commandReportToSyncResult(input) {
50411
50642
  break;
50412
50643
  case "failed":
50413
50644
  case "compile_failed":
50645
+ case "preflight_failed":
50414
50646
  input.recordFailure(
50415
50647
  result,
50416
50648
  outcome.identifier,
@@ -50448,12 +50680,12 @@ function compileEntryPushCommands(input) {
50448
50680
  const commandBindings = [];
50449
50681
  const localEntriesByType = new Map(
50450
50682
  [...input.local.entries.entries()].map(([contentType, entries]) => [
50451
- asCliContentTypeKey(contentType),
50452
- new Map(entries.map((entry) => [asCliEntryIdentifier(entry.identifier), entry]))
50683
+ unsafeAsCliContentTypeKey(contentType),
50684
+ new Map(entries.map((entry) => [unsafeAsCliEntryIdentifier(entry.identifier), entry]))
50453
50685
  ])
50454
50686
  );
50455
50687
  for (const [contentType, entryDiffs] of input.diff.entries) {
50456
- const contentTypeKey = asCliContentTypeKey(contentType);
50688
+ const contentTypeKey = unsafeAsCliContentTypeKey(contentType);
50457
50689
  for (const entryDiff of entryDiffs) {
50458
50690
  const commandResult = entryCommandsForDiff({
50459
50691
  contentType: contentTypeKey,
@@ -50483,7 +50715,8 @@ async function executeEntryCommandPlan(input) {
50483
50715
  identifier,
50484
50716
  contentType: command.input.contentTypeKey,
50485
50717
  data: command.input.data ?? {},
50486
- slug: command.input.slug
50718
+ slug: command.input.slug,
50719
+ manualOrder: command.input.manualOrder
50487
50720
  });
50488
50721
  return;
50489
50722
  }
@@ -50565,7 +50798,7 @@ function entryCommandsForDiff(input) {
50565
50798
  if (input.entryDiff.type === "unchanged" && !input.entryDiff.statusChange) {
50566
50799
  return ok([]);
50567
50800
  }
50568
- const entryIdentifier = asCliEntryIdentifier(input.entryDiff.identifier);
50801
+ const entryIdentifier = unsafeAsCliEntryIdentifier(input.entryDiff.identifier);
50569
50802
  const entryRef = createContentEntryRef([input.contentType, entryIdentifier]);
50570
50803
  const commandBindings = [];
50571
50804
  const upsertedInBatch = input.entryDiff.type !== "delete" && input.entryDiff.type !== "unchanged";
@@ -50597,7 +50830,7 @@ function entryCommandsForDiff(input) {
50597
50830
  message: `Missing local entry for ${input.contentType}/${input.entryDiff.identifier}.`
50598
50831
  });
50599
50832
  }
50600
- const localEntryIdentifier = asCliEntryIdentifier(localEntry.identifier);
50833
+ const localEntryIdentifier = unsafeAsCliEntryIdentifier(localEntry.identifier);
50601
50834
  if (input.entryDiff.type !== "unchanged") {
50602
50835
  const command = {
50603
50836
  type: "upsertContentEntry",
@@ -50606,6 +50839,7 @@ function entryCommandsForDiff(input) {
50606
50839
  identifier: localEntryIdentifier,
50607
50840
  contentTypeKey: input.contentType,
50608
50841
  ...localEntry.slug ? { slug: localEntry.slug } : {},
50842
+ ...typeof localEntry.manualOrder === "number" ? { manualOrder: localEntry.manualOrder } : {},
50609
50843
  ...optionalTitle(localEntry.data),
50610
50844
  data: localEntry.data
50611
50845
  }
@@ -50716,10 +50950,10 @@ var formSiteCommandTypes = [
50716
50950
  function compileFormPushCommands(input) {
50717
50951
  const commandBindings = [];
50718
50952
  const formsBySlug = new Map(
50719
- input.local.forms.map((form2) => [asCliFormSlug(form2.slug), form2])
50953
+ input.local.forms.map((form2) => [unsafeAsCliFormSlug(form2.slug), form2])
50720
50954
  );
50721
50955
  for (const formDiff of input.diff.forms) {
50722
- const formSlug = asCliFormSlug(formDiff.slug);
50956
+ const formSlug = unsafeAsCliFormSlug(formDiff.slug);
50723
50957
  const commandResult = formCommandForDiff({
50724
50958
  formDiff,
50725
50959
  slug: formSlug,
@@ -50799,7 +51033,7 @@ function formCommandForDiff(input) {
50799
51033
  message: `Missing local form: ${input.formDiff.slug}.`
50800
51034
  });
50801
51035
  }
50802
- const localFormSlug = asCliFormSlug(input.localForm.slug);
51036
+ const localFormSlug = unsafeAsCliFormSlug(input.localForm.slug);
50803
51037
  const formRef = createFormRef([input.slug]);
50804
51038
  return ok({
50805
51039
  command: {
@@ -50948,11 +51182,11 @@ var navigationSiteCommandTypes = [
50948
51182
  function compileNavigationPushCommands(input) {
50949
51183
  const commandBindings = [];
50950
51184
  const menusByName = new Map(
50951
- (input.local.navigation?.menus ?? []).map((menu) => [asCliNavigationMenuName(menu.name), menu])
51185
+ (input.local.navigation?.menus ?? []).map((menu) => [unsafeAsCliNavigationMenuName(menu.name), menu])
50952
51186
  );
50953
51187
  for (const navigationDiff of input.diff) {
50954
51188
  if (navigationDiff.type === "unchanged") continue;
50955
- const menuName = asCliNavigationMenuName(navigationDiff.name);
51189
+ const menuName = unsafeAsCliNavigationMenuName(navigationDiff.name);
50956
51190
  const menu = menusByName.get(menuName);
50957
51191
  if (!menu) {
50958
51192
  return err({
@@ -50961,7 +51195,7 @@ function compileNavigationPushCommands(input) {
50961
51195
  message: `Missing local navigation menu: ${navigationDiff.name}.`
50962
51196
  });
50963
51197
  }
50964
- const localMenuName = asCliNavigationMenuName(menu.name);
51198
+ const localMenuName = unsafeAsCliNavigationMenuName(menu.name);
50965
51199
  const commandRef = createNavigationRef([localMenuName]);
50966
51200
  const role = navigationRole(menu);
50967
51201
  const command = {
@@ -51109,6 +51343,9 @@ function recordNavigationFailure(result, identifier, message) {
51109
51343
 
51110
51344
  // src/cli/site-commands/pageCommands.ts
51111
51345
  init_src();
51346
+ function assertNeverField(field) {
51347
+ throw new Error(`Unhandled field type while extracting field ids: ${JSON.stringify(field)}`);
51348
+ }
51112
51349
  function extractFieldIds(fields3) {
51113
51350
  const ids = /* @__PURE__ */ new Set();
51114
51351
  function processField(field) {
@@ -51116,24 +51353,19 @@ function extractFieldIds(fields3) {
51116
51353
  switch (field.type) {
51117
51354
  case "group":
51118
51355
  case "modal":
51119
- if (field.schema?.fields) {
51120
- for (const nestedField of field.schema.fields) {
51121
- processField(nestedField);
51122
- }
51356
+ for (const nestedField of field.schema?.fields ?? []) {
51357
+ processField(nestedField);
51123
51358
  }
51124
51359
  break;
51125
51360
  case "repeater":
51126
- if (field.schema?.fields) {
51127
- for (const nestedField of field.schema.fields) {
51128
- processField(nestedField);
51129
- }
51361
+ for (const nestedField of field.schema?.fields ?? []) {
51362
+ processField(nestedField);
51130
51363
  }
51131
51364
  if ("itemTypes" in field && field.itemTypes) {
51132
51365
  for (const itemType of Object.values(field.itemTypes)) {
51133
- if (itemType.fields) {
51134
- for (const nestedField of itemType.fields) {
51135
- processField(nestedField);
51136
- }
51366
+ if (!itemType.fields) continue;
51367
+ for (const nestedField of itemType.fields) {
51368
+ processField(nestedField);
51137
51369
  }
51138
51370
  }
51139
51371
  }
@@ -51141,14 +51373,33 @@ function extractFieldIds(fields3) {
51141
51373
  case "tabGroup":
51142
51374
  if ("tabs" in field && field.tabs) {
51143
51375
  for (const tab of field.tabs) {
51144
- if (tab.fields) {
51145
- for (const nestedField of tab.fields) {
51146
- processField(nestedField);
51147
- }
51376
+ if (!tab.fields) continue;
51377
+ for (const nestedField of tab.fields) {
51378
+ processField(nestedField);
51148
51379
  }
51149
51380
  }
51150
51381
  }
51151
51382
  break;
51383
+ case "text":
51384
+ case "richText":
51385
+ case "media":
51386
+ case "file":
51387
+ case "boolean":
51388
+ case "number":
51389
+ case "date":
51390
+ case "time":
51391
+ case "datetime":
51392
+ case "slug":
51393
+ case "url":
51394
+ case "link":
51395
+ case "select":
51396
+ case "reference":
51397
+ case "presetOrCustom":
51398
+ case "contentTypeSelect":
51399
+ case "entryPicker":
51400
+ break;
51401
+ default:
51402
+ assertNeverField(field);
51152
51403
  }
51153
51404
  }
51154
51405
  for (const field of fields3) {
@@ -51253,10 +51504,10 @@ function compilePagePushCommands(input) {
51253
51504
  const commandBindings = [];
51254
51505
  const warnings = [];
51255
51506
  const pagesByIdentifier = new Map(
51256
- input.local.pages.map((page) => [asCliPageIdentifier(page.identifier), page])
51507
+ input.local.pages.map((page) => [unsafeAsCliPageIdentifier(page.identifier), page])
51257
51508
  );
51258
51509
  for (const pageDiff of input.diff.pages) {
51259
- const pageIdentifier = asCliPageIdentifier(pageDiff.identifier);
51510
+ const pageIdentifier = unsafeAsCliPageIdentifier(pageDiff.identifier);
51260
51511
  const commandResult = pageCommandsForDiff({
51261
51512
  pageDiff,
51262
51513
  pageIdentifier,
@@ -51366,6 +51617,76 @@ function pageCommandExecutionToReport(input) {
51366
51617
  includeFailureSubject: true
51367
51618
  });
51368
51619
  }
51620
+ function preflightPageCommandPlanAsReport(input) {
51621
+ const outcomes = [];
51622
+ const warnings = [];
51623
+ const subjectByCommandRef = new Map(
51624
+ input.compiledPlan.reportedCommands.map((reportedCommand) => [
51625
+ reportedCommand.plannedCommand.command.ref,
51626
+ reportedCommand.reportSubject
51627
+ ])
51628
+ );
51629
+ for (const plannedCommand of input.compiledPlan.plan.commands) {
51630
+ const command = plannedCommand.command;
51631
+ if (command.type !== "upsertPageBlock") continue;
51632
+ const validation = validateLocalBlock({
51633
+ pageIdentifier: unsafeAsCliPageIdentifier(pageIdentifierForBlockCommand(command)),
51634
+ blockIdentifier: unsafeAsCliBlockIdentifier(blockIdentifierForCommand(command)),
51635
+ kind: command.input.type,
51636
+ data: command.input.props ?? {},
51637
+ blockFieldExtensions: input.blockFieldExtensions,
51638
+ invalidContentAsError: true
51639
+ });
51640
+ if (validation.ok) {
51641
+ warnings.push(...validation.value);
51642
+ continue;
51643
+ }
51644
+ const failure = preflightFailureFromPageCompileError({
51645
+ error: validation.error,
51646
+ subject: subjectByCommandRef.get(command.ref)
51647
+ });
51648
+ outcomes.push(failure.outcome);
51649
+ warnings.push(...failure.warnings);
51650
+ }
51651
+ return reportFromOutcomes({ outcomes, warnings });
51652
+ }
51653
+ function preflightFailureFromPageCompileError(input) {
51654
+ switch (input.error.code) {
51655
+ case "missing_local_page":
51656
+ return {
51657
+ outcome: {
51658
+ status: "preflight_failed",
51659
+ identifier: input.error.identifier,
51660
+ message: input.error.message,
51661
+ subject: input.subject
51662
+ },
51663
+ warnings: []
51664
+ };
51665
+ case "missing_local_block":
51666
+ case "invalid_page_block":
51667
+ return {
51668
+ outcome: {
51669
+ status: "preflight_failed",
51670
+ identifier: input.error.identifier,
51671
+ message: input.error.message,
51672
+ subject: input.subject
51673
+ },
51674
+ warnings: input.error.code === "invalid_page_block" ? input.error.warnings : []
51675
+ };
51676
+ case "command_validation_failed":
51677
+ return {
51678
+ outcome: {
51679
+ status: "preflight_failed",
51680
+ identifier: "command-validation",
51681
+ message: input.error.message,
51682
+ subject: input.subject
51683
+ },
51684
+ warnings: []
51685
+ };
51686
+ default:
51687
+ assertNever(input.error);
51688
+ }
51689
+ }
51369
51690
  function pageCommandReportToSyncResult(report) {
51370
51691
  return commandReportToSyncResult({
51371
51692
  report,
@@ -51395,7 +51716,7 @@ function pageCommandsForDiff(input) {
51395
51716
  const commandBindings = [];
51396
51717
  const warnings = [];
51397
51718
  const upsertedInBatch = input.pageDiff.type !== "unchanged";
51398
- const localPageIdentifier = asCliPageIdentifier(input.localPage.identifier);
51719
+ const localPageIdentifier = unsafeAsCliPageIdentifier(input.localPage.identifier);
51399
51720
  if (input.pageDiff.type !== "unchanged") {
51400
51721
  const command = {
51401
51722
  type: "upsertPage",
@@ -51474,14 +51795,14 @@ function blockCommandsForDiff(input) {
51474
51795
  if (changedBlockDiffs.length === 0) return ok(emptyPageCommandCompileFragment());
51475
51796
  const localBlocks = input.localPage.blocks ?? [];
51476
51797
  const blockLookup = new Map(
51477
- localBlocks.map((block) => [asCliBlockIdentifier(block.identifier), block])
51798
+ localBlocks.map((block) => [unsafeAsCliBlockIdentifier(block.identifier), block])
51478
51799
  );
51479
51800
  const commandBindings = [];
51480
51801
  const warnings = [];
51481
51802
  const pageDependency = input.includePageRefDependency ? { pageRef: input.pageRef } : {};
51482
51803
  for (const blockDiff of changedBlockDiffs) {
51483
51804
  if (blockDiff.type === "reorder") continue;
51484
- const blockIdentifier = asCliBlockIdentifier(blockDiff.identifier);
51805
+ const blockIdentifier = unsafeAsCliBlockIdentifier(blockDiff.identifier);
51485
51806
  const blockRef = createBlockRef([input.pageIdentifier, blockIdentifier]);
51486
51807
  if (blockDiff.type === "delete") {
51487
51808
  const command2 = {
@@ -51512,7 +51833,7 @@ function blockCommandsForDiff(input) {
51512
51833
  message: `Missing local block: ${input.localPage.identifier}/${blockDiff.identifier}.`
51513
51834
  });
51514
51835
  }
51515
- const localBlockIdentifier = asCliBlockIdentifier(localBlock.identifier);
51836
+ const localBlockIdentifier = unsafeAsCliBlockIdentifier(localBlock.identifier);
51516
51837
  const validation = validateLocalBlock({
51517
51838
  pageIdentifier: input.pageIdentifier,
51518
51839
  blockIdentifier: localBlockIdentifier,
@@ -51520,8 +51841,9 @@ function blockCommandsForDiff(input) {
51520
51841
  data: localBlock.data,
51521
51842
  blockFieldExtensions: input.blockFieldExtensions
51522
51843
  });
51523
- if (!validation.ok) return validation;
51524
- warnings.push(...validation.value);
51844
+ if (validation.ok) {
51845
+ warnings.push(...validation.value);
51846
+ }
51525
51847
  const command = {
51526
51848
  type: "upsertPageBlock",
51527
51849
  ref: blockRef,
@@ -51550,8 +51872,8 @@ function blockCommandsForDiff(input) {
51550
51872
  pageIdentifier: input.pageIdentifier,
51551
51873
  ...pageDependency,
51552
51874
  blocks: localBlocks.map((block) => ({
51553
- blockRef: createBlockRef([input.pageIdentifier, asCliBlockIdentifier(block.identifier)]),
51554
- identifier: asCliBlockIdentifier(block.identifier)
51875
+ blockRef: createBlockRef([input.pageIdentifier, unsafeAsCliBlockIdentifier(block.identifier)]),
51876
+ identifier: unsafeAsCliBlockIdentifier(block.identifier)
51555
51877
  }))
51556
51878
  }
51557
51879
  };
@@ -51568,21 +51890,39 @@ function blockCommandsForDiff(input) {
51568
51890
  }
51569
51891
  function validateLocalBlock(input) {
51570
51892
  const blockDefinition = getBlockDefinition(input.kind);
51571
- if (!blockDefinition) return ok([]);
51572
51893
  const customFields = customBlockFields(input.blockFieldExtensions, input.kind);
51573
- const validation = validateBlockData(input.data, blockDefinition.manifest, customFields);
51894
+ if (!blockDefinition && !customFields) {
51895
+ if (input.kind.startsWith("custom.")) {
51896
+ return err({
51897
+ code: "invalid_page_block",
51898
+ identifier: pageBlockIdentifier(input.pageIdentifier, input.blockIdentifier),
51899
+ warnings: [],
51900
+ message: `Unknown custom block kind: ${input.kind}`
51901
+ });
51902
+ }
51903
+ return ok([]);
51904
+ }
51905
+ const validation = validateBlockData(
51906
+ input.data,
51907
+ blockDefinition?.manifest ?? { fields: customFields ?? [] },
51908
+ blockDefinition ? customFields : void 0
51909
+ );
51574
51910
  const warnings = formatValidationResult(
51575
51911
  input.pageIdentifier,
51576
51912
  input.blockIdentifier,
51577
51913
  input.kind,
51578
51914
  validation
51579
51915
  );
51580
- if (validation.valid) return ok(warnings);
51916
+ const blockingIssues = [
51917
+ ...validation.errors,
51918
+ ...input.invalidContentAsError ? validation.warnings.filter((warning) => warning.type === "invalid_content") : []
51919
+ ];
51920
+ if (blockingIssues.length === 0) return ok(warnings);
51581
51921
  return err({
51582
51922
  code: "invalid_page_block",
51583
51923
  identifier: pageBlockIdentifier(input.pageIdentifier, input.blockIdentifier),
51584
51924
  warnings,
51585
- message: validation.errors.map((error) => error.message).join("; ")
51925
+ message: blockingIssues.map((error) => error.message).join("; ")
51586
51926
  });
51587
51927
  }
51588
51928
  function emptyPageCommandCompileFragment() {
@@ -51683,10 +52023,10 @@ function pageBlockIdentifier(pageIdentifier, blockIdentifier) {
51683
52023
  return `${pageIdentifier}/${blockIdentifier}`;
51684
52024
  }
51685
52025
  function pageIdentifierFromPageBlockIdentifier(identifier) {
51686
- return asCliPageIdentifier(identifier.split("/")[0] ?? identifier);
52026
+ return unsafeAsCliPageIdentifier(identifier.split("/")[0] ?? identifier);
51687
52027
  }
51688
52028
  function blockIdentifierFromPageBlockIdentifier(identifier) {
51689
- return asCliBlockIdentifier(identifier.split("/")[1] ?? identifier);
52029
+ return unsafeAsCliBlockIdentifier(identifier.split("/")[1] ?? identifier);
51690
52030
  }
51691
52031
 
51692
52032
  // src/cli/site-commands/pushExecution.ts
@@ -51721,6 +52061,23 @@ function compileContentPushExecutionPlan(plan, input, dependencies = {}) {
51721
52061
  steps
51722
52062
  });
51723
52063
  }
52064
+ function preflightContentPushExecutionPlan(steps, input, dependencies = {}) {
52065
+ const commandReports = steps.flatMap((step) => {
52066
+ if (step.kind !== "command-surface") return [];
52067
+ const report = (dependencies.preflightCommandSurfaceAsReport ?? preflightCommandSurfaceAsReport)(
52068
+ step.surface,
52069
+ input
52070
+ );
52071
+ return commandSurfaceReportHasFailures(report) ? [report] : [];
52072
+ });
52073
+ return {
52074
+ commandReports,
52075
+ residualSyncResults: []
52076
+ };
52077
+ }
52078
+ function contentPushExecutionReportHasFailures(report) {
52079
+ return report.commandReports.some(commandSurfaceReportHasFailures) || report.residualSyncResults.some((result) => result.errors.length > 0);
52080
+ }
51724
52081
  async function executeCommandSurfaceAsReport(surface, input) {
51725
52082
  switch (surface.surface) {
51726
52083
  case "entry":
@@ -51763,6 +52120,26 @@ async function executeCommandSurfaceAsReport(surface, input) {
51763
52120
  assertNever(surface);
51764
52121
  }
51765
52122
  }
52123
+ function preflightCommandSurfaceAsReport(surface, input) {
52124
+ switch (surface.surface) {
52125
+ case "entry":
52126
+ return { surface: "entry", report: reportFromOutcomes({ outcomes: [] }) };
52127
+ case "page":
52128
+ return {
52129
+ surface: "page",
52130
+ report: preflightPageCommandPlanAsReport({
52131
+ compiledPlan: surface.compileValue,
52132
+ blockFieldExtensions: input.blockFieldExtensions
52133
+ })
52134
+ };
52135
+ case "form":
52136
+ return { surface: "form", report: reportFromOutcomes({ outcomes: [] }) };
52137
+ case "navigation":
52138
+ return { surface: "navigation", report: reportFromOutcomes({ outcomes: [] }) };
52139
+ default:
52140
+ assertNever(surface);
52141
+ }
52142
+ }
51766
52143
  function skippedRemainingCommandReports(steps) {
51767
52144
  return steps.flatMap((step) => step.kind === "command-surface" ? [skippedCommandSurfaceReport(step.surface)] : []);
51768
52145
  }
@@ -51780,6 +52157,9 @@ function commandSurfaceReportToSyncResult(report) {
51780
52157
  assertNever(report);
51781
52158
  }
51782
52159
  }
52160
+ function commandSurfaceReportHasFailures(report) {
52161
+ return commandReportHasFailures(report.report);
52162
+ }
51783
52163
  function compileCommandSurface(surface, input) {
51784
52164
  switch (surface) {
51785
52165
  case "entry":
@@ -52047,6 +52427,8 @@ function planContentPushExecution(input) {
52047
52427
  return syncPlanWithSteps([commandSurfaceStep("navigation", "continue")]);
52048
52428
  case "pages":
52049
52429
  return pageCommandRouting(input.diff).kind === "command_backed" ? syncPlanWithSteps([commandSurfaceStep("page", "continue")]) : syncPlanWithResidualOnly(input);
52430
+ case "settings":
52431
+ return syncPlanWithResidualOnly(input);
52050
52432
  case "all":
52051
52433
  return pushAllExecutionPlan(input);
52052
52434
  default:
@@ -52127,14 +52509,29 @@ async function executeContentPushPlan(input) {
52127
52509
  return contentPushExecutionReportToSyncResult(report);
52128
52510
  }
52129
52511
  async function executeContentPushPlanAsCommandReport(input, dependencies = {}) {
52512
+ const preflight = preflightContentPushPlanAsCommandReport(input, dependencies);
52513
+ if (!preflight.ok) return preflight.report;
52514
+ return executePushExecutionSteps(preflight.compiled.steps, input, dependencies);
52515
+ }
52516
+ function preflightContentPushPlanAsCommandReport(input, dependencies = {}) {
52130
52517
  const executionPlan = planContentPushExecution({
52131
52518
  pushScope: input.pushScope,
52132
52519
  diff: input.diff,
52133
52520
  local: input.local
52134
52521
  });
52135
52522
  const compiled = compileContentPushExecutionPlan(executionPlan, input, dependencies);
52136
- if (!compiled.ok) return compiled.error;
52137
- return executePushExecutionSteps(compiled.value.steps, input, dependencies);
52523
+ if (!compiled.ok) {
52524
+ return { ok: false, report: compiled.error };
52525
+ }
52526
+ const preflightReport = preflightContentPushExecutionPlan(
52527
+ compiled.value.steps,
52528
+ input,
52529
+ dependencies
52530
+ );
52531
+ if (contentPushExecutionReportHasFailures(preflightReport)) {
52532
+ return { ok: false, report: preflightReport };
52533
+ }
52534
+ return { ok: true, compiled: compiled.value, report: preflightReport };
52138
52535
  }
52139
52536
  async function executePushExecutionSteps(steps, input, dependencies) {
52140
52537
  const commandReports = [];
@@ -53111,6 +53508,8 @@ function scalarEntryChanges(changes) {
53111
53508
  function setEntryPath(entry, pathParts, value) {
53112
53509
  const [head, ...rest] = pathParts;
53113
53510
  switch (head) {
53511
+ case void 0:
53512
+ throw new Error("Cannot set an empty entry merge path.");
53114
53513
  case "identifier":
53115
53514
  entry.identifier = expectStringValue(head, value);
53116
53515
  return;
@@ -53747,6 +54146,21 @@ async function executeScopedPush(output, isRemote, options, globalOpts, scopeLab
53747
54146
  }
53748
54147
  return { success: true };
53749
54148
  }
54149
+ function noContentFoundWarningDetails(contentDir) {
54150
+ return {
54151
+ contentDir,
54152
+ expectedFiles: [
54153
+ "content/pages/*.json",
54154
+ "content/entries/<type>/*.json",
54155
+ "content/navigation.json",
54156
+ "content/settings.json"
54157
+ ],
54158
+ suggestion: "Document content is read from content/**. Add file-based pages, entries, navigation, or settings, then run `riverbankcms push` again. Use `riverbankcms push-config` for schema/config only."
54159
+ };
54160
+ }
54161
+ function contentSummaryHasPushableContent(summary) {
54162
+ return summary.totalEntries > 0 || summary.pageCount > 0 || summary.hasNavigation || summary.hasSettings || summary.hasForms || summary.hasVenues || summary.hasEventCategories || summary.hasEvents || summary.hasCourses;
54163
+ }
53750
54164
  function validateMergeRemoteEntryPushOptions(input) {
53751
54165
  if (input.target !== "remote") {
53752
54166
  return {
@@ -54028,8 +54442,8 @@ ${errors}`
54028
54442
  });
54029
54443
  }
54030
54444
  const summary = await getContentSummary(contentDir);
54031
- if (summary.totalEntries === 0 && summary.pageCount === 0 && !summary.hasNavigation && !summary.hasForms && !summary.hasVenues && !summary.hasEventCategories && !summary.hasEvents && !summary.hasCourses) {
54032
- output.warn("No content found to push");
54445
+ if (!contentSummaryHasPushableContent(summary)) {
54446
+ output.warn("No content found to push", noContentFoundWarningDetails(contentDir));
54033
54447
  return { success: true };
54034
54448
  }
54035
54449
  const env = loadEnvironment(isRemote);
@@ -54137,10 +54551,11 @@ ${errors}`
54137
54551
  }
54138
54552
  if (!options.force) {
54139
54553
  output.info("Checking for stale content...");
54140
- const [localMeta, pagesMeta, navigationMeta, formsMeta] = await Promise.all([
54554
+ const [localMeta, pagesMeta, navigationMeta, settingsMeta, formsMeta] = await Promise.all([
54141
54555
  readAllMeta(contentDir),
54142
54556
  readPagesMeta(contentDir),
54143
54557
  readNavigationMeta(contentDir),
54558
+ readSettingsMeta(contentDir),
54144
54559
  readFormsMeta(contentDir)
54145
54560
  ]);
54146
54561
  const staleItems = checkForStaleContent(
@@ -54149,7 +54564,8 @@ ${errors}`
54149
54564
  pagesMeta,
54150
54565
  navigationMeta,
54151
54566
  formsMeta,
54152
- remoteContent
54567
+ remoteContent,
54568
+ settingsMeta
54153
54569
  );
54154
54570
  if (staleItems.length > 0) {
54155
54571
  output.warn(
@@ -54275,6 +54691,22 @@ ${errors}`
54275
54691
  humanDiff
54276
54692
  });
54277
54693
  if (dryRun) {
54694
+ const preflight = preflightContentPushPlanAsCommandReport({
54695
+ pushScope,
54696
+ siteId: env.siteId,
54697
+ target,
54698
+ diff,
54699
+ local: filteredLocal,
54700
+ client,
54701
+ blockFieldExtensions: cliConfig.blockFieldExtensions,
54702
+ output
54703
+ });
54704
+ const preflightResult = contentPushExecutionReportToSyncResult(preflight.report);
54705
+ if (preflightResult.errors.length > 0) {
54706
+ reportSyncResults({ output, result: preflightResult, hasErrors: true });
54707
+ process.exitCode = 1;
54708
+ return { success: false };
54709
+ }
54278
54710
  if (pushScope === "all") {
54279
54711
  if (pushAllExtraChanges?.venues.toPush.size) {
54280
54712
  output.info(
@@ -54415,6 +54847,7 @@ ${errors}`
54415
54847
  createdAt: n.createdAt
54416
54848
  })
54417
54849
  ),
54850
+ settingsUpdatedAt: metadataFlags.willUpdateSettings ? freshRemote.meta.settingsUpdatedAt ?? null : void 0,
54418
54851
  forms: mapIfUpdating(metadataFlags.willUpdateForms, freshRemote.forms, (f) => ({
54419
54852
  slug: f.slug,
54420
54853
  updatedAt: f.updatedAt,
@@ -54604,8 +55037,8 @@ Pushing ${label.toLowerCase()}...`);
54604
55037
  // src/cli/commands/push.ts
54605
55038
  var pushCommand = new Command("push").description("Push content to CMS").argument(
54606
55039
  "[scope]",
54607
- "What to push: entries, pages, navigation, forms, footer, theme, venues, event-categories, events, courses, or all (default)"
54608
- ).argument("[type]", "Content type (entries), page identifier (pages), or theme name (theme)").argument("[identifier]", 'Entry identifier (when scope is "entries" and type is set)').option("--content-dir <dir>", "Content directory (overrides config)").option("--dry-run", "Show what would be pushed without making changes").option("--yes", "Skip confirmation prompt (required for --env=remote or --env=both)").option("--force", "Push even if remote content is newer (skip stale check)").option("--force-update-asset", "Replace CMS media when identifiers conflict (local media sync only)").option("--allow-truncated", "Push even if remote content was truncated (may cause incomplete sync)").option("--json-diff [mode]", "Output JSON diff (summary or full)", "summary").option("--with-config", "Also push SDK config after content").option("--with-theme", "Also push theme when pushing all content").option("--sync-media", "Sync media files from local to remote environment").option("--overwrite-media", "When using --sync-media, overwrite target media on checksum mismatch").option(
55040
+ "What to push: entries, pages, navigation, forms, settings, footer, theme, venues, event-categories, events, courses, or all (default)"
55041
+ ).argument("[type]", "Content type (entries), page identifier (pages), or theme name (theme)").argument("[identifier]", 'Entry identifier (when scope is "entries" and type is set)').option("--content-dir <dir>", "Content directory (overrides config)").option("--dry-run", "Show what would be pushed without making changes").option("--yes", "Skip confirmation prompt (required for --env=remote or --env=both)").option("--force", "Push even if remote content is newer (skip stale check)").option("--force-update-asset", "Replace CMS media when identifiers conflict (local media sync only)").option("--allow-truncated", "Push even if remote content was truncated (may cause incomplete sync)").option("--json-diff [mode]", "Output JSON diff (summary or full)", "summary").option("--with-config", "Also push SDK schema/config after file content").option("--with-theme", "Also push theme when pushing all content").option("--sync-media", "Sync media files from local to remote environment").option("--overwrite-media", "When using --sync-media, overwrite target media on checksum mismatch").option(
54609
55042
  "--delete-missing",
54610
55043
  "[Deprecated: use --delete-orphaned] Delete CMS entries not in local file (single content type only)"
54611
55044
  ).option("--delete-orphaned", "Delete remote items not present in local files (entries, events, courses, venues, event-categories)").option("--auto-pull-stale", "Automatically pull stale content and retry push").option("--merge-remote", "Plan an entries-only three-way merge that preserves remote edits").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(
@@ -54616,7 +55049,7 @@ Examples:
54616
55049
  $ riverbankcms push --env=remote --yes # Push to production
54617
55050
  $ riverbankcms push --env=both --yes # Push to both environments
54618
55051
  $ riverbankcms push --dry-run # Preview changes
54619
- $ riverbankcms push --with-config # Push content and config together
55052
+ $ riverbankcms push --with-config # Push file content and schema/config together
54620
55053
  $ riverbankcms push --with-theme # Push content and theme together
54621
55054
  $ riverbankcms push entries # Push all entries
54622
55055
  $ riverbankcms push entries blog-post # Push specific content type
@@ -54624,6 +55057,8 @@ Examples:
54624
55057
  $ riverbankcms push pages # Push pages with blocks
54625
55058
  $ riverbankcms push pages home # Push specific page with blocks
54626
55059
  $ riverbankcms push navigation # Push navigation menus
55060
+ $ riverbankcms push settings # Push site settings
55061
+ $ riverbankcms push settings --sync-media # Push site settings and sync referenced branding media
54627
55062
  $ riverbankcms push forms # Push forms
54628
55063
  $ riverbankcms push venues # Push venues
54629
55064
  $ riverbankcms push event-categories # Push event categories
@@ -54648,11 +55083,16 @@ Sync Behavior:
54648
55083
  - Status (draft/published) is synced based on local file status
54649
55084
 
54650
55085
  Safety:
55086
+ - Preflight validation: deterministic content issues are checked before mutations
55087
+ and reported together when possible.
54651
55088
  - Stale detection: aborts if remote content is newer than last pull (use --force to override)
54652
55089
  - Truncation: aborts if remote has >100 entries per type (use --allow-truncated to override)
54653
55090
  - Remote environment (--env=remote): defaults to dry-run, requires --yes to execute
54654
55091
  - Remote-aware merge: entries-only v1 for --env=remote; run a dry-run first, then add --yes
54655
55092
  - Theme: not pushed by default (use "push theme" or --with-theme)
55093
+ - Boundaries: media uploads/storage writes and multi-endpoint CMS mutations are
55094
+ not globally transactional; preflight prevents deterministic validation failures
55095
+ before apply, but runtime/network/storage failures can still stop a push mid-run.
54656
55096
 
54657
55097
  Media Sync:
54658
55098
  Local media sync is enabled by default for push.
@@ -55112,8 +55552,8 @@ async function applyOneOffNavigationCommand(command, client) {
55112
55552
  });
55113
55553
  }
55114
55554
  function oneOffEntryCommandBinding(mutation) {
55115
- const contentType = asCliContentTypeKey(mutation.contentType);
55116
- const identifier = asCliEntryIdentifier(mutation.identifier);
55555
+ const contentType = unsafeAsCliContentTypeKey(mutation.contentType);
55556
+ const identifier = unsafeAsCliEntryIdentifier(mutation.identifier);
55117
55557
  switch (mutation.kind) {
55118
55558
  case "upsert": {
55119
55559
  const title = titleFromEntryData(mutation.data);
@@ -55160,7 +55600,7 @@ function oneOffEntryCommandBinding(mutation) {
55160
55600
  }
55161
55601
  }
55162
55602
  function oneOffPageCommandBinding(mutation) {
55163
- const identifier = asCliPageIdentifier(mutation.identifier);
55603
+ const identifier = unsafeAsCliPageIdentifier(mutation.identifier);
55164
55604
  switch (mutation.kind) {
55165
55605
  case "upsert": {
55166
55606
  const command = {
@@ -55207,10 +55647,10 @@ function oneOffPageCommandBinding(mutation) {
55207
55647
  }
55208
55648
  }
55209
55649
  function oneOffBlockCommandBinding(mutation) {
55210
- const pageIdentifier = asCliPageIdentifier(mutation.pageIdentifier);
55650
+ const pageIdentifier = unsafeAsCliPageIdentifier(mutation.pageIdentifier);
55211
55651
  switch (mutation.kind) {
55212
55652
  case "upsert": {
55213
- const identifier = asCliBlockIdentifier(mutation.blockIdentifier);
55653
+ const identifier = unsafeAsCliBlockIdentifier(mutation.blockIdentifier);
55214
55654
  const command = {
55215
55655
  type: "upsertPageBlock",
55216
55656
  ref: createBlockRef([pageIdentifier, identifier]),
@@ -55232,7 +55672,7 @@ function oneOffBlockCommandBinding(mutation) {
55232
55672
  };
55233
55673
  }
55234
55674
  case "reorder": {
55235
- const identifiers = mutation.blockIdentifiers.map(asCliBlockIdentifier);
55675
+ const identifiers = mutation.blockIdentifiers.map(unsafeAsCliBlockIdentifier);
55236
55676
  const command = {
55237
55677
  type: "reorderPageBlocks",
55238
55678
  ref: createBlocksRef([pageIdentifier]),
@@ -55259,7 +55699,7 @@ function oneOffBlockCommandBinding(mutation) {
55259
55699
  }
55260
55700
  }
55261
55701
  function oneOffNavigationCommandBinding(mutation) {
55262
- const name = asCliNavigationMenuName(mutation.menuName);
55702
+ const name = unsafeAsCliNavigationMenuName(mutation.menuName);
55263
55703
  const command = {
55264
55704
  type: "upsertNavigationMenu",
55265
55705
  ref: createNavigationRef([name]),
@@ -56137,7 +56577,7 @@ var THEME_FIELD_CATEGORY_MAP = {
56137
56577
  };
56138
56578
 
56139
56579
  // src/cli/init-docs/zod-to-markdown.ts
56140
- function isRecord12(value) {
56580
+ function isRecord13(value) {
56141
56581
  return typeof value === "object" && value !== null && !Array.isArray(value);
56142
56582
  }
56143
56583
  function isZodTypeAny(value) {
@@ -56224,6 +56664,8 @@ function unwrapSchema(schema) {
56224
56664
  function zodTypeToString(schema) {
56225
56665
  const typeName = getTypeName(schema);
56226
56666
  switch (typeName) {
56667
+ case void 0:
56668
+ return "unknown";
56227
56669
  case ZodTypeName.ZodString:
56228
56670
  return "string";
56229
56671
  case ZodTypeName.ZodNumber:
@@ -56263,7 +56705,7 @@ function extractLiteralValue(schema) {
56263
56705
  const typeName = getTypeName(schema);
56264
56706
  if (typeName !== ZodTypeName.ZodLiteral) return void 0;
56265
56707
  const def = schema._def;
56266
- if (!isRecord12(def)) return void 0;
56708
+ if (!isRecord13(def)) return void 0;
56267
56709
  return String(def.value);
56268
56710
  }
56269
56711
  function extractSchemaInfo(schema, skipFields = []) {
@@ -56333,7 +56775,7 @@ function extractFieldInfo(name, schema) {
56333
56775
  }
56334
56776
  if (typeName === ZodTypeName.ZodRecord) {
56335
56777
  const def = inner._def;
56336
- const valueSchema = isRecord12(def) ? def.valueType : void 0;
56778
+ const valueSchema = isRecord13(def) ? def.valueType : void 0;
56337
56779
  if (!isZodTypeAny(valueSchema)) {
56338
56780
  info.recordValueType = "unknown";
56339
56781
  return info;
@@ -56348,7 +56790,7 @@ function extractFieldInfo(name, schema) {
56348
56790
  }
56349
56791
  } else if (getTypeName(valueInner) === ZodTypeName.ZodRecord) {
56350
56792
  const nestedDef = valueInner._def;
56351
- const nestedValueSchema = isRecord12(nestedDef) ? nestedDef.valueType : void 0;
56793
+ const nestedValueSchema = isRecord13(nestedDef) ? nestedDef.valueType : void 0;
56352
56794
  if (!isZodTypeAny(nestedValueSchema)) {
56353
56795
  info.recordValueType = "record<string, unknown>";
56354
56796
  return info;
@@ -56359,7 +56801,7 @@ function extractFieldInfo(name, schema) {
56359
56801
  }
56360
56802
  if (typeName === ZodTypeName.ZodUnion || typeName === ZodTypeName.ZodDiscriminatedUnion) {
56361
56803
  const def = inner._def;
56362
- const optionsValue = isRecord12(def) ? def.options : void 0;
56804
+ const optionsValue = isRecord13(def) ? def.options : void 0;
56363
56805
  const options = Array.isArray(optionsValue) ? optionsValue.filter(isZodTypeAny) : [];
56364
56806
  const optionTypes = options.map((opt) => {
56365
56807
  const { inner: optInner } = unwrapSchema(opt);
@@ -57071,14 +57513,14 @@ function renderFieldList(fields3, depth, skipPatternCheck = false) {
57071
57513
  );
57072
57514
  }
57073
57515
  }
57074
- if ("fields" in field && Array.isArray(field.fields)) {
57516
+ if ("fields" in field && isFieldDefinitionArray(field.fields)) {
57075
57517
  lines.push(...renderFieldList(field.fields, depth + 1));
57076
57518
  }
57077
57519
  if ("schema" in field) {
57078
57520
  const schema = field.schema;
57079
57521
  if (schema && typeof schema === "object" && "fields" in schema) {
57080
57522
  const fields4 = schema.fields;
57081
- if (Array.isArray(fields4)) {
57523
+ if (isFieldDefinitionArray(fields4)) {
57082
57524
  lines.push(...renderFieldList(fields4, depth + 1));
57083
57525
  }
57084
57526
  }
@@ -57101,6 +57543,9 @@ function renderFieldList(fields3, depth, skipPatternCheck = false) {
57101
57543
  }
57102
57544
  return lines;
57103
57545
  }
57546
+ function isFieldDefinitionArray(value) {
57547
+ return Array.isArray(value);
57548
+ }
57104
57549
  function renderOptionsList(options, depth) {
57105
57550
  const indent = " ".repeat(depth);
57106
57551
  return options.map((option) => {
@@ -57516,7 +57961,7 @@ var SimpleCache = class {
57516
57961
  };
57517
57962
 
57518
57963
  // src/version.ts
57519
- var SDK_VERSION = "0.78.0";
57964
+ var SDK_VERSION = "0.78.2";
57520
57965
 
57521
57966
  // src/client/error.ts
57522
57967
  var RiverbankApiError = class _RiverbankApiError extends Error {
@@ -57929,9 +58374,10 @@ var CircuitOpenError = class extends Error {
57929
58374
  var prebuildModule = null;
57930
58375
  function tryRequire(modulePath) {
57931
58376
  try {
57932
- const req = Function(
58377
+ const getRequire = new Function(
57933
58378
  'return typeof require === "function" ? require : null'
57934
- )();
58379
+ );
58380
+ const req = getRequire();
57935
58381
  return req ? req(modulePath) : null;
57936
58382
  } catch {
57937
58383
  return null;
@@ -58444,8 +58890,7 @@ function createRiverbankClient(config2) {
58444
58890
  async (sig) => {
58445
58891
  return await apiClient({
58446
58892
  endpoint: "getContentByPath",
58447
- params: { siteId },
58448
- body: { path: path24, preview },
58893
+ params: { siteId, path: path24, preview: String(preview) },
58449
58894
  options: { signal: sig }
58450
58895
  });
58451
58896
  },
@@ -58495,6 +58940,8 @@ function createRiverbankClient(config2) {
58495
58940
  orderParam = "published_at.asc";
58496
58941
  } else if (order === "title") {
58497
58942
  orderParam = "title.asc";
58943
+ } else if (order === "manual") {
58944
+ orderParam = "manual.asc";
58498
58945
  }
58499
58946
  const apiParams = {
58500
58947
  siteId,
@@ -61672,11 +62119,14 @@ function collectFieldIds(fields3) {
61672
62119
  for (const field of fieldList) {
61673
62120
  ids.add(field.id);
61674
62121
  if (field.schema && typeof field.schema === "object" && "fields" in field.schema) {
61675
- collect(field.schema.fields);
62122
+ const nestedFields = field.schema.fields;
62123
+ if (isFieldIdRecordArray(nestedFields)) {
62124
+ collect(nestedFields);
62125
+ }
61676
62126
  }
61677
- if (field.tabs && Array.isArray(field.tabs)) {
62127
+ if (isRecordArray(field.tabs)) {
61678
62128
  for (const tab of field.tabs) {
61679
- if (tab.fields && Array.isArray(tab.fields)) {
62129
+ if (isFieldIdRecordArray(tab.fields)) {
61680
62130
  collect(tab.fields);
61681
62131
  }
61682
62132
  }
@@ -61693,6 +62143,12 @@ function collectFieldIds(fields3) {
61693
62143
  collect(fields3);
61694
62144
  return ids;
61695
62145
  }
62146
+ function isRecordArray(value) {
62147
+ return Array.isArray(value);
62148
+ }
62149
+ function isFieldIdRecordArray(value) {
62150
+ return Array.isArray(value) && value.every((item) => typeof item === "object" && item !== null && typeof item.id === "string");
62151
+ }
61696
62152
  var CONTENT_NODE_TYPES = ["text", "richText", "media", "button", "link"];
61697
62153
  function collectFieldInfo(fields3) {
61698
62154
  const topLevelFieldIds = /* @__PURE__ */ new Set();