riverbankcms 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -946,7 +946,7 @@ riverbankcms event occurrence delete summer-fest summer-run <occurrence-uuid> --
946
946
 
947
947
  `event upsert` and `push events` accept canonical event files with `path` and `blocks`. Events use native page authority: an `eventOffering` or `eventSeries` subject owns a page surface, and that surface owns its route, field content, publication state, and slots. `path` updates the page-surface route. `blocks` maps slot keys to surface-slot blocks, for example `blocks.main` for the built-in event template. Use stable block identifiers so repeat pushes update existing slot blocks safely. Unknown slot keys or block kinds fail validation; default slots accept enabled SDK `custom.*` blocks, while explicit template `allowedBlocks` lists remain authoritative. Ordinary editorial entries continue to use the separate `entry` commands and content-entry model described above.
948
948
 
949
- For an online Event page, updating `content` publishes its field content immediately, matching the dashboard Content tab. The same save updates the image shown in run listings. Route, block and layout changes retain their separate draft and publish flow.
949
+ When the Event page is online, a push publishes the page once its content, route, identity and blocks are written, so everything pending on the page goes live, including anything saved as a draft in the dashboard. The same publish updates the image shown in run listings. While the page is offline, a push saves a draft that goes live when the page is put online. A push whose content matches the page writes no new content.
950
950
 
951
951
  #### Taking an event offline and deleting it
952
952
 
@@ -1504,3 +1504,9 @@ riverbankcms push --env=both --yes
1504
1504
  # Push to both and verify both targets are clean afterwards
1505
1505
  riverbankcms push --env=both --yes --verify-noop
1506
1506
  ```
1507
+
1508
+ ### Block order and selective pushes
1509
+
1510
+ A block reorder must include every block that will remain on the page. Normal push removes remote blocks absent from the local page, then reorders the complete remaining list. If a selective push keeps a remote-only block or skips creating a listed block, preflight rejects the reorder and names the affected blocks before making changes. Include the missing block locally or select the required create/delete operation.
1511
+
1512
+ A positional block upsert inserts or moves the block at that position and shifts the remaining blocks into contiguous positions. Omitting position keeps an existing block in place and appends a new block.
@@ -748,7 +748,8 @@ Footer links are managed via the site's footer navigation menu (see `content/nav
748
748
  listings and search). A run that has not gone live yet is a "draft"
749
749
  `status`, not a listing choice.
750
750
  - Event page content is owned by the native `eventOffering` or `eventSeries` page-surface subject.
751
- - Updating an online Event's `content` through `event upsert` or `push events` publishes its field content immediately, as the dashboard Content tab does. Its route, blocks and layout keep their separate draft and publish flow.
751
+ - The listing image (the picture on the event's card in listings) is always the event page's `content.image`. Changing `content.image` changes the card too, on every run that shares the page.
752
+ - `event upsert` and `push events` save an Event's page as a draft and, when the page is online, then publish it, so everything pending on the page goes live (the dashboard's own saves stay drafts until someone publishes). An offline page keeps the draft until it is put online.
752
753
  - `blocks` writes to the event page surface's template-defined surface slots. The default event template declares `blocks.main`.
753
754
  - Use stable block `identifier` values. Re-pushing the same event updates matching slot blocks instead of creating duplicates.
754
755
  - Default surface slots accept built-in content blocks plus enabled SDK custom blocks. If a template sets `allowedBlocks`, that explicit list is authoritative.
@@ -763,6 +764,11 @@ retiming remain an explicit capability gap; use `riverbankcms event occurrence
763
764
  list|add|update|cancel|delete` for those operational changes. Cancelled rows are
764
765
  operational tombstones and are not recreated from portable content.
765
766
 
767
+ Built-in event cards and the booking-page catalogue write dates in the style of
768
+ the site's default booking time zone: a `Europe/*` zone reads "Friday, 16
769
+ October 2026" and "10:00 to 16:00", while zones with no match read the US way.
770
+ The times themselves are always in each event's own `timeZone`.
771
+
766
772
  ---
767
773
 
768
774
  ## Configuration Reference
@@ -304,3 +304,9 @@ riverbankcms delete block home old-section --yes
304
304
  - **Custom Blocks** - Create site-specific blocks: see `custom-block.md`
305
305
  - **Content Types** - Embed content entries on pages: see `content-types.md`
306
306
  - **CMS-ify a Page** - Convert hard-coded pages to CMS-driven: see `cmsify-page.md`
