@riverbankcms/sdk 0.70.0 → 0.70.3

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 (61) hide show
  1. package/README.md +29 -0
  2. package/dist/_dts/ai/src/contracts/commandExposure.d.ts +8 -0
  3. package/dist/_dts/ai/src/contracts/feedback.d.ts +55 -0
  4. package/dist/_dts/ai/src/contracts/proposals.d.ts +34764 -0
  5. package/dist/_dts/ai/src/contracts.d.ts +5 -0
  6. package/dist/_dts/ai/src/designer/rfc6902.d.ts +16 -0
  7. package/dist/_dts/ai/src/designer/themePatch.d.ts +50 -0
  8. package/dist/_dts/api/src/aiPlayground.d.ts +1 -1
  9. package/dist/_dts/api/src/appointmentSetup.d.ts +19 -0
  10. package/dist/_dts/api/src/availability.d.ts +84 -2
  11. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +10 -1
  12. package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
  13. package/dist/_dts/api/src/endpoints.d.ts +29 -0
  14. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +4 -0
  15. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +29 -1
  16. package/dist/_dts/api/src/types.d.ts +1 -1
  17. package/dist/_dts/billing/src/components/index.d.ts +41 -0
  18. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +219 -0
  19. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -1
  20. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +2 -1
  21. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +2 -1
  22. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +3 -1
  23. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.d.ts +3 -1
  24. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +1 -0
  25. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorApplyPayload.d.ts +8 -0
  26. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorSnapshot.d.ts +1 -0
  27. package/dist/_dts/sdk/src/cli/commands/delete.d.ts +3 -0
  28. package/dist/_dts/sdk/src/cli/commands/style.d.ts +37 -0
  29. package/dist/_dts/sdk/src/cli/helpers.d.ts +8 -33
  30. package/dist/_dts/sdk/src/cli/site-commands/oneOffCommands.d.ts +81 -0
  31. package/dist/_dts/sdk/src/client/management/index.d.ts +2 -1
  32. package/dist/_dts/sdk/src/client/management/theme.d.ts +3 -1
  33. package/dist/_dts/sdk/src/client/management/types.d.ts +23 -0
  34. package/dist/_dts/sdk/src/components.d.ts +2 -1
  35. package/dist/_dts/sdk/src/next/types.d.ts +4 -2
  36. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -0
  37. package/dist/_dts/sdk/src/rendering/index.d.ts +2 -1
  38. package/dist/_dts/sdk/src/rendering/overrideResolution.d.ts +10 -0
  39. package/dist/_dts/sdk/src/rendering/overrides.d.ts +12 -0
  40. package/dist/_dts/sdk/src/version.d.ts +1 -1
  41. package/dist/_dts/site-commands/src/commands.d.ts +25 -7
  42. package/dist/_dts/site-commands/src/metadata.d.ts +2 -2
  43. package/dist/cli/index.mjs +844 -108
  44. package/dist/client/client.mjs +256 -202
  45. package/dist/client/hooks.mjs +55 -1
  46. package/dist/client/rendering.mjs +25467 -25403
  47. package/dist/preview-next/before-render.mjs +39 -0
  48. package/dist/preview-next/client/runtime.mjs +160 -39
  49. package/dist/preview-next/middleware.mjs +39 -0
  50. package/dist/server/components.mjs +65 -1
  51. package/dist/server/config-validation.mjs +55 -1
  52. package/dist/server/config.mjs +55 -1
  53. package/dist/server/data.mjs +55 -1
  54. package/dist/server/index.mjs +40 -1
  55. package/dist/server/next.mjs +137 -4
  56. package/dist/server/prebuild.mjs +1 -1
  57. package/dist/server/rendering/server.mjs +55 -1
  58. package/dist/server/rendering.mjs +65 -1
  59. package/dist/server/routing.mjs +56 -2
  60. package/dist/server/server.mjs +56 -2
  61. package/package.json +4 -3
@@ -3402,7 +3402,10 @@ var init_soft_pill = __esm({
3402
3402
  });
3403
3403
 
3404
3404
  // ../theme-core/src/buttons/personalities/index.ts