307
+
308
+ ### Block order and selective pushes
309
+
310
+ A block reorder must include every block that will remain on the page. Normal push removes remote blocks absent from the local page, then reorders the complete remaining list. If a selective push keeps a remote-only block or skips creating a listed block, preflight rejects the reorder and names the affected blocks before making changes. Include the missing block locally or select the required create/delete operation.
311
+
312
+ A positional block upsert inserts or moves the block at that position and shifts the remaining blocks into contiguous positions. Omitting position keeps an existing block in place and appends a new block.
@@ -214,3 +214,9 @@ Creating a page on a path that another page or route already uses fails with a `
214
214
  - **Content Types** - Create structured content with pages: see `content-types.md`
215
215
  - **CMS-ify a Page** - Convert hard-coded pages to CMS-driven: see `cmsify-page.md`
216
216
  - **Publish Workflow** - Publishing content safely: see `publish-workflow.md`
217
+
218
+ ### Block order and selective pushes
219
+
220
+ A block reorder must include every block that will remain on the page. Normal push removes remote blocks absent from the local page, then reorders the complete remaining list. If a selective push keeps a remote-only block or skips creating a listed block, preflight rejects the reorder and names the affected blocks before making changes. Include the missing block locally or select the required create/delete operation.
221
+
222
+ A positional block upsert inserts or moves the block at that position and shifts the remaining blocks into contiguous positions. Omitting position keeps an existing block in place and appends a new block.
@@ -112,13 +112,13 @@ Page workflows patch route metadata only:
112
112
 
113
113
  - `draftTitle`
114
114
  - `draftSlug`
115
- - `draftStatus`
116
- - `scheduledPublishAt`
117
115
  - `draftMetaTitle`
118
116
  - `draftMetaDescription`
119
117
  - `canonicalUrl`
120
118
  - `ogImageId`
121
119
 
120
+ Status and schedule aren't patchable: publishing and scheduling are lifecycle operations, and a patch that includes `draftStatus` or `scheduledPublishAt` is rejected.
121
+
122
122
  If the workflow returns no `draftContentPatch`, it must make changes through management API endpoints or leave the draft unchanged.
123
123
 
124
124
  ## Verification
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { a as classifySdkEventSchedule, i as sdkEventUpsertOptionalFieldSchemas, n as sdkCourseBookingSettingsSchema, o as classifySdkEventBookingOffer } from "./sdk-event-upsert-CuDl9Gk1.mjs";
3
- import { l as EVENT_PRESET_VALUES } from "./src-9YtMip19.mjs";
2
+ import { a as classifySdkEventSchedule, i as sdkEventUpsertOptionalFieldSchemas, n as sdkCourseBookingSettingsSchema, o as classifySdkEventBookingOffer } from "./sdk-event-upsert-CqCQwcwu.mjs";
3
+ import { l as EVENT_PRESET_VALUES } from "./src-CxEAuQpf.mjs";
4
4
  import { z } from "zod";
5
5
 
6
6
  //#region ../blocks/src/lib/typeGuards.ts
@@ -293,44 +293,6 @@ const ROUTE_METADATA_MANIFEST = {
293
293
  maxLength: 96,
294
294
  ui: { showSlugPreview: true }
295
295
  },
296
- {
297
- id: "draftStatus",
298
- type: "select",
299
- label: "Draft status",
300
- description: "Schedule to publish automatically, or keep as draft.",
301
- required: true,
302
- defaultValue: "draft",
303
- options: [
304
- {
305
- value: "draft",
306
- label: "Draft"
307
- },
308
- {
309
- value: "scheduled",
310
- label: "Scheduled"
311
- },
312
- {
313
- value: "published",
314
- label: "Published"
315
- },
316
- {
317
- value: "archived",
318
- label: "Archived"
319
- }
320
- ],
321
- multiple: false
322
- },
323
- {
324
- id: "scheduledPublishAt",
325
- type: "datetime",
326
- label: "Publish at",
327
- description: "When scheduled, the entry will publish at this time.",
328
- required: false,
329
- ui: { visibleWhen: {
330
- field: "draftStatus",
331
- equals: "scheduled"
332
- } }
333
- },
334
296
  {
335
297
  id: "draftMetaTitle",
336
298
  type: "text",
@@ -360,12 +322,6 @@ const ROUTE_METADATA_MANIFEST = {
360
322
  ],
361
323
  slots: []
362
324
  };
363
- const METADATA_WORKFLOW_FIELDS = {
364
- title: "draftTitle",
365
- slug: "draftSlug",
366
- status: "draftStatus",
367
- publishAt: "scheduledPublishAt"
368
- };
369
325
  const HOMEPAGE_PAGE_ROUTE_SLUG = { kind: "homepage" };
370
326
  function asNonEmptyPageRouteSlug(value) {
371
327
  return value;
@@ -397,30 +353,10 @@ function resolvePageRouteSlug(entry, currentSlug) {
397
353
  return pageRouteSlugFromEditorValue(entry.draft.slug);
398
354
  }
399
355
  const ROUTE_METADATA_MANAGED_FIELDS_BY_TYPE = {
400
- event: [
401
- "draftTitle",
402
- "draftSlug",
403
- "draftStatus",
404
- "scheduledPublishAt"
405
- ],
406
- product: [
407
- "draftTitle",
408
- "draftSlug",
409
- "draftStatus",
410
- "scheduledPublishAt"
411
- ],
412
- "product-category": [
413
- "draftTitle",
414
- "draftSlug",
415
- "draftStatus",
416
- "scheduledPublishAt"
417
- ],
418
- "team-member": [
419
- "draftTitle",
420
- "draftSlug",
421
- "draftStatus",
422
- "scheduledPublishAt"
423
- ]
356
+ event: ["draftTitle", "draftSlug"],
357
+ product: ["draftTitle", "draftSlug"],
358
+ "product-category": ["draftTitle", "draftSlug"],
359
+ "team-member": ["draftTitle", "draftSlug"]
424
360
  };
425
361
  const EMPTY_METADATA_FIELDS = [];
426
362
  function normalizeContentTypeKey(typeKey) {
@@ -1253,8 +1189,6 @@ function createMetadataStateFromSnapshot(snapshot) {
1253
1189
  const values = {
1254
1190
  draftTitle: snapshot.draft.title,
1255
1191
  draftSlug: snapshot.draft.slug,
1256
- draftStatus: snapshot.draft.status,
1257
- scheduledPublishAt: snapshot.draft.publishAt,
1258
1192
  draftMetaTitle: snapshot.route.draftMetaTitle ?? null,
1259
1193
  draftMetaDescription: snapshot.route.draftMetaDescription ?? null,
1260
1194
  ogImageId: snapshot.route.ogImageId ?? null
@@ -1264,6 +1198,13 @@ function createMetadataStateFromSnapshot(snapshot) {
1264
1198
  baseline: { ...values }
1265
1199
  };
1266
1200
  }
1201
+ function routeLifecycleContext(snapshot) {
1202
+ if (snapshot.kind === "non-routable") return null;
1203
+ return {
1204
+ draftStatus: snapshot.draft.status,
1205
+ scheduledPublishAt: snapshot.draft.publishAt
1206
+ };
1207
+ }
1267
1208
  /**
1268
1209
  * Extract published metadata values from a snapshot.
1269
1210
  * Used to set the publishedBaseline for unpublished changes detection.
@@ -1285,8 +1226,6 @@ function getPublishedMetadataFromSnapshot(snapshot, routing) {
1285
1226
  return {
1286
1227
  draftTitle: publishedTitle,
1287
1228
  draftSlug: publishedSlug,
1288
- draftStatus: snapshot.published.status ?? snapshot.draft.status ?? "draft",
1289
- scheduledPublishAt: null,
1290
1229
  draftMetaTitle: snapshot.route.publishedMetaTitle ?? null,
1291
1230
  draftMetaDescription: snapshot.route.publishedMetaDescription ?? null,
1292
1231
  ogImageId: snapshot.route.ogImageId ?? null
@@ -1308,16 +1247,12 @@ function buildToolbarState(snapshot, context, options) {
1308
1247
  }
1309
1248
  return "Not yet published";
1310
1249
  };
1311
- const { status: statusField } = METADATA_WORKFLOW_FIELDS;
1312
1250
  const publishedMessage = formatPublishMessage({
1313
1251
  status: snapshot.status,
1314
1252
  publishedAt: snapshot.published.publishAt,
1315
1253
  scheduledAt: snapshot.draft.publishAt
1316
1254
  });
1317
- let publishLabel = `Publish ${options.entityLabel.toLowerCase()}`;
1318
- if (statusField && context.values[statusField] === "scheduled") {
1319
- publishLabel = "Schedule publish";
1320
- }
1255
+ const publishLabel = routeLifecycleContext(snapshot)?.draftStatus === "scheduled" ? "Publish now" : `Publish ${options.entityLabel.toLowerCase()}`;
1321
1256
  return {
1322
1257
  currentStatus: snapshot.status,
1323
1258
  publishLabel,
@@ -2040,20 +1975,20 @@ const EVENT_CONTENT_TYPE_SCHEMA = {
2040
1975
  id: "summary",
2041
1976
  type: "textarea",
2042
1977
  label: "Short introduction",
2043
- description: "Write one or two sentences that help people quickly understand what this is. It appears wherever the event is listed and near the top of its page.",
1978
+ description: "Shown in your listings and search results, and at the top of its page.",
2044
1979
  rows: 3
2045
1980
  },
2046
1981
  {
2047
1982
  id: "image",
2048
1983
  type: "media",
2049
1984
  label: "Event image",
2050
- description: "Choose the main image people will see wherever the event is listed and on its page."
1985
+ description: "At the top of its page and beside it in your listings."
2051
1986
  },
2052
1987
  {
2053
1988
  id: "body",
2054
1989
  type: "richText",
2055
- label: "About this event",
2056
- description: "Add the main information people need before booking—what to expect, who it’s for, what’s included, and anything they should bring or know."
1990
+ label: "Full description",
1991
+ description: "The main text on its page, under the introduction."
2057
1992
  }
2058
1993
  ],
2059
1994
  routing: {
@@ -3340,7 +3275,6 @@ const DEFAULT_TEMPLATE_DEFINITIONS = {
3340
3275
  maxTickets: "5",
3341
3276
  showVenue: true,
3342
3277
  showCapacity: true,
3343
- successMessage: "Thank you for registering! Check your email for confirmation details.",
3344
3278
  buttonText: "Complete Registration",
3345
3279
  buttonVariant: "primary"
3346
3280
  },
@@ -4710,6 +4644,25 @@ function removeTemplateBlockBinding(allBindings, blockId, propId) {
4710
4644
  };
4711
4645
  }
4712
4646
 
4647
+ //#endregion
4648
+ //#region ../content-model/src/entry-slots/serializeAllowedBlocks.ts
4649
+ function serializeEntrySlotAllowedBlocks(definition) {
4650
+ switch (definition.allowedBlocks.kind) {
4651
+ case "default": return {
4652
+ kind: "default",
4653
+ blockKinds: [...definition.allowedBlocks.blockKinds]
4654
+ };
4655
+ case "restricted": return {
4656
+ kind: "restricted",
4657
+ blockKinds: [...definition.allowedBlocks.blockKinds]
4658
+ };
4659
+ case "none": return {
4660
+ kind: "none",
4661
+ blockKinds: []
4662
+ };
4663
+ }
4664
+ }
4665
+
4713
4666
  //#endregion
4714
4667
  //#region ../content-model/src/entry-slots/sdkBlocks.ts
4715
4668
  const defaultContentSchema = z.record(z.string(), z.unknown());
@@ -4799,7 +4752,6 @@ const eventRunInputSchema = z.object({
4799
4752
  categoryRef: z.string().nullable().optional(),
4800
4753
  formRef: z.string().nullable().optional(),
4801
4754
  settings: z.record(z.string(), z.unknown()).optional(),
4802
- presentation: z.record(z.string(), z.unknown()).nullable().optional(),
4803
4755
  tags: z.array(z.string()).optional()
4804
4756
  }).strict();
4805
4757
  const eventUpsertInputSchema = z.object({
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { t as loadConfigFile } from "./load-config-D0Qfqh2m.mjs";
3
+
4
+ export { loadConfigFile };
@@ -7,7 +7,7 @@ import { existsSync as existsSync$1 } from "fs";
7
7
  import { fileURLToPath } from "url";
8
8
 
9
9
  //#region package.json
10
- var version = "0.12.0";
10
+ var version = "0.14.0";
11
11
  var peerDependencies = { "@riverbankcms/sdk": ">=0.139.0 <1.0.0" };
12
12
  var package_default = {
13
13
  name: "riverbankcms",
@@ -83,7 +83,7 @@ var package_default = {
83
83
  //#endregion
84
84
  //#region src/version.ts
85
85
  /** The package manifest is the source-run fallback; builds inject this value. */
86
- const CLI_VERSION = typeof "0.12.0" === "string" ? "0.12.0" : version;
86
+ const CLI_VERSION = typeof "0.14.0" === "string" ? "0.14.0" : version;
87
87
  /**
88
88
  * The CLI's SDK peer range is bundled from the CLI manifest alongside its
89
89
  * version. Runtime config loading uses this value as the single compatibility
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { T as eventBookingOfferIntentSchema, d as stableStringify, et as themeSchema, gr as asAppearancePresetId, hn as pageDesignIntentSchemaVersion, ln as buttonStyleSelectionSchema, mn as pageDesignBoundaryTreatmentSchema, n as sdkCourseBookingSettingsSchema, r as sdkEventOccurrenceInputSchema, s as eventVisibilitySchema, vr as asPageFlowPresetId, yr as asSiteStyleId } from "./sdk-event-upsert-CuDl9Gk1.mjs";
3
- import { At as unsafeAsOriginalFilename, Bt as unsafeAsStoragePath, Ct as unsafeAsDetectedMimeType, Dt as unsafeAsFileChecksumSha256, Et as unsafeAsEventSeriesId, Ft as unsafeAsSiteFontId, Ht as unsafeAsUserId, It as unsafeAsSiteId, J as parseUtcIsoDateTimeString, Lt as unsafeAsSiteScopedStoragePath, Mt as unsafeAsPositiveSeconds, Nt as unsafeAsProductId, Ot as unsafeAsMediaAssetId, Pt as unsafeAsSafeDownloadFilename, Tt as unsafeAsEventOfferingId, Ut as err, Vt as unsafeAsUploadSessionId, Wt as ok, a as parseVerticalId, bt as unsafeAsBookingSessionId, ct as fromArray, dt as assertNever, gt as parseSiteId, i as canonicalizeConfiguredBookingVerticalConfig, j as parseFooterCompositionV1, jt as unsafeAsPositiveByteCount, kt as unsafeAsOccurrenceId, l as EVENT_PRESET_VALUES, lt as mapNonEmptyArray, o as parseVerticalPresetId, s as resolveSiteVerticalBookingConfig, v as exposeSecret, wt as unsafeAsEntitlementId, xt as unsafeAsDeclaredMimeType, yt as unsafeAsBookingRequirementId, zt as unsafeAsStorageBucketName } from "./src-9YtMip19.mjs";
2
+ import { T as eventBookingOfferIntentSchema, d as stableStringify, et as themeSchema, gr as asAppearancePresetId, hn as pageDesignIntentSchemaVersion, ln as buttonStyleSelectionSchema, mn as pageDesignBoundaryTreatmentSchema, n as sdkCourseBookingSettingsSchema, r as sdkEventOccurrenceInputSchema, s as eventVisibilitySchema, vr as asPageFlowPresetId, yr as asSiteStyleId } from "./sdk-event-upsert-CqCQwcwu.mjs";
3
+ import { At as unsafeAsOriginalFilename, Bt as unsafeAsStoragePath, Ct as unsafeAsDetectedMimeType, Dt as unsafeAsFileChecksumSha256, Et as unsafeAsEventSeriesId, Ft as unsafeAsSiteFontId, Ht as unsafeAsUserId, It as unsafeAsSiteId, J as parseUtcIsoDateTimeString, Lt as unsafeAsSiteScopedStoragePath, Mt as unsafeAsPositiveSeconds, Nt as unsafeAsProductId, Ot as unsafeAsMediaAssetId, Pt as unsafeAsSafeDownloadFilename, Tt as unsafeAsEventOfferingId, Ut as err, Vt as unsafeAsUploadSessionId, Wt as ok, a as parseVerticalId, bt as unsafeAsBookingSessionId, ct as fromArray, dt as assertNever, gt as parseSiteId, i as canonicalizeConfiguredBookingVerticalConfig, j as parseFooterCompositionV1, jt as unsafeAsPositiveByteCount, kt as unsafeAsOccurrenceId, l as EVENT_PRESET_VALUES, lt as mapNonEmptyArray, o as parseVerticalPresetId, s as resolveSiteVerticalBookingConfig, v as exposeSecret, wt as unsafeAsEntitlementId, xt as unsafeAsDeclaredMimeType, yt as unsafeAsBookingRequirementId, zt as unsafeAsStorageBucketName } from "./src-CxEAuQpf.mjs";
4
4
  import * as fs$1 from "fs/promises";
5
5
  import * as path$1 from "path";
6
6
  import { z } from "zod";
@@ -143,6 +143,40 @@ function sdkCommandApplicationResultSchema(value) {
143
143
  }).passthrough();
144
144
  }
145
145
 
146
+ //#endregion
147
+ //#region ../api/src/sdkBlockUpsertContracts.ts
148
+ const sdkBlockAppearanceChoiceSchema = z.discriminatedUnion("kind", [z.object({
149
+ kind: z.literal("pinned"),
150
+ appearancePresetId: z.string().min(1).transform(asAppearancePresetId)
151
+ }), z.object({ kind: z.literal("automatic") })]);
152
+ const sdkBlockAppearanceOutcomeSchema = z.discriminatedUnion("kind", [z.object({
153
+ kind: z.literal("applied"),
154
+ choice: sdkBlockAppearanceChoiceSchema,
155
+ effect: z.enum(["updated", "unchanged"])
156
+ }), z.object({
157
+ kind: z.literal("not-applied"),
158
+ code: z.enum(["STALE_PAGE_DESIGN_STATE", "SAVE_PAGE_DESIGN_STATE_FAILED"]),
159
+ message: z.string(),
160
+ retryable: z.literal(true)
161
+ })]);
162
+ const pageBlockDesignSyncWarningSchema = z.object({
163
+ kind: z.enum([
164
+ "blocked",
165
+ "failed",
166
+ "skipped-invalid"
167
+ ]),
168
+ operation: z.enum([
169
+ "create",
170
+ "update",
171
+ "delete",
172
+ "reorder"
173
+ ]),
174
+ message: z.string(),
175
+ blocker: z.string().optional(),
176
+ source: z.enum(["draft", "published-fallback"]).optional(),
177
+ reason: z.string().optional()
178
+ });
179
+
146
180
  //#endregion
147
181
  //#region ../api/src/sdkOccurrenceResponseSchemas.ts
148
182
  const identifierSchema$1 = z.string().min(1);
@@ -183,7 +217,11 @@ const sdkListEventOccurrencesResponseSchema = z.object({
183
217
  });
184
218
  const sdkEventOccurrenceResponseSchema = z.object({ occurrence: sdkManagementEventOccurrenceSchema });
185
219
  const sdkDeleteEventOccurrenceResponseSchema = z.object({ deleted: z.literal(true) });
186
- const sdkReorderResponseSchema = z.object({ reordered: z.literal(true) });
220
+ const sdkReorderResponseSchema = z.object({
221
+ reordered: z.literal(true),
222
+ effect: sdkCommandEffectSchema,
223
+ designSyncWarning: pageBlockDesignSyncWarningSchema.optional()
224
+ });
187
225
 
188
226
  //#endregion
189
227
  //#region ../api/src/sdkPageDesign.ts
@@ -706,6 +744,7 @@ const sdkPullSettingsSchema = sdkSettingsUpdateSchema.extend({
706
744
  seoDefaults: sdkSeoDefaultsSchema.nullable(),
707
745
  verticalConfig: sdkConfiguredBookingVerticalConfigSchema.optional()
708
746
  });
747
+ /** A form's schema as the SDK pulls it; the push route extends it. */
709
748
  const sdkPullFormSchema = z.object({
710
749
  version: z.string().optional(),
711
750
  fields: z.array(z.object({
@@ -715,6 +754,7 @@ const sdkPullFormSchema = z.object({
715
754
  required: z.boolean().optional(),
716
755
  placeholder: z.string().optional(),
717
756
  helpText: z.string().optional(),
757
+ layout: z.object({ width: z.enum(["full", "half"]).optional() }).optional(),
718
758
  options: z.array(z.object({
719
759
  value: z.string(),
720
760
  label: z.string()
@@ -810,7 +850,7 @@ const sdkPullEventRunSchema = z.object({
810
850
  categoryRef: z.string().nullable(),
811
851
  formRef: z.string().nullable(),
812
852
  settings: sdkJsonObjectSchema$1,
813
- presentation: sdkJsonObjectSchema$1.nullable(),
853
+ presentation: z.unknown().optional(),
814
854
  tags: z.array(z.string()),
815
855
  updatedAt: sdkTimestampSchema$2,
816
856
  createdAt: sdkTimestampSchema$2
@@ -892,23 +932,6 @@ const sdkPullEventsResponseSchema = z.object({
892
932
  meta: sdkPullMetaSchema
893
933
  });
894
934
 
895
- //#endregion
896
- //#region ../api/src/sdkBlockUpsertContracts.ts
897
- const sdkBlockAppearanceChoiceSchema = z.discriminatedUnion("kind", [z.object({
898
- kind: z.literal("pinned"),
899
- appearancePresetId: z.string().min(1).transform(asAppearancePresetId)
900
- }), z.object({ kind: z.literal("automatic") })]);
901
- const sdkBlockAppearanceOutcomeSchema = z.discriminatedUnion("kind", [z.object({
902
- kind: z.literal("applied"),
903
- choice: sdkBlockAppearanceChoiceSchema,
904
- effect: z.enum(["updated", "unchanged"])
905
- }), z.object({
906
- kind: z.literal("not-applied"),
907
- code: z.enum(["STALE_PAGE_DESIGN_STATE", "SAVE_PAGE_DESIGN_STATE_FAILED"]),
908
- message: z.string(),
909
- retryable: z.literal(true)
910
- })]);
911
-
912
935
  //#endregion
913
936
  //#region ../api/src/sdkManagementResponseSchemas.ts
914
937
  const sdkIdentifierSchema = z.string().min(1);
@@ -978,6 +1001,7 @@ const sdkUpsertPagePublishResponseSchema = sdkCommandApplicationResultSchema(sdk
978
1001
  const sdkUpsertPageResponseSchema = z.union([sdkUpsertPageDraftResponseSchema, sdkUpsertPagePublishResponseSchema]);
979
1002
  const sdkUpsertEntryResponseSchema = z.union([sdkUpsertEntryDraftResponseSchema, sdkUpsertEntryPublishResponseSchema]);
980
1003
  const sdkDeleteResponseSchema = sdkCommandApplicationResultSchema(z.object({ deleted: z.literal(true) }));
1004
+ const sdkDeleteBlockResponseSchema = sdkDeleteResponseSchema.extend({ designSyncWarning: pageBlockDesignSyncWarningSchema.optional() });
981
1005
  const sdkBlockContentWarningSchema = z.object({
982
1006
  field: z.string(),
983
1007
  code: z.literal("theme-unavailable-variant"),
@@ -986,7 +1010,8 @@ const sdkBlockContentWarningSchema = z.object({
986
1010
  });
987
1011
  const sdkUpsertBlockResponseSchema = sdkCommandApplicationResultSchema(sdkManagementBlockSchema).extend({
988
1012
  warnings: z.array(sdkBlockContentWarningSchema).optional(),
989
- appearance: sdkBlockAppearanceOutcomeSchema.optional()
1013
+ appearance: sdkBlockAppearanceOutcomeSchema.optional(),
1014
+ designSyncWarning: pageBlockDesignSyncWarningSchema.optional()
990
1015
  });
991
1016
  const sdkPatchPageBlockResponseSchema = z.object({
992
1017
  block: z.object({
@@ -1119,10 +1144,16 @@ function isDeleteMutationPath(path$2) {
1119
1144
  /^\/events\/[^/]+$/
1120
1145
  ].some((pattern) => pattern.test(path$2));
1121
1146
  }
1122
- function nestedMutationSchema(method, path$2) {
1147
+ function blockMutationSchema(method, path$2) {
1123
1148
  if (method === "POST" && /^\/pages\/[^/]+\/blocks$/.test(path$2)) return sdkUpsertBlockResponseSchema;
1124
1149
  if (method === "POST" && /^\/pages\/[^/]+\/blocks\/reorder$/.test(path$2)) return sdkReorderResponseSchema;
1125
1150
  if (method === "PATCH" && /^\/pages\/[^/]+\/blocks\/[^/]+$/.test(path$2)) return sdkPatchPageBlockResponseSchema;
1151
+ if (method === "DELETE" && /^\/pages\/[^/]+\/blocks\/[^/]+$/.test(path$2)) return sdkDeleteBlockResponseSchema;
1152
+ return undefined;
1153
+ }
1154
+ function nestedMutationSchema(method, path$2) {
1155
+ const blockSchema = blockMutationSchema(method, path$2);
1156
+ if (blockSchema) return blockSchema;
1126
1157
  if (method === "POST" && /^\/entries\/[^/]+\/[^/]+\/(publish|unpublish)$/.test(path$2)) {
1127
1158
  return sdkCommandApplicationResultSchema(sdkUpsertEntryDraftResponseSchema.shape.value);
1128
1159
  }
@@ -2547,12 +2578,23 @@ function normalizeDownloadFilename(value) {
2547
2578
  const FILE_STORAGE_BUCKETS = {
2548
2579
  publicSite: unsafeAsStorageBucketName("media"),
2549
2580
  privateSite: unsafeAsStorageBucketName("site-files-private"),
2550
- temporary: unsafeAsStorageBucketName("temp-uploads")
2581
+ temporary: unsafeAsStorageBucketName("temp-uploads"),
2582
+ siteAssets: unsafeAsStorageBucketName("site-assets"),
2583
+ siteFonts: unsafeAsStorageBucketName("site-fonts"),
2584
+ bookingRequirementDocuments: unsafeAsStorageBucketName("booking-requirement-documents")
2551
2585
  };
2552
2586
  const PUBLIC_SITE_FILE_STORAGE_BUCKETS = [
2553
2587
  FILE_STORAGE_BUCKETS.publicSite,
2554
- unsafeAsStorageBucketName("site-assets"),
2555
- unsafeAsStorageBucketName("site-fonts")
2588
+ FILE_STORAGE_BUCKETS.siteAssets,
2589
+ FILE_STORAGE_BUCKETS.siteFonts
2590
+ ];
2591
+ const SITE_STORAGE_BUCKETS = [
2592
+ FILE_STORAGE_BUCKETS.publicSite,
2593
+ FILE_STORAGE_BUCKETS.privateSite,
2594
+ FILE_STORAGE_BUCKETS.temporary,
2595
+ FILE_STORAGE_BUCKETS.siteAssets,
2596
+ FILE_STORAGE_BUCKETS.siteFonts,
2597
+ FILE_STORAGE_BUCKETS.bookingRequirementDocuments
2556
2598
  ];
2557
2599
  const FILE_UPLOAD_STAGING_PREFIX = "temp-file-uploads";
2558
2600
  const DURABLE_FILE_STORAGE_PREFIX = "sites";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { Ut as err, Wt as ok, gt as parseSiteId } from "./src-9YtMip19.mjs";
2
+ import { Ut as err, Wt as ok, gt as parseSiteId } from "./src-CxEAuQpf.mjs";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { dirname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import "../src-9YtMip19.mjs";
3
- import { a as prepareScaffoldExecution, d as loadGeneratedPackageRanges, i as preflightScaffoldTargets, l as deriveGeneratedPackageRanges, o as writeScaffoldFiles, r as preflightScaffoldPlan, s as deriveScaffoldLocalManifest, t as deriveScaffoldPlan, u as findPackageManifestPath } from "../plan-DzYyb_iu.mjs";
2
+ import "../src-CxEAuQpf.mjs";
3
+ import { a as prepareScaffoldExecution, d as loadGeneratedPackageRanges, i as preflightScaffoldTargets, l as deriveGeneratedPackageRanges, o as writeScaffoldFiles, r as preflightScaffoldPlan, s as deriveScaffoldLocalManifest, t as deriveScaffoldPlan, u as findPackageManifestPath } from "../plan-mb_YslEh.mjs";
4
4
 
5
5
  export { deriveGeneratedPackageRanges, deriveScaffoldLocalManifest, deriveScaffoldPlan, findPackageManifestPath, loadGeneratedPackageRanges, preflightScaffoldPlan, preflightScaffoldTargets, prepareScaffoldExecution, writeScaffoldFiles };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { A as footerNavigationLayouts, F as isPresent, J as parseUtcIsoDateTimeString, N as isCanonicalRichTextDoc, Q as parseBookingTimeZone, Ut as err, Wt as ok, b as stableJsonStringify, dt as assertNever, j as parseFooterCompositionV1, l as EVENT_PRESET_VALUES, n as NAVIGATION_LOCATIONS, s as resolveSiteVerticalBookingConfig, u as ORDINARY_EVENT_PRESET_VALUES } from "./src-9YtMip19.mjs";
2
+ import { A as footerNavigationLayouts, F as isPresent, J as parseUtcIsoDateTimeString, N as isCanonicalRichTextDoc, Q as parseBookingTimeZone, Ut as err, Wt as ok, b as stableJsonStringify, dt as assertNever, j as parseFooterCompositionV1, l as EVENT_PRESET_VALUES, n as NAVIGATION_LOCATIONS, s as resolveSiteVerticalBookingConfig, u as ORDINARY_EVENT_PRESET_VALUES } from "./src-CxEAuQpf.mjs";
3
3
  import "node:module";
4
4
  import { z } from "zod";
5
5
 
@@ -5741,7 +5741,6 @@ function reducePageDesignIntentForStructureEvent(intent, event) {
5741
5741
  };
5742
5742
  case "block-removed": return removeBlockFromPageDesignIntent(intent, event.blockId);
5743
5743
  case "blocks-reordered": return pruneBoundaryPinsForOrder(intent, event.orderedBlockIds);
5744
- case "block-kind-changed": return changeBlockKindInPageDesignIntent(intent, event);
5745
5744
  case "block-duplicated": return duplicateBlockInPageDesignIntent(intent, event);
5746
5745
  default: return assertNever$1(event, "Unhandled page design structure event");
5747
5746
  }
@@ -5864,33 +5863,6 @@ function pruneBoundaryPinsForOrder(intent, orderedBlockIds) {
5864
5863
  issues: removedBoundaryIssues
5865
5864
  };
5866
5865
  }
5867
- /**
5868
- * A block-kind change updates the pin's current block kind so future resolution sees
5869
- * the current tree. If the pinned Look is incompatible, the pin remains stored and
5870
- * the resolver must render a safe auto fallback while the user-facing issue is open.
5871
- */
5872
- function changeBlockKindInPageDesignIntent(intent, event) {
5873
- const blockLookPins = intent.blockLookPins.map((pin) => pin.blockId === event.blockId ? {
5874
- ...pin,
5875
- blockKind: event.nextBlockKind
5876
- } : pin);
5877
- const changed = intent.blockLookPins.find((pin) => pin.blockId === event.blockId);
5878
- const incompatiblePinnedLook = changed && !event.compatiblePinnedLookPresetIds.includes(changed.choice.value) ? changed : null;
5879
- return {
5880
- intent: {
5881
- ...intent,
5882
- blockLookPins
5883
- },
5884
- issues: incompatiblePinnedLook ? [{
5885
- kind: "pinned-look-incompatible-with-block-kind",
5886
- blockId: event.blockId,
5887
- presetId: incompatiblePinnedLook.choice.value,
5888
- previousBlockKind: incompatiblePinnedLook.blockKind,
5889
- nextBlockKind: event.nextBlockKind,
5890
- feedback: "user-facing"
5891
- }] : []
5892
- };
5893
- }
5894
5866
  function boundaryIssuePresetId(treatment) {
5895
5867
  if (typeof treatment === "string") return treatment;
5896
5868
  return boundaryOptionIdForTreatment(treatment) ?? unknownBoundaryOptionId;
@@ -31137,7 +31109,6 @@ const upsertEventSeriesCommandSchema = z.object({
31137
31109
  occurrences: z.array(eventOccurrenceSchema).min(1).readonly(),
31138
31110
  content: contentSummarySchema.optional(),
31139
31111
  settings: unknownRecordSchema.optional(),
31140
- presentation: unknownRecordSchema.nullable().optional(),
31141
31112
  tags: z.array(z.string()).readonly().optional(),
31142
31113
  blocks: entrySlotBlocksSchema.optional(),
31143
31114
  staffRefs: z.array(staffRefSchema).readonly().optional()
@@ -31367,7 +31338,6 @@ const allowedRuntimes = [
31367
31338
  const intendedExposures = [
31368
31339
  "recipe",
31369
31340
  "sdk_cli",
31370
- "onboarding_planner",
31371
31341
  "ai_proposal",
31372
31342
  "internal_apply"
31373
31343
  ];
@@ -31409,21 +31379,15 @@ const allRuntimes = [
31409
31379
  const standardExposure = [
31410
31380
  "recipe",
31411
31381
  "sdk_cli",
31412
- "onboarding_planner",
31413
31382
  "internal_apply"
31414
31383
  ];
31415
31384
  const proposalExposure = [
31416
31385
  "recipe",
31417
31386
  "sdk_cli",
31418
- "onboarding_planner",
31419
31387
  "ai_proposal",
31420
31388
  "internal_apply"
31421
31389
  ];
31422
- const recipeExposure = [
31423
- "recipe",
31424
- "onboarding_planner",
31425
- "internal_apply"
31426
- ];
31390
+ const recipeExposure = ["recipe", "internal_apply"];
31427
31391
  const sdkExposure = ["sdk_cli", "internal_apply"];
31428
31392
 
31429
31393
  //#endregion
@@ -32116,6 +32080,18 @@ function isIdentifiedImage(image) {
32116
32080
  return typeof image === "object" && image !== null && typeof image.identifier === "string" && image.identifier.trim().length > 0;
32117
32081
  }
32118
32082
 
32083
+ //#endregion
32084
+ //#region ../site-commands/src/planCommandOrderingDependencies.ts
32085
+ /** A complete reorder observes the membership after all selected page mutations. */
32086
+ function planCommandOrderingDependencies(command, commands, providerByRef, requiresByCommand) {
32087
+ const referenced = (requiresByCommand.get(command.ref) ?? []).flatMap(({ ref }) => {
32088
+ const provider = providerByRef.get(ref);
32089
+ return provider === undefined ? [] : [provider];
32090
+ });
32091
+ const membership = command.type === "reorderPageBlocks" ? commands.filter((candidate$1) => (candidate$1.type === "upsertPageBlock" || candidate$1.type === "deletePageBlock") && candidate$1.input.pageIdentifier === command.input.pageIdentifier).map((candidate$1) => candidate$1.ref) : [];
32092
+ return [...new Set([...referenced, ...membership])];
32093
+ }
32094
+
32119
32095
  //#endregion
32120
32096
  //#region ../site-commands/src/guards.ts
32121
32097
  function isRecord(value) {
@@ -32545,13 +32521,12 @@ const unsupportedWholeSeriesPageFieldChecks = [
32545
32521
  (input) => input.categoryRef !== undefined,
32546
32522
  (input) => input.categoryIdentifier !== undefined,
32547
32523
  (input) => input.tags !== undefined,
32548
- (input) => input.presentation !== undefined,
32549
32524
  (input) => input.content?.imageRef !== undefined,
32550
32525
  (input) => input.content?.mediaRefs !== undefined
32551
32526
  ];
32552
32527
  function wholeSeriesPageFieldsGap(input) {
32553
32528
  if (!unsupportedWholeSeriesPageFieldChecks.some((hasField) => hasField(input))) return null;
32554
- return staticGap("event_whole_series_page_fields_unsupported", "Whole-series page, reference, tag, and presentation fields need native page-authority mapping before mutation.");
32529
+ return staticGap("event_whole_series_page_fields_unsupported", "Whole-series page, reference and tag fields need native page-authority mapping before mutation.");
32555
32530
  }
32556
32531
  function passesGap(input) {
32557
32532
  return input.bookingOffer.pricing.acceptsPasses === true ? staticGap("event_whole_series_passes_unsupported", "Whole-series commands do not support pass redemption.") : null;
@@ -32965,10 +32940,9 @@ function orderCommands(commands, providerByRef, requiresByCommand) {
32965
32940
  const outgoing = new Map();
32966
32941
  const indegree = new Map(commands.map((command) => [command.ref, 0]));
32967
32942
  for (const command of commands) {
32968
- const requires = requiresByCommand.get(command.ref) ?? [];
32969
- for (const { ref } of requires) {
32970
- const provider = providerByRef.get(ref);
32971
- if (provider === undefined || provider === command.ref) continue;
32943
+ const providers = planCommandOrderingDependencies(command, commands, providerByRef, requiresByCommand);
32944
+ for (const provider of providers) {
32945
+ if (provider === command.ref) continue;
32972
32946
  if (!outgoing.has(provider)) outgoing.set(provider, new Set());
32973
32947
  const dependents = outgoing.get(provider);
32974
32948
  if (dependents !== undefined && !dependents.has(command.ref)) {