3405
- var buttonPersonalities;
3405
+ function findButtonPersonality(id) {
3406
+ return personalitiesById.get(id);
3407
+ }
3408
+ var buttonPersonalities, personalitiesById;
3406
3409
  var init_personalities = __esm({
3407
3410
  "../theme-core/src/buttons/personalities/index.ts"() {
3408
3411
  init_brushed_wash();
@@ -3422,7 +3425,7 @@ var init_personalities = __esm({
3422
3425
  brushedWash,
3423
3426
  showtimePill
3424
3427
  ];
3425
- new Map(
3428
+ personalitiesById = new Map(
3426
3429
  buttonPersonalities.map((p) => [p.id, p])
3427
3430
  );
3428
3431
  }
@@ -5115,7 +5118,10 @@ var init_warm_neutral = __esm({
5115
5118
  });
5116
5119
 
5117
5120
  // ../theme-core/src/palette/variants/index.ts
5118
- var paletteVariants;
5121
+ function findPaletteVariant(id) {
5122
+ return paletteVariantsById.get(id);
5123
+ }
5124
+ var paletteVariants, paletteVariantsById;
5119
5125
  var init_variants = __esm({
5120
5126
  "../theme-core/src/palette/variants/index.ts"() {
5121
5127
  init_brand_led();
@@ -5142,7 +5148,7 @@ var init_variants = __esm({
5142
5148
  softNaturalStone,
5143
5149
  softNaturalWatercolor
5144
5150
  ];
5145
- new Map(
5151
+ paletteVariantsById = new Map(
5146
5152
  paletteVariants.map((v) => [v.id, v])
5147
5153
  );
5148
5154
  }
@@ -5407,7 +5413,10 @@ function floatingGlassHeader(theme) {
5407
5413
  }
5408
5414
  };
5409
5415
  }
5410
- var headerLookCatalog;
5416
+ function findHeaderLook(id) {
5417
+ return headerLooksById.get(id);
5418
+ }
5419
+ var headerLookCatalog, headerLooksById;
5411
5420
  var init_headerLooks = __esm({
5412
5421
  "../theme-core/src/site-styles/headerLooks.ts"() {
5413
5422
  init_headerCtaVariants();
@@ -5487,7 +5496,7 @@ var init_headerLooks = __esm({
5487
5496
  compile: floatingGlassHeader
5488
5497
  }
5489
5498
  ];
5490
- new Map(
5499
+ headerLooksById = new Map(
5491
5500
  headerLookCatalog.map((look) => [look.id, look])
5492
5501
  );
5493
5502
  }
@@ -5556,7 +5565,10 @@ function brandTwoBandFooter(theme) {
5556
5565
  }
5557
5566
  };
5558
5567
  }
5559
- var footerLookCatalog;
5568
+ function findFooterLook(id) {
5569
+ return footerLooksById.get(id);
5570
+ }
5571
+ var footerLookCatalog, footerLooksById;
5560
5572
  var init_footerLooks = __esm({
5561
5573
  "../theme-core/src/site-styles/footerLooks.ts"() {
5562
5574
  init_customizableSurfaces();
@@ -5575,7 +5587,7 @@ var init_footerLooks = __esm({
5575
5587
  compile: brandTwoBandFooter
5576
5588
  }
5577
5589
  ];
5578
- new Map(
5590
+ footerLooksById = new Map(
5579
5591
  footerLookCatalog.map((look) => [look.id, look])
5580
5592
  );
5581
5593
  }
@@ -19328,6 +19340,24 @@ var ENDPOINT_DEFINITIONS = {
19328
19340
  "server:internal_error"
19329
19341
  ]
19330
19342
  },
19343
+ setServiceSpecificAvailability: {
19344
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/service-availability",
19345
+ method: "PUT",
19346
+ auth: "user",
19347
+ responseKind: "json",
19348
+ errors: [
19349
+ "validation:invalid_input",
19350
+ "resource:not_found",
19351
+ "server:internal_error"
19352
+ ]
19353
+ },
19354
+ deleteServiceSpecificAvailability: {
19355
+ path: "/sites/{siteId}/bookings/resources/{resourceId}/service-availability/{scheduleId}",
19356
+ method: "DELETE",
19357
+ auth: "user",
19358
+ responseKind: "json",
19359
+ errors: ["resource:not_found", "server:internal_error"]
19360
+ },
19331
19361
  listBlackouts: {
19332
19362
  path: "/sites/{siteId}/bookings/resources/{resourceId}/blackouts",
19333
19363
  method: "GET",
@@ -20963,6 +20993,20 @@ var ENDPOINT_DEFINITIONS = {
20963
20993
  auth: "user",
20964
20994
  responseKind: "json"
20965
20995
  },
20996
+ applySiteStyleSelection: {
20997
+ path: "/sites/{siteId}/theme/style-selection/apply",
20998
+ method: "POST",
20999
+ tags: [TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme],
21000
+ auth: "user",
21001
+ errors: [
21002
+ "validation:invalid_input",
21003
+ "auth:forbidden",
21004
+ "resource:not_found",
21005
+ "resource:conflict",
21006
+ "server:internal_error"
21007
+ ],
21008
+ responseKind: "json"
21009
+ },
20966
21010
  saveSiteChromeLookSelection: {
20967
21011
  path: "/sites/{siteId}/theme/site-chrome-look",
20968
21012
  method: "POST",
@@ -23706,6 +23750,13 @@ var ENDPOINT_DEFINITIONS = {
23706
23750
  auth: "service",
23707
23751
  responseKind: "json"
23708
23752
  },
23753
+ sdkApplySiteStyleSelection: {
23754
+ path: "/sdk/{siteId}/theme/style-selection/apply",
23755
+ method: "POST",
23756
+ auth: "service",
23757
+ responseKind: "json",
23758
+ errors: ["validation:invalid_input", "resource:not_found", "resource:conflict", "server:internal_error"]
23759
+ },
23709
23760
  sdkUpsertFooter: {
23710
23761
  path: "/sdk/{siteId}/footer",
23711
23762
  method: "POST",
@@ -34679,11 +34730,26 @@ var appointmentSetupWeeklyWindowDraftSchema = z.object({
34679
34730
  startTime: z.string(),
34680
34731
  endTime: z.string()
34681
34732
  });
34733
+ var appointmentSetupStartTimePolicyDraftSchema = z.discriminatedUnion("kind", [
34734
+ z.object({ kind: z.literal("automatic_spacing") }),
34735
+ z.object({
34736
+ kind: z.literal("regular_interval"),
34737
+ intervalMinutes: z.union([
34738
+ z.literal(10),
34739
+ z.literal(15),
34740
+ z.literal(20),
34741
+ z.literal(30),
34742
+ z.literal(45),
34743
+ z.literal(60)
34744
+ ])
34745
+ })
34746
+ ]);
34682
34747
  var appointmentSetupAvailabilityDraftSchema = z.object({
34683
34748
  kind: z.literal("weekly_windows"),
34684
34749
  resourceRef: appointmentSetupRefSchema,
34685
34750
  serviceRef: appointmentSetupRefSchema.nullable(),
34686
- windows: z.array(appointmentSetupWeeklyWindowDraftSchema)
34751
+ windows: z.array(appointmentSetupWeeklyWindowDraftSchema),
34752
+ startTimePolicy: appointmentSetupStartTimePolicyDraftSchema.optional()
34687
34753
  });
34688
34754
  var APPOINTMENT_DEFAULT_MIN_LEAD_MINUTES_MAX = 28 * 24 * 60;
34689
34755
  var APPOINTMENT_DEFAULT_MAX_BOOKING_NOTICE_MINUTES_MAX = 10 * 365 * 24 * 60;
@@ -36532,11 +36598,51 @@ function createFormOperations(http) {
36532
36598
  }
36533
36599
 
36534
36600
  // src/client/management/theme.ts
36601
+ function buildApplySiteStyleSelectionCommand(input) {
36602
+ return {
36603
+ type: "applySiteStyleSelection",
36604
+ ref: input.siteStyleId,
36605
+ input: {
36606
+ siteStyleId: input.siteStyleId,
36607
+ buttonPersonalityId: input.buttonPersonalityId,
36608
+ paletteVariantId: input.paletteVariantId,
36609
+ paletteOverrides: input.paletteOverrides,
36610
+ headerLookId: input.headerLookId,
36611
+ footerLookId: input.footerLookId,
36612
+ baseSelectionVersion: input.baseSelectionVersion
36613
+ }
36614
+ };
36615
+ }
36616
+ function applySiteStyleSelectionBodyFromCommand(command, selectionId) {
36617
+ const baseSelectionVersion = command.input.baseSelectionVersion;
36618
+ if (baseSelectionVersion === void 0) {
36619
+ throw new Error("applySiteStyleSelection command is missing baseSelectionVersion");
36620
+ }
36621
+ return {
36622
+ siteStyleId: command.input.siteStyleId,
36623
+ buttonPersonalityId: command.input.buttonPersonalityId,
36624
+ paletteVariantId: command.input.paletteVariantId,
36625
+ paletteOverrides: command.input.paletteOverrides,
36626
+ headerLookId: command.input.headerLookId,
36627
+ footerLookId: command.input.footerLookId,
36628
+ baseSelectionVersion,
36629
+ selectionId
36630
+ };
36631
+ }
36535
36632
  function createThemeOperations(http) {
36536
36633
  return {
36537
36634
  async upsert(input) {
36538
36635
  const result = await http.post("/theme", input);
36539
36636
  return result;
36637
+ },
36638
+ async applySelection(input) {
36639
+ const command = buildApplySiteStyleSelectionCommand(input);
36640
+ const body = applySiteStyleSelectionBodyFromCommand(command, input.selectionId);
36641
+ const result = await http.post(
36642
+ "/theme/style-selection/apply",
36643
+ body
36644
+ );
36645
+ return result;
36540
36646
  }
36541
36647
  };
36542
36648
  }
@@ -37435,14 +37541,14 @@ function createCommandContext(command) {
37435
37541
  "This command does not support --env=both. Use --env=local or --env=remote."
37436
37542
  );
37437
37543
  }
37438
- const primaryTarget = envTargets[0];
37439
- const env = loadEnvironment(primaryTarget === "remote");
37544
+ const targetEnv = envTargets[0] ?? "local";
37545
+ const env = loadEnvironment(targetEnv === "remote");
37440
37546
  const client = createManagementClient({
37441
37547
  dashboardUrl: env.dashboardUrl,
37442
37548
  managementApiKey: env.managementApiKey,
37443
37549
  siteId: env.siteId
37444
37550
  });
37445
- return { output, client, isRemote, isJsonOutput, envTargets };
37551
+ return { output, client, isRemote, isJsonOutput, targetEnv, siteId: env.siteId, envTargets };
37446
37552
  }
37447
37553
  function getOutputContext(command) {
37448
37554
  const globalOpts = command.optsWithGlobals();
@@ -37488,6 +37594,14 @@ function withErrorHandling(action) {
37488
37594
  }
37489
37595
  };
37490
37596
  }
37597
+ function withCommandContext(action) {
37598
+ return withErrorHandling(async (...allArgs) => {
37599
+ const command = allArgs[allArgs.length - 1];
37600
+ const actionArgs = allArgs.slice(0, -1);
37601
+ const ctx = createCommandContext(command);
37602
+ await action(ctx, ...actionArgs);
37603
+ });
37604
+ }
37491
37605
  function withConfirmation(getMessage, action) {
37492
37606
  return async (...allArgs) => {
37493
37607
  const command = allArgs[allArgs.length - 1];
@@ -37522,40 +37636,6 @@ function withConfirmation(getMessage, action) {
37522
37636
  function capitalize(str) {
37523
37637
  return str.charAt(0).toUpperCase() + str.slice(1);
37524
37638
  }
37525
- function createPublishCommand(config2) {
37526
- const cmd = new Command("publish").description(`Publish a ${config2.resourceName}`);
37527
- for (const arg of config2.args) {
37528
- cmd.argument(`<${arg}>`, `${capitalize(arg.replace("-", " "))}`);
37529
- }
37530
- return cmd.action(
37531
- withErrorHandling(async (...actionArgs) => {
37532
- const args = actionArgs.slice(0, config2.args.length);
37533
- const command = actionArgs[actionArgs.length - 1];
37534
- const { output, client } = createCommandContext(command);
37535
- const label = args.join("/");
37536
- output.info(`Publishing ${config2.resourceName}: ${label}`);
37537
- await config2.action(client, ...args);
37538
- output.success(`${capitalize(config2.resourceName)} published: ${label}`);
37539
- })
37540
- );
37541
- }
37542
- function createUnpublishCommand(config2) {
37543
- const cmd = new Command("unpublish").description(`Unpublish a ${config2.resourceName}`);
37544
- for (const arg of config2.args) {
37545
- cmd.argument(`<${arg}>`, `${capitalize(arg.replace("-", " "))}`);
37546
- }
37547
- return cmd.action(
37548
- withErrorHandling(async (...actionArgs) => {
37549
- const args = actionArgs.slice(0, config2.args.length);
37550
- const command = actionArgs[actionArgs.length - 1];
37551
- const { output, client } = createCommandContext(command);
37552
- const label = args.join("/");
37553
- output.info(`Unpublishing ${config2.resourceName}: ${label}`);
37554
- await config2.action(client, ...args);
37555
- output.success(`${capitalize(config2.resourceName)} unpublished: ${label}`);
37556
- })
37557
- );
37558
- }
37559
37639
  function createGetCommand(config2) {
37560
37640
  const cmd = new Command("get").description(`Get a single ${config2.resourceName}`);
37561
37641
  for (const arg of config2.args) {
@@ -44215,6 +44295,7 @@ var recipeIdentifierSchema = z.string().regex(
44215
44295
  "Use lowercase letters, numbers, and hyphens."
44216
44296
  );
44217
44297
  var currencySchema = z.string().regex(/^[A-Z]{3}$/u);
44298
+ var hexColorSchema2 = z.string().regex(/^#[0-9a-f]{6}$/u, "Hex must be #RRGGBB (lowercase)");
44218
44299
  var isoDateTimeSchema = z.string().datetime({ offset: true });
44219
44300
  var ianaTimezoneSchema = z.string().trim().min(1).max(64).refine(isValidIanaTimezone, {
44220
44301
  message: "Invalid IANA timezone"
@@ -44364,11 +44445,20 @@ var configureSiteIdentityCommandSchema = z.object({
44364
44445
  seoIndexing: z.enum(["index", "noindex", "noindex_demo"]).optional()
44365
44446
  }).strict()
44366
44447
  }).strict();
44367
- var applySiteStyleCommandSchema = z.object({
44368
- type: z.literal("applySiteStyle"),
44448
+ var styleSelectionVersionSchema = nonNegativeIntegerSchema;
44449
+ var styleCatalogIdSchema = z.string().trim().min(1);
44450
+ var paletteOverridesSchema2 = z.record(z.string().trim().min(1), hexColorSchema2).readonly();
44451
+ var applySiteStyleSelectionCommandSchema = z.object({
44452
+ type: z.literal("applySiteStyleSelection"),
44369
44453
  ref: siteStyleRefSchema,
44370
44454
  input: z.object({
44371
- styleKey: z.string().min(1)
44455
+ siteStyleId: siteStyleRefSchema,
44456
+ buttonPersonalityId: styleCatalogIdSchema.nullable(),
44457
+ paletteVariantId: styleCatalogIdSchema.nullable(),
44458
+ paletteOverrides: paletteOverridesSchema2.nullable(),
44459
+ headerLookId: styleCatalogIdSchema.nullable(),
44460
+ footerLookId: styleCatalogIdSchema.nullable(),
44461
+ baseSelectionVersion: styleSelectionVersionSchema.optional()
44372
44462
  }).strict()
44373
44463
  }).strict();
44374
44464
  var upsertMediaAssetCommandSchema = z.object({
@@ -45097,7 +45187,7 @@ var configureAppointmentAvailabilityCommandSchema = z.object({
45097
45187
  var siteCommandSchema = z.discriminatedUnion("type", [
45098
45188
  configureSiteIdentityCommandSchema,
45099
45189
  configureBookingSettingsCommandSchema,
45100
- applySiteStyleCommandSchema,
45190
+ applySiteStyleSelectionCommandSchema,
45101
45191
  upsertMediaAssetCommandSchema,
45102
45192
  upsertPageCommandSchema,
45103
45193
  upsertBlockTreeCommandSchema,
@@ -45238,7 +45328,7 @@ var siteCommandMetadata = {
45238
45328
  capability: "bookings.settings.write",
45239
45329
  support: "supported"
45240
45330
  },
45241
- applySiteStyle: {
45331
+ applySiteStyleSelection: {
45242
45332
  scope: "style",
45243
45333
  risk: "low",
45244
45334
  writeSemantics: "upsert",
@@ -45247,7 +45337,7 @@ var siteCommandMetadata = {
45247
45337
  conflictPolicy: "update_existing",
45248
45338
  previewability: "static_preview",
45249
45339
  allowedRuntimes: ["development", "staging", "demo", "production"],
45250
- intendedExposure: ["recipe", "sdk_cli", "onboarding_planner", "internal_apply"],
45340
+ intendedExposure: ["recipe", "sdk_cli", "onboarding_planner", "ai_proposal", "internal_apply"],
45251
45341
  capability: "theme.write",
45252
45342
  support: "supported"
45253
45343
  },
@@ -45812,7 +45902,7 @@ function commandRefContributions(command) {
45812
45902
  case "configureSiteIdentity":
45813
45903
  case "configureBookingSettings":
45814
45904
  return { provides: [], requires: [] };
45815
- case "applySiteStyle":
45905
+ case "applySiteStyleSelection":
45816
45906
  return { provides: [{ ref: command.ref, field: "ref" }], requires: [] };
45817
45907
  case "upsertMediaAsset":
45818
45908
  case "upsertPage":
@@ -46236,7 +46326,7 @@ function matchSiteCommand(command, match) {
46236
46326
  return match(command);
46237
46327
  case "configureBookingSettings":
46238
46328
  return match(command);
46239
- case "applySiteStyle":
46329
+ case "applySiteStyleSelection":
46240
46330
  return match(command);
46241
46331
  case "upsertMediaAsset":
46242
46332
  return match(command);
@@ -52122,6 +52212,403 @@ function reportMediaValidationWarningsAndCollectBlocking(output, validation) {
52122
52212
  return validation.diagnostics.filter((diagnostic) => diagnostic.severity === "error").map((diagnostic) => formatMediaGuardDiagnostic(diagnostic));
52123
52213
  }
52124
52214
 
52215
+ // src/cli/site-commands/oneOffCommands.ts
52216
+ init_src();
52217
+ function compileOneOffEntryCommand(input) {
52218
+ const commandBinding2 = oneOffEntryCommandBinding(input.mutation);
52219
+ return planCliCommandBatchForBindings({
52220
+ source: input.source,
52221
+ siteId: input.siteId,
52222
+ targetEnv: input.targetEnv,
52223
+ commandTypes: entrySiteCommandTypes,
52224
+ commandBindings: [commandBinding2]
52225
+ });
52226
+ }
52227
+ function compileOneOffPageCommand(input) {
52228
+ const commandBinding2 = oneOffPageCommandBinding(input.mutation);
52229
+ return planCliCommandBatchForBindings({
52230
+ source: input.source,
52231
+ siteId: input.siteId,
52232
+ targetEnv: input.targetEnv,
52233
+ commandTypes: pageSiteCommandTypes,
52234
+ commandBindings: [commandBinding2]
52235
+ });
52236
+ }
52237
+ function compileOneOffBlockCommand(input) {
52238
+ const commandBinding2 = oneOffBlockCommandBinding(input.mutation);
52239
+ return planCliCommandBatchForBindings({
52240
+ source: input.source,
52241
+ siteId: input.siteId,
52242
+ targetEnv: input.targetEnv,
52243
+ commandTypes: pageSiteCommandTypes,
52244
+ commandBindings: [commandBinding2]
52245
+ });
52246
+ }
52247
+ function compileOneOffNavigationCommand(input) {
52248
+ const commandBinding2 = oneOffNavigationCommandBinding(input.mutation);
52249
+ return planCliCommandBatchForBindings({
52250
+ source: input.source,
52251
+ siteId: input.siteId,
52252
+ targetEnv: input.targetEnv,
52253
+ commandTypes: navigationSiteCommandTypes,
52254
+ commandBindings: [commandBinding2]
52255
+ });
52256
+ }
52257
+ async function executeOneOffEntryCommand(input) {
52258
+ const plannedCommand = singlePlannedCommand(input.compiledPlan.plan.commands);
52259
+ return input.apply(plannedCommand.command, input.client);
52260
+ }
52261
+ async function executeOneOffPageCommand(input) {
52262
+ const plannedCommand = singlePlannedCommand(input.compiledPlan.plan.commands);
52263
+ return input.apply(plannedCommand.command, input.client);
52264
+ }
52265
+ async function executeOneOffNavigationCommand(input) {
52266
+ const plannedCommand = singlePlannedCommand(input.compiledPlan.plan.commands);
52267
+ return input.apply(plannedCommand.command, input.client);
52268
+ }
52269
+ async function applyOneOffEntryCommand(command, client) {
52270
+ switch (command.type) {
52271
+ case "upsertContentEntry":
52272
+ return client.entries.upsert({
52273
+ identifier: entryIdentifierForCommand(command),
52274
+ contentType: command.input.contentTypeKey,
52275
+ data: command.input.data ?? {},
52276
+ slug: command.input.slug
52277
+ });
52278
+ case "publishContentEntry":
52279
+ await client.entries.publish(
52280
+ command.input.contentTypeKey,
52281
+ entryIdentifierForCommand(command)
52282
+ );
52283
+ return;
52284
+ case "unpublishContentEntry":
52285
+ await client.entries.unpublish(
52286
+ command.input.contentTypeKey,
52287
+ entryIdentifierForCommand(command)
52288
+ );
52289
+ return;
52290
+ case "deleteContentEntry":
52291
+ await client.entries.delete(
52292
+ command.input.contentTypeKey,
52293
+ entryIdentifierForCommand(command)
52294
+ );
52295
+ return;
52296
+ default:
52297
+ assertNever(command);
52298
+ }
52299
+ }
52300
+ async function applyOneOffEntryCommandReturningEntry(command, client) {
52301
+ const result = await applyOneOffEntryCommand(command, client);
52302
+ if (!result) {
52303
+ throw new Error("Entry upsert completed without returning an entry.");
52304
+ }
52305
+ return result;
52306
+ }
52307
+ async function applyOneOffPageCommand(command, client) {
52308
+ switch (command.type) {
52309
+ case "upsertPage":
52310
+ return client.pages.upsert({
52311
+ identifier: pageIdentifierForCommand(command),
52312
+ title: command.input.title,
52313
+ path: pagePathForCommand(command),
52314
+ seoTitle: command.input.seoTitle,
52315
+ seoDescription: command.input.seoDescription
52316
+ });
52317
+ case "publishPage":
52318
+ await client.pages.publish(pageIdentifierForCommand(command));
52319
+ return;
52320
+ case "unpublishPage":
52321
+ await client.pages.unpublish(pageIdentifierForCommand(command));
52322
+ return;
52323
+ case "upsertPageBlock":
52324
+ return client.blocks.upsert(pageIdentifierForBlockCommand(command), {
52325
+ identifier: blockIdentifierForCommand(command),
52326
+ kind: command.input.type,
52327
+ data: command.input.props ?? {}
52328
+ });
52329
+ case "reorderPageBlocks":
52330
+ await client.blocks.reorder(
52331
+ pageIdentifierForBlockCommand(command),
52332
+ [...blockOrderIdentifiersForCommand(command)]
52333
+ );
52334
+ return;
52335
+ case "deletePageBlock":
52336
+ await client.blocks.delete(
52337
+ pageIdentifierForBlockCommand(command),
52338
+ blockIdentifierForCommand(command)
52339
+ );
52340
+ return;
52341
+ default:
52342
+ assertNever(command);
52343
+ }
52344
+ }
52345
+ async function applyOneOffPageCommandReturningPage(command, client) {
52346
+ const result = await applyOneOffPageCommand(command, client);
52347
+ if (!result || !isManagementPage(result)) {
52348
+ throw new Error("Page upsert completed without returning a page.");
52349
+ }
52350
+ return result;
52351
+ }
52352
+ async function applyOneOffPageCommandReturningBlock(command, client) {
52353
+ const result = await applyOneOffPageCommand(command, client);
52354
+ if (!result || !isManagementBlock(result)) {
52355
+ throw new Error("Block upsert completed without returning a block.");
52356
+ }
52357
+ return result;
52358
+ }
52359
+ async function applyOneOffNavigationCommand(command, client) {
52360
+ const role = navigationCommandRole2(command);
52361
+ return client.navigation.upsert({
52362
+ name: navigationCommandMenuName2(command),
52363
+ items: command.input.items.map(navigationItemInput2),
52364
+ ...role === "primary" ? { isPrimary: true } : {},
52365
+ ...role === "footer" ? { isFooter: true } : {}
52366
+ });
52367
+ }
52368
+ function oneOffEntryCommandBinding(mutation) {
52369
+ const contentType = asCliContentTypeKey(mutation.contentType);
52370
+ const identifier = asCliEntryIdentifier(mutation.identifier);
52371
+ switch (mutation.kind) {
52372
+ case "upsert": {
52373
+ const title = titleFromEntryData(mutation.data);
52374
+ const command = {
52375
+ type: "upsertContentEntry",
52376
+ ref: createContentEntryRef([contentType, identifier]),
52377
+ input: {
52378
+ identifier,
52379
+ contentTypeKey: contentType,
52380
+ ...mutation.slug ? { slug: mutation.slug } : {},
52381
+ ...title ? { title } : {},
52382
+ data: mutation.data
52383
+ }
52384
+ };
52385
+ return {
52386
+ command,
52387
+ reportSubject: { contentType, identifier, counter: "updated" }
52388
+ };
52389
+ }
52390
+ case "publish": {
52391
+ const command = {
52392
+ type: "publishContentEntry",
52393
+ ref: createCommandRef("publish", [contentType, identifier]),
52394
+ input: { contentTypeKey: contentType, identifier }
52395
+ };
52396
+ return {
52397
+ command,
52398
+ reportSubject: { contentType, identifier, counter: "published" }
52399
+ };
52400
+ }
52401
+ case "unpublish": {
52402
+ const command = {
52403
+ type: "unpublishContentEntry",
52404
+ ref: createCommandRef("unpublish", [contentType, identifier]),
52405
+ input: { contentTypeKey: contentType, identifier }
52406
+ };
52407
+ return {
52408
+ command,
52409
+ reportSubject: { contentType, identifier, counter: "unpublished" }
52410
+ };
52411
+ }
52412
+ default:
52413
+ assertNever(mutation);
52414
+ }
52415
+ }
52416
+ function oneOffPageCommandBinding(mutation) {
52417
+ const identifier = asCliPageIdentifier(mutation.identifier);
52418
+ switch (mutation.kind) {
52419
+ case "upsert": {
52420
+ const command = {
52421
+ type: "upsertPage",
52422
+ ref: createPageRef([identifier]),
52423
+ input: {
52424
+ identifier,
52425
+ slug: identifier,
52426
+ title: mutation.title,
52427
+ path: mutation.path,
52428
+ ...mutation.seoTitle ? { seoTitle: mutation.seoTitle } : {},
52429
+ ...mutation.seoDescription ? { seoDescription: mutation.seoDescription } : {}
52430
+ }
52431
+ };
52432
+ return {
52433
+ command,
52434
+ reportSubject: { resource: "page", identifier, counter: "updated" }
52435
+ };
52436
+ }
52437
+ case "publish": {
52438
+ const command = {
52439
+ type: "publishPage",
52440
+ ref: createCommandRef("publish-page", [identifier]),
52441
+ input: { identifier }
52442
+ };
52443
+ return {
52444
+ command,
52445
+ reportSubject: { resource: "page", identifier, counter: "published" }
52446
+ };
52447
+ }
52448
+ case "unpublish": {
52449
+ const command = {
52450
+ type: "unpublishPage",
52451
+ ref: createCommandRef("unpublish-page", [identifier]),
52452
+ input: { identifier }
52453
+ };
52454
+ return {
52455
+ command,
52456
+ reportSubject: { resource: "page", identifier, counter: "unpublished" }
52457
+ };
52458
+ }
52459
+ default:
52460
+ assertNever(mutation);
52461
+ }
52462
+ }
52463
+ function oneOffBlockCommandBinding(mutation) {
52464
+ const pageIdentifier = asCliPageIdentifier(mutation.pageIdentifier);
52465
+ switch (mutation.kind) {
52466
+ case "upsert": {
52467
+ const identifier = asCliBlockIdentifier(mutation.blockIdentifier);
52468
+ const command = {
52469
+ type: "upsertPageBlock",
52470
+ ref: createBlockRef([pageIdentifier, identifier]),
52471
+ input: {
52472
+ pageIdentifier,
52473
+ identifier,
52474
+ type: mutation.blockKind,
52475
+ props: mutation.data
52476
+ }
52477
+ };
52478
+ return {
52479
+ command,
52480
+ reportSubject: {
52481
+ resource: "block",
52482
+ pageIdentifier,
52483
+ identifier,
52484
+ counter: "updated"
52485
+ }
52486
+ };
52487
+ }
52488
+ case "reorder": {
52489
+ const identifiers = mutation.blockIdentifiers.map(asCliBlockIdentifier);
52490
+ const command = {
52491
+ type: "reorderPageBlocks",
52492
+ ref: createBlocksRef([pageIdentifier]),
52493
+ input: {
52494
+ pageIdentifier,
52495
+ blocks: identifiers.map((identifier) => ({
52496
+ blockRef: createBlockRef([pageIdentifier, identifier]),
52497
+ identifier
52498
+ }))
52499
+ }
52500
+ };
52501
+ return {
52502
+ command,
52503
+ reportSubject: {
52504
+ resource: "block",
52505
+ pageIdentifier,
52506
+ identifier: pageIdentifier,
52507
+ counter: "reordered"
52508
+ }
52509
+ };
52510
+ }
52511
+ default:
52512
+ assertNever(mutation);
52513
+ }
52514
+ }
52515
+ function oneOffNavigationCommandBinding(mutation) {
52516
+ const name = asCliNavigationMenuName(mutation.menuName);
52517
+ const command = {
52518
+ type: "upsertNavigationMenu",
52519
+ ref: createNavigationRef([name]),
52520
+ input: {
52521
+ name,
52522
+ items: mutation.items.map(navigationItemForCommand2)
52523
+ }
52524
+ };
52525
+ return {
52526
+ command,
52527
+ reportSubject: { name, counter: "updated" }
52528
+ };
52529
+ }
52530
+ function navigationItemForCommand2(item) {
52531
+ return {
52532
+ label: item.label,
52533
+ ...item.isCta ? { isCta: true } : {},
52534
+ ...item.link ? { link: navigationLinkForCommand(item.link) } : {},
52535
+ ...item.children ? { children: item.children.map(navigationItemForCommand2) } : {}
52536
+ };
52537
+ }
52538
+ function navigationLinkForCommand(link2) {
52539
+ switch (link2.kind) {
52540
+ case "page":
52541
+ return { kind: "page", identifier: link2.identifier };
52542
+ case "entry":
52543
+ return {
52544
+ kind: "entry",
52545
+ contentType: link2.contentType,
52546
+ identifier: link2.identifier
52547
+ };
52548
+ case "external":
52549
+ return { kind: "external", href: link2.href };
52550
+ case "url":
52551
+ return { kind: "url", href: link2.href };
52552
+ case "portal":
52553
+ return {
52554
+ kind: "portal",
52555
+ ...link2.path ? { path: link2.path } : {},
52556
+ ...link2.labels ? { labels: link2.labels } : {}
52557
+ };
52558
+ case "cart":
52559
+ return {
52560
+ kind: "cart",
52561
+ badge: link2.badge,
52562
+ label: link2.label
52563
+ };
52564
+ default:
52565
+ assertNever(link2);
52566
+ }
52567
+ }
52568
+ function navigationItemInput2(item) {
52569
+ return {
52570
+ label: item.label,
52571
+ ...item.isCta ? { isCta: true } : {},
52572
+ ...item.link ? { link: item.link } : {},
52573
+ ...item.children ? { children: item.children.map(navigationItemInput2) } : {}
52574
+ };
52575
+ }
52576
+ function navigationCommandMenuName2(command) {
52577
+ const name = command.input.name ?? command.input.location;
52578
+ if (name) return name;
52579
+ throw new Error(`Invalid navigation command ${command.ref}: missing input.name or input.location.`);
52580
+ }
52581
+ function navigationCommandRole2(command) {
52582
+ if (command.input.role) return command.input.role;
52583
+ switch (command.input.location) {
52584
+ case "main":
52585
+ case "header":
52586
+ return "primary";
52587
+ case "footer":
52588
+ return "footer";
52589
+ case void 0:
52590
+ return void 0;
52591
+ default:
52592
+ return assertNever(command.input.location);
52593
+ }
52594
+ }
52595
+ function isManagementPage(value) {
52596
+ return "path" in value;
52597
+ }
52598
+ function isManagementBlock(value) {
52599
+ return "kind" in value;
52600
+ }
52601
+ function singlePlannedCommand(commands) {
52602
+ if (commands.length !== 1) {
52603
+ throw new Error(`Expected exactly one one-off site command, got ${commands.length}.`);
52604
+ }
52605
+ const plannedCommand = commands[0];
52606
+ if (!plannedCommand) {
52607
+ throw new Error("Expected one one-off site command, got none.");
52608
+ }
52609
+ return plannedCommand;
52610
+ }
52611
+
52125
52612
  // src/cli/commands/entry.ts
52126
52613
  var ENTRY_LIST_COLUMNS = [
52127
52614
  "id",
@@ -52285,8 +52772,8 @@ async function validateEntryUpsertMedia(options) {
52285
52772
  };
52286
52773
  }
52287
52774
  var upsertCommand = new Command("upsert").description("Create or update an entry").argument("<type>", "Content type").argument("<identifier>", "Entry identifier").option("--data <json>", "Entry data as JSON string").option("--file <path>", "Path to JSON file with entry data").option("--slug <slug>", "Entry slug (defaults to identifier)").action(
52288
- withErrorHandling(async (type, identifier, options, command) => {
52289
- const { output, client } = createCommandContext(command);
52775
+ withCommandContext(async (ctx, type, identifier, options) => {
52776
+ const { output, client, siteId, targetEnv } = ctx;
52290
52777
  const data = await parseJsonData(options);
52291
52778
  output.info(`Upserting entry: ${type}/${identifier}`);
52292
52779
  const mediaValidation = await validateEntryUpsertMedia({
@@ -52302,11 +52789,25 @@ var upsertCommand = new Command("upsert").description("Create or update an entry
52302
52789
  suggestion: "Resolve media identifiers on the CMS first, or remove invalid media references."
52303
52790
  });
52304
52791
  }
52305
- const entry = await client.entries.upsert({
52306
- contentType: type,
52307
- identifier,
52308
- data,
52309
- slug: options.slug
52792
+ const compiled = compileOneOffEntryCommand({
52793
+ source: "one_off_entry",
52794
+ siteId,
52795
+ targetEnv,
52796
+ mutation: {
52797
+ kind: "upsert",
52798
+ contentType: type,
52799
+ identifier,
52800
+ data,
52801
+ ...options.slug ? { slug: options.slug } : {}
52802
+ }
52803
+ });
52804
+ if (!compiled.ok) {
52805
+ return output.error(compiled.error.message);
52806
+ }
52807
+ const entry = await executeOneOffEntryCommand({
52808
+ compiledPlan: compiled.value,
52809
+ client,
52810
+ apply: applyOneOffEntryCommandReturningEntry
52310
52811
  });
52311
52812
  output.success(`Entry upserted: ${entry.identifier}`, {
52312
52813
  id: entry.id,
@@ -52316,16 +52817,50 @@ var upsertCommand = new Command("upsert").description("Create or update an entry
52316
52817
  });
52317
52818
  })
52318
52819
  );
52319
- var publishCommand = createPublishCommand({
52320
- resourceName: "entry",
52321
- args: ["type", "identifier"],
52322
- action: (client, type, identifier) => client.entries.publish(type, identifier)
52323
- });
52324
- var unpublishCommand = createUnpublishCommand({
52325
- resourceName: "entry",
52326
- args: ["type", "identifier"],
52327
- action: (client, type, identifier) => client.entries.unpublish(type, identifier)
52328
- });
52820
+ var publishCommand = new Command("publish").description("Publish a entry").argument("<type>", "Type").argument("<identifier>", "Identifier").action(
52821
+ withCommandContext(async (ctx, type, identifier) => {
52822
+ const { output, client, siteId, targetEnv } = ctx;
52823
+ const label = `${type}/${identifier}`;
52824
+ output.info(`Publishing entry: ${label}`);
52825
+ const compiled = compileOneOffEntryCommand({
52826
+ source: "one_off_entry",
52827
+ siteId,
52828
+ targetEnv,
52829
+ mutation: { kind: "publish", contentType: type, identifier }
52830
+ });
52831
+ if (!compiled.ok) {
52832
+ return output.error(compiled.error.message);
52833
+ }
52834
+ await executeOneOffEntryCommand({
52835
+ compiledPlan: compiled.value,
52836
+ client,
52837
+ apply: applyOneOffEntryCommand
52838
+ });
52839
+ output.success(`Entry published: ${label}`);
52840
+ })
52841
+ );
52842
+ var unpublishCommand = new Command("unpublish").description("Unpublish a entry").argument("<type>", "Type").argument("<identifier>", "Identifier").action(
52843
+ withCommandContext(async (ctx, type, identifier) => {
52844
+ const { output, client, siteId, targetEnv } = ctx;
52845
+ const label = `${type}/${identifier}`;
52846
+ output.info(`Unpublishing entry: ${label}`);
52847
+ const compiled = compileOneOffEntryCommand({
52848
+ source: "one_off_entry",
52849
+ siteId,
52850
+ targetEnv,
52851
+ mutation: { kind: "unpublish", contentType: type, identifier }
52852
+ });
52853
+ if (!compiled.ok) {
52854
+ return output.error(compiled.error.message);
52855
+ }
52856
+ await executeOneOffEntryCommand({
52857
+ compiledPlan: compiled.value,
52858
+ client,
52859
+ apply: applyOneOffEntryCommand
52860
+ });
52861
+ output.success(`Entry unpublished: ${label}`);
52862
+ })
52863
+ );
52329
52864
  async function findEntryById(client, contentType, entryId, options = {}) {
52330
52865
  const limit = options.limit ?? 20;
52331
52866
  if (!Number.isFinite(limit) || limit <= 0) {
@@ -52460,15 +52995,29 @@ var formatPageRow = (page) => [
52460
52995
  formatDateShort(page.updatedAt)
52461
52996
  ];
52462
52997
  var upsertCommand2 = new Command("upsert").description("Create or update a page").argument("<identifier>", "Page identifier").requiredOption("--title <title>", "Page title").requiredOption("--path <path>", "Page path (e.g., /about)").option("--seo-title <title>", "SEO title").option("--seo-description <description>", "SEO description").action(
52463
- withErrorHandling(async (identifier, options, command) => {
52464
- const { output, client } = createCommandContext(command);
52998
+ withCommandContext(async (ctx, identifier, options) => {
52999
+ const { output, client, siteId, targetEnv } = ctx;
52465
53000
  output.info(`Upserting page: ${identifier}`);
52466
- const page = await client.pages.upsert({
52467
- identifier,
52468
- title: options.title,
52469
- path: options.path,
52470
- seoTitle: options.seoTitle,
52471
- seoDescription: options.seoDescription
53001
+ const compiled = compileOneOffPageCommand({
53002
+ source: "one_off_page",
53003
+ siteId,
53004
+ targetEnv,
53005
+ mutation: {
53006
+ kind: "upsert",
53007
+ identifier,
53008
+ title: options.title,
53009
+ path: options.path,
53010
+ ...options.seoTitle ? { seoTitle: options.seoTitle } : {},
53011
+ ...options.seoDescription ? { seoDescription: options.seoDescription } : {}
53012
+ }
53013
+ });
53014
+ if (!compiled.ok) {
53015
+ return output.error(compiled.error.message);
53016
+ }
53017
+ const page = await executeOneOffPageCommand({
53018
+ compiledPlan: compiled.value,
53019
+ client,
53020
+ apply: applyOneOffPageCommandReturningPage
52472
53021
  });
52473
53022
  output.success(`Page upserted: ${page.identifier}`, {
52474
53023
  id: page.id,
@@ -52478,16 +53027,48 @@ var upsertCommand2 = new Command("upsert").description("Create or update a page"
52478
53027
  });
52479
53028
  })
52480
53029
  );
52481
- var publishCommand2 = createPublishCommand({
52482
- resourceName: "page",
52483
- args: ["identifier"],
52484
- action: (client, identifier) => client.pages.publish(identifier)
52485
- });
52486
- var unpublishCommand2 = createUnpublishCommand({
52487
- resourceName: "page",
52488
- args: ["identifier"],
52489
- action: (client, identifier) => client.pages.unpublish(identifier)
52490
- });
53030
+ var publishCommand2 = new Command("publish").description("Publish a page").argument("<identifier>", "Identifier").action(
53031
+ withCommandContext(async (ctx, identifier) => {
53032
+ const { output, client, siteId, targetEnv } = ctx;
53033
+ output.info(`Publishing page: ${identifier}`);
53034
+ const compiled = compileOneOffPageCommand({
53035
+ source: "one_off_page",
53036
+ siteId,
53037
+ targetEnv,
53038
+ mutation: { kind: "publish", identifier }
53039
+ });
53040
+ if (!compiled.ok) {
53041
+ return output.error(compiled.error.message);
53042
+ }
53043
+ await executeOneOffPageCommand({
53044
+ compiledPlan: compiled.value,
53045
+ client,
53046
+ apply: applyOneOffPageCommand
53047
+ });
53048
+ output.success(`Page published: ${identifier}`);
53049
+ })
53050
+ );
53051
+ var unpublishCommand2 = new Command("unpublish").description("Unpublish a page").argument("<identifier>", "Identifier").action(
53052
+ withCommandContext(async (ctx, identifier) => {
53053
+ const { output, client, siteId, targetEnv } = ctx;
53054
+ output.info(`Unpublishing page: ${identifier}`);
53055
+ const compiled = compileOneOffPageCommand({
53056
+ source: "one_off_page",
53057
+ siteId,
53058
+ targetEnv,
53059
+ mutation: { kind: "unpublish", identifier }
53060
+ });
53061
+ if (!compiled.ok) {
53062
+ return output.error(compiled.error.message);
53063
+ }
53064
+ await executeOneOffPageCommand({
53065
+ compiledPlan: compiled.value,
53066
+ client,
53067
+ apply: applyOneOffPageCommand
53068
+ });
53069
+ output.success(`Page unpublished: ${identifier}`);
53070
+ })
53071
+ );
52491
53072
  var getCommand2 = createGetCommand({
52492
53073
  resourceName: "page",
52493
53074
  args: ["identifier"],
@@ -52549,9 +53130,9 @@ async function validateBlockUpsertMedia(options) {
52549
53130
  };
52550
53131
  }
52551
53132
  var upsertCommand3 = new Command("upsert").description("Create or update a block on a page").argument("<page-identifier>", "Page identifier").argument("<block-identifier>", "Block identifier").requiredOption("--kind <kind>", "Block kind (e.g., block.hero, block.body-text)").option("--data <json>", "Block data as JSON string").option("--file <path>", "Path to JSON file with block data").option("--position <n>", "Block position (0-indexed)").action(
52552
- withErrorHandling(
52553
- async (pageIdentifier, blockIdentifier, options, command) => {
52554
- const { output, client } = createCommandContext(command);
53133
+ withCommandContext(
53134
+ async (ctx, pageIdentifier, blockIdentifier, options) => {
53135
+ const { output, client, siteId, targetEnv } = ctx;
52555
53136
  const data = await parseJsonData(options);
52556
53137
  output.info(`Upserting block: ${pageIdentifier}/${blockIdentifier}`);
52557
53138
  const mediaValidation = await validateBlockUpsertMedia({
@@ -52568,12 +53149,37 @@ var upsertCommand3 = new Command("upsert").description("Create or update a block
52568
53149
  suggestion: "Resolve media identifiers on the CMS first, or remove invalid media references."
52569
53150
  });
52570
53151
  }
52571
- const block = await client.blocks.upsert(pageIdentifier, {
52572
- identifier: blockIdentifier,
52573
- kind: options.kind,
52574
- data,
52575
- position: options.position ? parseInt(options.position, 10) : void 0
52576
- });
53152
+ const position = options.position ? parseInt(options.position, 10) : void 0;
53153
+ let block;
53154
+ if (position !== void 0) {
53155
+ block = await client.blocks.upsert(pageIdentifier, {
53156
+ identifier: blockIdentifier,
53157
+ kind: options.kind,
53158
+ data,
53159
+ position
53160
+ });
53161
+ } else {
53162
+ const compiled = compileOneOffBlockCommand({
53163
+ source: "one_off_block",
53164
+ siteId,
53165
+ targetEnv,
53166
+ mutation: {
53167
+ kind: "upsert",
53168
+ pageIdentifier,
53169
+ blockIdentifier,
53170
+ blockKind: options.kind,
53171
+ data
53172
+ }
53173
+ });
53174
+ if (!compiled.ok) {
53175
+ return output.error(compiled.error.message);
53176
+ }
53177
+ block = await executeOneOffPageCommand({
53178
+ compiledPlan: compiled.value,
53179
+ client,
53180
+ apply: applyOneOffPageCommandReturningBlock
53181
+ });
53182
+ }
52577
53183
  output.success(`Block upserted: ${block.identifier}`, {
52578
53184
  id: block.id,
52579
53185
  identifier: block.identifier,
@@ -52584,14 +53190,27 @@ var upsertCommand3 = new Command("upsert").description("Create or update a block
52584
53190
  )
52585
53191
  );
52586
53192
  var reorderCommand = new Command("reorder").description("Reorder blocks on a page").argument("<page-identifier>", "Page identifier").argument("<identifiers...>", "Block identifiers in desired order").action(
52587
- withErrorHandling(
52588
- async (pageIdentifier, identifiers, _options, command) => {
52589
- const { output, client } = createCommandContext(command);
53193
+ withCommandContext(
53194
+ async (ctx, pageIdentifier, identifiers) => {
53195
+ const { output, client, siteId, targetEnv } = ctx;
52590
53196
  if (identifiers.length < 2) {
52591
53197
  return output.error("At least 2 block identifiers are required for reordering");
52592
53198
  }
52593
53199
  output.info(`Reordering blocks on page: ${pageIdentifier}`);
52594
- await client.blocks.reorder(pageIdentifier, identifiers);
53200
+ const compiled = compileOneOffBlockCommand({
53201
+ source: "one_off_block",
53202
+ siteId,
53203
+ targetEnv,
53204
+ mutation: { kind: "reorder", pageIdentifier, blockIdentifiers: identifiers }
53205
+ });
53206
+ if (!compiled.ok) {
53207
+ return output.error(compiled.error.message);
53208
+ }
53209
+ await executeOneOffPageCommand({
53210
+ compiledPlan: compiled.value,
53211
+ client,
53212
+ apply: applyOneOffPageCommand
53213
+ });
52595
53214
  output.success(`Blocks reordered`, {
52596
53215
  page: pageIdentifier,
52597
53216
  order: identifiers
@@ -52659,13 +53278,23 @@ function countItems(items) {
52659
53278
  return count;
52660
53279
  }
52661
53280
  var upsertCommand4 = new Command("upsert").description("Create or update a navigation menu").argument("<menu-name>", "Navigation menu name").option("--file <path>", "Path to JSON file with menu items").option("--data <json>", "Menu items as JSON string").action(
52662
- withErrorHandling(async (menuName, options, command) => {
52663
- const { output, client } = createCommandContext(command);
53281
+ withCommandContext(async (ctx, menuName, options) => {
53282
+ const { output, client, siteId, targetEnv } = ctx;
52664
53283
  const items = await parseJsonArray(options);
52665
53284
  output.info(`Upserting navigation menu: ${menuName}`);
52666
- const menu = await client.navigation.upsert({
52667
- name: menuName,
52668
- items
53285
+ const compiled = compileOneOffNavigationCommand({
53286
+ source: "one_off_navigation",
53287
+ siteId,
53288
+ targetEnv,
53289
+ mutation: { kind: "upsert", menuName, items }
53290
+ });
53291
+ if (!compiled.ok) {
53292
+ return output.error(compiled.error.message);
53293
+ }
53294
+ const menu = await executeOneOffNavigationCommand({
53295
+ compiledPlan: compiled.value,
53296
+ client,
53297
+ apply: applyOneOffNavigationCommand
52669
53298
  });
52670
53299
  output.success(`Navigation menu upserted: ${menu.name}`, {
52671
53300
  id: menu.id,
@@ -54145,7 +54774,7 @@ var SimpleCache = class {
54145
54774
  };
54146
54775
 
54147
54776
  // src/version.ts
54148
- var SDK_VERSION = "0.70.0";
54777
+ var SDK_VERSION = "0.70.3";
54149
54778
 
54150
54779
  // src/client/error.ts
54151
54780
  var RiverbankApiError = class _RiverbankApiError extends Error {
@@ -60780,6 +61409,112 @@ Examples:
60780
61409
  })
60781
61410
  );
60782
61411
 
61412
+ // src/cli/commands/style.ts
61413
+ init_buttons();
61414
+ init_site_styles();
61415
+ function buildStyleSelectionApplyInputFromOptions(options) {
61416
+ const baseSelectionVersion = Number(options.baseSelectionVersion);
61417
+ if (!Number.isInteger(baseSelectionVersion) || baseSelectionVersion < 0) {
61418
+ throw new Error("--base-selection-version must be a non-negative integer");
61419
+ }
61420
+ return {
61421
+ siteStyleId: options.siteStyleId,
61422
+ buttonPersonalityId: options.buttonPersonalityId ?? null,
61423
+ paletteVariantId: options.paletteVariantId ?? null,
61424
+ paletteOverrides: parsePaletteOverrides(options.paletteOverrides),
61425
+ headerLookId: options.headerLookId ?? null,
61426
+ footerLookId: options.footerLookId ?? null,
61427
+ baseSelectionVersion,
61428
+ selectionId: options.selectionId ?? null
61429
+ };
61430
+ }
61431
+ function parsePaletteOverrides(value) {
61432
+ if (value === void 0 || value.trim() === "") {
61433
+ return null;
61434
+ }
61435
+ const parsed = JSON.parse(value);
61436
+ if (!isStringRecord(parsed)) {
61437
+ throw new Error("--palette-overrides must be a JSON object with string values");
61438
+ }
61439
+ return parsed;
61440
+ }
61441
+ function isStringRecord(value) {
61442
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
61443
+ return false;
61444
+ }
61445
+ return Object.values(value).every((entry) => typeof entry === "string");
61446
+ }
61447
+ function buildStyleCatalogListRows(styles = curatedSiteStyles, options = {}) {
61448
+ const filteredStyles = options.siteStyleId ? styles.filter((style) => String(style.id) === options.siteStyleId) : styles;
61449
+ return filteredStyles.map((style) => ({
61450
+ siteStyleId: style.id,
61451
+ name: style.name,
61452
+ palettes: style.paletteVariantChoices.map((choice) => ({
61453
+ id: choice.id,
61454
+ label: findPaletteVariant(choice.id)?.name ?? choice.id
61455
+ })),
61456
+ buttonPersonalities: style.buttonPersonalityChoices.map((choice) => ({
61457
+ id: choice.id,
61458
+ label: findButtonPersonality(choice.id)?.name ?? choice.id
61459
+ })),
61460
+ headerLooks: style.recommendedHeaderLookIds.map((lookId) => ({
61461
+ id: lookId,
61462
+ label: findHeaderLook(lookId)?.label ?? lookId
61463
+ })),
61464
+ footerLooks: style.recommendedFooterLookIds.map((lookId) => ({
61465
+ id: lookId,
61466
+ label: findFooterLook(lookId)?.label ?? lookId
61467
+ }))
61468
+ }));
61469
+ }
61470
+ function formatStyleCatalogListRow(row) {
61471
+ return [
61472
+ row.siteStyleId,
61473
+ row.name,
61474
+ formatChoiceList(row.palettes),
61475
+ formatChoiceList(row.buttonPersonalities),
61476
+ formatChoiceList(row.headerLooks),
61477
+ formatChoiceList(row.footerLooks)
61478
+ ];
61479
+ }
61480
+ function formatChoiceList(choices) {
61481
+ return choices.map((choice) => `${choice.id} (${choice.label})`).join(", ");
61482
+ }
61483
+ var listCommand8 = new Command("list").description("List curated site styles and compatible selection IDs").option("--site-style-id <id>", "Show one curated site style").action(
61484
+ withErrorHandling(async (options, command) => {
61485
+ const { output } = getOutputContext(command);
61486
+ const rows = buildStyleCatalogListRows(curatedSiteStyles, options);
61487
+ if (options.siteStyleId && rows.length === 0) {
61488
+ output.error(`Unknown site style: ${options.siteStyleId}`);
61489
+ }
61490
+ output.table(
61491
+ ["Site Style ID", "Name", "Palettes", "Buttons", "Header Looks", "Footer Looks"],
61492
+ rows.map(formatStyleCatalogListRow)
61493
+ );
61494
+ })
61495
+ );
61496
+ var applyCommand = new Command("apply").description("Apply a curated site-style selection").requiredOption("--site-style-id <id>", "Site style ID, e.g. site-style:calm-studio").requiredOption("--base-selection-version <version>", "Current style selection version").option("--selection-id <id>", "Current style selection row ID").option("--button-personality-id <id>", "Button personality ID").option("--palette-variant-id <id>", "Palette variant ID").option("--palette-overrides <json>", "JSON object of palette token overrides").option("--header-look-id <id>", "Header look ID").option("--footer-look-id <id>", "Footer look ID").action(
61497
+ withErrorHandling(async (options, command) => {
61498
+ const { output, client } = createCommandContext(command);
61499
+ const input = buildStyleSelectionApplyInputFromOptions(options);
61500
+ const commandIr = buildApplySiteStyleSelectionCommand(input);
61501
+ output.info(`Applying site style: ${input.siteStyleId}`);
61502
+ const result = await client.theme.applySelection(input);
61503
+ output.success("Site style applied", {
61504
+ command: commandIr,
61505
+ themeId: result.themeId,
61506
+ selectionId: result.selectionId,
61507
+ selectionVersion: result.selectionVersion,
61508
+ savedAt: result.savedAt
61509
+ });
61510
+ })
61511
+ );
61512
+ var styleCommand = new Command("style").description("Manage curated site styles").addHelpText("after", `
61513
+ Examples:
61514
+ $ riverbankcms style apply --site-style-id site-style:calm-studio --base-selection-version 3
61515
+ $ riverbankcms style apply --site-style-id site-style:calm-studio --base-selection-version 3 --palette-variant-id soft-natural-sage
61516
+ `).addCommand(listCommand8).addCommand(applyCommand);
61517
+
60783
61518
  // src/cli/index.ts
60784
61519
  config({ path: ".env.local" });
60785
61520
  config({ path: ".env" });
@@ -60829,6 +61564,7 @@ program.addCommand(auditCommand);
60829
61564
  program.addCommand(compareCommand);
60830
61565
  program.addCommand(eventCommand);
60831
61566
  program.addCommand(courseCommand2);
61567
+ program.addCommand(styleCommand);
60832
61568
  program.addCommand(manifestCommand);
60833
61569
  program.addCommand(envCommand);
60834
61570
  program.addCommand(migrateCommand);