riverbankcms 0.4.2 → 0.4.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.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { c as EVENT_PRESET_VALUES } from "./src-BRAF1Dee.mjs";
3
- import { a as classifySdkEventPricing, i as classifySdkEventSchedule, o as classifySdkEventPaymentTerms, r as sdkEventUpsertOptionalFieldSchemas } from "./sdk-event-upsert-C6zsxDcf.mjs";
2
+ import { c as EVENT_PRESET_VALUES } from "./src-DKm0bLEA.mjs";
3
+ import { a as classifySdkEventPricing, i as classifySdkEventSchedule, o as classifySdkEventPaymentTerms, r as sdkEventUpsertOptionalFieldSchemas } from "./sdk-event-upsert-Dy08IXYL.mjs";
4
4
  import { z } from "zod";
5
5
 
6
6
  //#region ../blocks/src/lib/typeGuards.ts
@@ -403,12 +403,6 @@ const ROUTE_METADATA_MANAGED_FIELDS_BY_TYPE = {
403
403
  "draftStatus",
404
404
  "scheduledPublishAt"
405
405
  ],
406
- course: [
407
- "draftTitle",
408
- "draftSlug",
409
- "draftStatus",
410
- "scheduledPublishAt"
411
- ],
412
406
  product: [
413
407
  "draftTitle",
414
408
  "draftSlug",
@@ -2082,40 +2076,6 @@ const EVENT_CONTENT_TYPE_SCHEMA = {
2082
2076
  plural: "Events"
2083
2077
  }
2084
2078
  };
2085
- const COURSE_CONTENT_TYPE_SCHEMA = {
2086
- version: 1,
2087
- fields: [
2088
- {
2089
- id: "summary",
2090
- type: "textarea",
2091
- label: "Summary",
2092
- description: "Short teaser shown in listings.",
2093
- rows: 3
2094
- },
2095
- {
2096
- id: "image",
2097
- type: "media",
2098
- label: "Listing image",
2099
- description: "Optional image used for course cards and previews."
2100
- },
2101
- {
2102
- id: "body",
2103
- type: "richText",
2104
- label: "Details",
2105
- description: "Full course details and curriculum."
2106
- }
2107
- ],
2108
- routing: {
2109
- enabled: true,
2110
- pattern: "/courses/{slug}",
2111
- slugField: "slug",
2112
- prefix: "/courses/"
2113
- },
2114
- labels: {
2115
- singular: "Course",
2116
- plural: "Courses"
2117
- }
2118
- };
2119
2079
  const TEAM_MEMBER_CONTENT_TYPE_SCHEMA = {
2120
2080
  version: 1,
2121
2081
  fields: [
@@ -2324,7 +2284,6 @@ const PRODUCT_CATEGORY_CONTENT_TYPE_SCHEMA = {
2324
2284
  const BUILTIN_CONTENT_TYPE_SCHEMAS = {
2325
2285
  post: POST_CONTENT_TYPE_SCHEMA,
2326
2286
  event: EVENT_CONTENT_TYPE_SCHEMA,
2327
- course: COURSE_CONTENT_TYPE_SCHEMA,
2328
2287
  "team-member": TEAM_MEMBER_CONTENT_TYPE_SCHEMA,
2329
2288
  product: PRODUCT_CONTENT_TYPE_SCHEMA,
2330
2289
  testimonial: TESTIMONIAL_CONTENT_TYPE_SCHEMA,
@@ -2345,7 +2304,6 @@ function deriveFieldIdSet(schema) {
2345
2304
  const BUILTIN_CONTENT_TYPE_FIELD_IDS = {
2346
2305
  post: deriveFieldIdSet(BUILTIN_CONTENT_TYPE_SCHEMAS.post),
2347
2306
  event: deriveFieldIdSet(BUILTIN_CONTENT_TYPE_SCHEMAS.event),
2348
- course: deriveFieldIdSet(BUILTIN_CONTENT_TYPE_SCHEMAS.course),
2349
2307
  "team-member": deriveFieldIdSet(BUILTIN_CONTENT_TYPE_SCHEMAS["team-member"]),
2350
2308
  product: deriveFieldIdSet(BUILTIN_CONTENT_TYPE_SCHEMAS.product),
2351
2309
  testimonial: deriveFieldIdSet(BUILTIN_CONTENT_TYPE_SCHEMAS.testimonial),
@@ -2365,10 +2323,6 @@ const BUILTIN_PREVIEW_LINKED_ENTRY_EDITING = {
2365
2323
  kind: "unsupported-domain-backed",
2366
2324
  reason: DOMAIN_BACKED_LINKED_ENTRY_REASON
2367
2325
  },
2368
- course: {
2369
- kind: "unsupported-domain-backed",
2370
- reason: DOMAIN_BACKED_LINKED_ENTRY_REASON
2371
- },
2372
2326
  "team-member": { kind: "generic" },
2373
2327
  product: {
2374
2328
  kind: "unsupported-domain-backed",
@@ -3263,7 +3217,6 @@ function assertNever(value) {
3263
3217
  //#region ../content-model/src/templates/defaults.ts
3264
3218
  const POST_EXCERPT_FALLBACK = fallbackBinding(fieldBinding("excerpt"), transformBinding(TEMPLATE_BINDING_TRANSFORMS.RICHTEXT_FIRST_PARAGRAPH, { input: fieldBinding("body") }));
3265
3219
  const EVENT_SUBHEADLINE_FALLBACK = fallbackBinding(fieldBinding("summary"), transformBinding(TEMPLATE_BINDING_TRANSFORMS.RICHTEXT_FIRST_PARAGRAPH, { input: fieldBinding("body") }));
3266
- const COURSE_SUMMARY_FALLBACK = fallbackBinding(fieldBinding("summary"), transformBinding(TEMPLATE_BINDING_TRANSFORMS.RICHTEXT_FIRST_PARAGRAPH, { input: fieldBinding("body") }));
3267
3220
  const ENTRY_TITLE_INLINE_TEXT = transformBinding(TEMPLATE_BINDING_TRANSFORMS.TEXT_INLINE_TEXT, { input: metaBinding("title") });
3268
3221
  const POST_BODY_TEXT_BINDINGS = {
3269
3222
  body: fieldBinding("body"),
@@ -3366,6 +3319,7 @@ const DEFAULT_TEMPLATE_DEFINITIONS = {
3366
3319
  {
3367
3320
  blockKind: "block.body-text",
3368
3321
  scope: "entry",
3322
+ content: { body: createRichTextDoc([""]) },
3369
3323
  bindings: EVENT_BODY_TEXT_BINDINGS
3370
3324
  },
3371
3325
  {
@@ -3385,7 +3339,6 @@ const DEFAULT_TEMPLATE_DEFINITIONS = {
3385
3339
  showVenue: true,
3386
3340
  showCapacity: true,
3387
3341
  successMessage: "Thank you for registering! Check your email for confirmation details.",
3388
- waitlistMessage: "You've been added to the waitlist. We'll email you a claim link if a spot opens up.",
3389
3342
  buttonText: "Complete Registration",
3390
3343
  buttonVariant: "primary"
3391
3344
  },
@@ -3396,64 +3349,6 @@ const DEFAULT_TEMPLATE_DEFINITIONS = {
3396
3349
  }
3397
3350
  ]
3398
3351
  },
3399
- course: {
3400
- templateKey: "default",
3401
- name: "Course detail",
3402
- description: "Standard landing page for multi-session courses.",
3403
- metadata: {},
3404
- blocks: [
3405
- {
3406
- blockKind: "block.hero",
3407
- scope: "entry",
3408
- bindings: {
3409
- eyebrow: literalBinding("Course"),
3410
- headline: metaBinding("title"),
3411
- headlineInline: ENTRY_TITLE_INLINE_TEXT,
3412
- subheadline: COURSE_SUMMARY_FALLBACK
3413
- }
3414
- },
3415
- {
3416
- blockKind: "block.course-details",
3417
- scope: "entry",
3418
- content: {
3419
- heading: "Course details",
3420
- showTitle: false,
3421
- showDescription: false,
3422
- showSessions: true,
3423
- sessionsLimit: "10",
3424
- showVenue: true,
3425
- showPrice: true,
3426
- showCapacity: true,
3427
- showEnrollmentStatus: true,
3428
- showMembershipNote: true
3429
- }
3430
- },
3431
- {
3432
- blockKind: SYSTEM_ENTRY_SLOT_BLOCK_KIND,
3433
- scope: "template",
3434
- content: {
3435
- slotKey: "main",
3436
- label: "Page content"
3437
- }
3438
- },
3439
- {
3440
- blockKind: "block.course-registration",
3441
- scope: "entry",
3442
- content: {
3443
- heading: "Enroll in this course",
3444
- showSessions: true,
3445
- showPrice: true,
3446
- showCapacity: true,
3447
- showVenue: true,
3448
- successMessage: "You're enrolled! Check your email for confirmation and session details.",
3449
- waitlistMessage: "You've been added to the waitlist. We'll email you a claim link if a spot opens up.",
3450
- membershipMessage: "Enrolled using your membership! Check your email for session details.",
3451
- buttonText: "Complete Enrollment",
3452
- buttonVariant: "primary"
3453
- }
3454
- }
3455
- ]
3456
- },
3457
3352
  "team-member": {
3458
3353
  templateKey: "default",
3459
3354
  name: "Team member profile",
@@ -3471,6 +3366,7 @@ const DEFAULT_TEMPLATE_DEFINITIONS = {
3471
3366
  }, {
3472
3367
  blockKind: "block.body-text",
3473
3368
  scope: "entry",
3369
+ content: { body: createRichTextDoc([""]) },
3474
3370
  bindings: TEAM_MEMBER_BODY_TEXT_BINDINGS
3475
3371
  }]
3476
3372
  },
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import "./sdk-peer-CeNepTFW.mjs";
3
+ import { t as loadConfigFile } from "./load-config-lESIf8eO.mjs";
4
+
5
+ export { loadConfigFile };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as assertCompatibleSdkPeer } from "./sdk-peer-C6kOODEY.mjs";
2
+ import { n as assertCompatibleSdkPeer } from "./sdk-peer-CeNepTFW.mjs";
3
3
  import { dirname, resolve } from "path";
4
4
  import { createJiti } from "jiti";
5
5
  import { existsSync } from "fs";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { At as ok, kt as err, nt as parseSiteId } from "./src-BRAF1Dee.mjs";
2
+ import { At as ok, kt as err, nt as parseSiteId } from "./src-DKm0bLEA.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-BRAF1Dee.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-CaWqAqfn.mjs";
2
+ import "../src-DKm0bLEA.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-DPS1XAby.mjs";
4
4
 
5
5
  export { deriveGeneratedPackageRanges, deriveScaffoldLocalManifest, deriveScaffoldPlan, findPackageManifestPath, loadGeneratedPackageRanges, preflightScaffoldPlan, preflightScaffoldTargets, prepareScaffoldExecution, writeScaffoldFiles };
@@ -1,11 +1,75 @@
1
1
  #!/usr/bin/env node
2
- import { B as parseUtcIsoDateTimeString, W as parseBookingTimeZone } from "./src-BRAF1Dee.mjs";
2
+ import { B as parseUtcIsoDateTimeString, W as parseBookingTimeZone } from "./src-DKm0bLEA.mjs";
3
3
  import { z } from "zod";
4
4
 
5
+ //#region ../api/src/bookingPaymentTermSchemas.ts
6
+ const bookingDepositRefundPolicySchema = z.enum(["refundable", "non_refundable"]);
7
+ const bookingInstalmentPlanSchema = z.discriminatedUnion("kind", [
8
+ z.object({
9
+ kind: z.literal("deposit_plus_one_remainder"),
10
+ depositAmountCents: z.number().int().nonnegative(),
11
+ depositRefundability: bookingDepositRefundPolicySchema,
12
+ remainderDueCount: z.number().int().positive(),
13
+ intervalUnit: z.enum([
14
+ "day",
15
+ "week",
16
+ "month"
17
+ ])
18
+ }),
19
+ z.object({
20
+ kind: z.literal("deposit_plus_scheduled_instalments"),
21
+ depositAmountCents: z.number().int().nonnegative(),
22
+ depositRefundability: bookingDepositRefundPolicySchema,
23
+ instalmentCount: z.number().int().positive(),
24
+ intervalCount: z.number().int().positive(),
25
+ intervalUnit: z.enum([
26
+ "day",
27
+ "week",
28
+ "month"
29
+ ])
30
+ }),
31
+ z.object({
32
+ kind: z.literal("equal_scheduled_instalments"),
33
+ instalmentCount: z.number().int().positive(),
34
+ intervalCount: z.number().int().positive(),
35
+ intervalUnit: z.enum([
36
+ "day",
37
+ "week",
38
+ "month"
39
+ ])
40
+ })
41
+ ]);
42
+ const bookingFlexibleBalanceDueDateRuleSchema = z.discriminatedUnion("kind", [z.object({
43
+ kind: z.literal("relative_to_start_date"),
44
+ daysBeforeStart: z.number().int().positive()
45
+ }), z.object({
46
+ kind: z.literal("fixed_calendar_date"),
47
+ dueAt: z.string().datetime()
48
+ })]);
49
+ const bookingFlexibleBalanceConfigSchema = z.object({
50
+ upfrontAmountCents: z.number().int().nonnegative(),
51
+ dueDateRule: bookingFlexibleBalanceDueDateRuleSchema,
52
+ depositRefundability: bookingDepositRefundPolicySchema
53
+ });
54
+ const bookingPaymentCollectionOptionSchema = z.discriminatedUnion("kind", [
55
+ z.object({ kind: z.literal("upfront") }),
56
+ z.object({ kind: z.literal("deferred_manual") }),
57
+ z.object({
58
+ kind: z.literal("instalment_plan"),
59
+ plan: bookingInstalmentPlanSchema
60
+ }),
61
+ z.object({
62
+ kind: z.literal("flexible_balance"),
63
+ config: bookingFlexibleBalanceConfigSchema
64
+ })
65
+ ]);
66
+
67
+ //#endregion
5
68
  //#region ../api/src/sdk-event-payment-terms.ts
6
69
  const supportedKinds = new Set([
7
70
  "upfront",
8
71
  "deferred_manual",
72
+ "instalment_plan",
9
73
  "flexible_balance"
10
74
  ]);
11
75
  function issue$2(path, message) {
@@ -26,6 +90,13 @@ function isPositiveWholeNumber(value) {
26
90
  function isDepositRefundability(value) {
27
91
  return value === "refundable" || value === "non_refundable";
28
92
  }
93
+ function validateInstalmentPlan(raw, path) {
94
+ if (!isRecord$1(raw)) {
95
+ return [issue$2(path, "Instalment plan must be an object")];
96
+ }
97
+ const parsed = bookingInstalmentPlanSchema.safeParse(raw);
98
+ return parsed.success ? parsed.data : parsed.error.issues.map((problem) => issue$2([...path, ...problem.path.map(String)], `Invalid instalment plan: ${problem.message}`));
99
+ }
29
100
  function isSupportedOptionKind(value) {
30
101
  return typeof value === "string" && supportedKinds.has(value);
31
102
  }
@@ -90,15 +161,19 @@ function validateCollectionOption(raw, index) {
90
161
  if (!isRecord$1(raw)) {
91
162
  return [issue$2(path, "Payment option must be an object")];
92
163
  }
93
- if (raw.kind === "instalment_plan") {
94
- return [issue$2([...path, "kind"], "Event instalment plans are not supported yet. Use upfront, deferred_manual, or flexible_balance.")];
95
- }
96
164
  if (!isSupportedOptionKind(raw.kind)) {
97
- return [issue$2([...path, "kind"], "Payment option kind must be upfront, deferred_manual, or flexible_balance")];
165
+ return [issue$2([...path, "kind"], "Payment option kind must be upfront, deferred_manual, instalment_plan, or flexible_balance")];
98
166
  }
99
167
  switch (raw.kind) {
100
168
  case "upfront":
101
169
  case "deferred_manual": return { kind: raw.kind };
170
+ case "instalment_plan": {
171
+ const plan = validateInstalmentPlan(raw.plan, [...path, "plan"]);
172
+ return Array.isArray(plan) ? plan : {
173
+ kind: "instalment_plan",
174
+ plan
175
+ };
176
+ }
102
177
  case "flexible_balance": {
103
178
  const config = validateFlexibleBalanceConfig(raw.config, [...path, "config"]);
104
179
  if (Array.isArray(config)) {
@@ -127,8 +202,8 @@ function optionCombinationIssues(options) {
127
202
  if (options.length > 2) {
128
203
  issues.push(issue$2(["allowedOptions"], "Event payment terms can offer one option, or a choice between upfront and one alternative option"));
129
204
  }
130
- if (options.length === 2 && (!seenKinds.has("upfront") || !seenKinds.has("deferred_manual") && !seenKinds.has("flexible_balance"))) {
131
- issues.push(issue$2(["allowedOptions"], "Event payment terms with two options must combine upfront with deferred_manual or flexible_balance"));
205
+ if (options.length === 2 && (!seenKinds.has("upfront") || !seenKinds.has("deferred_manual") && !seenKinds.has("instalment_plan") && !seenKinds.has("flexible_balance"))) {
206
+ issues.push(issue$2(["allowedOptions"], "Event payment terms with two options must combine upfront with one alternative option"));
132
207
  }
133
208
  return issues;
134
209
  }
@@ -3,7 +3,7 @@ import { existsSync, readFileSync } from "node:fs";
3
3
  import { dirname, join, parse } from "node:path";
4
4
 
5
5
  //#region package.json
6
- var version = "0.4.2";
6
+ var version = "0.4.3";
7
7
  var peerDependencies = { "@riverbankcms/sdk": ">=0.130.0 <1.0.0" };
8
8
  var package_default = {
9
9
  name: "riverbankcms",
@@ -79,7 +79,7 @@ var package_default = {
79
79
  //#endregion
80
80
  //#region src/version.ts
81
81
  /** The package manifest is the source-run fallback; builds inject this value. */
82
- const CLI_VERSION = typeof "0.4.2" === "string" ? "0.4.2" : version;
82
+ const CLI_VERSION = typeof "0.4.3" === "string" ? "0.4.3" : version;
83
83
  /**
84
84
  * The CLI's SDK peer range is bundled from the CLI manifest alongside its
85
85
  * version. Runtime config loading uses this value as the single compatibility
@@ -53,6 +53,7 @@ const unsafeAsEventOfferingId = (id) => id;
53
53
  const unsafeAsEventSeriesId = (id) => id;
54
54
  const unsafeAsEventPageRouteSlug = (value) => value;
55
55
  const unsafeAsTicketTypeId = (id) => id;
56
+ const unsafeAsEventSeriesRegistrationId = (id) => id;
56
57
  const unsafeAsEventCategoryId = (id) => id;
57
58
  const unsafeAsVenueId = (id) => id;
58
59
  const unsafeAsPricingOptionId = (id) => id;
@@ -104,7 +105,6 @@ const unsafeAsCheckoutLineId = (id) => id;
104
105
  const unsafeAsAttendeeId = (id) => id;
105
106
  const unsafeAsCustomerPassId = (id) => id;
106
107
  const unsafeAsCustomerMembershipId = (id) => id;
107
- const unsafeAsEnrollmentId = (id) => id;
108
108
  const unsafeAsAppointmentId = (id) => id;
109
109
  const unsafeAsAppointmentServiceId = (id) => id;
110
110
  const unsafeAsAppointmentResourceId = (id) => id;
@@ -194,7 +194,7 @@ const parseCustomerId = (value) => parseUuidBrand(value, unsafeAsCustomerId);
194
194
  const parseCustomerPassId = (value) => parseUuidBrand(value, unsafeAsCustomerPassId);
195
195
  const parseCustomerMembershipId = (value) => parseUuidBrand(value, unsafeAsCustomerMembershipId);
196
196
  const parseEventSeriesId = (value) => parseUuidBrand(value, unsafeAsEventSeriesId);
197
- const parseEnrollmentId = (value) => parseUuidBrand(value, unsafeAsEnrollmentId);
197
+ const parseEventSeriesRegistrationId = (value) => parseUuidBrand(value, unsafeAsEventSeriesRegistrationId);
198
198
  const parseParticipantId = (value) => parseUuidBrand(value, unsafeAsParticipantId);
199
199
  const parseParticipantParticipationId = (value) => parseUuidBrand(value, unsafeAsParticipantParticipationId);
200
200
  const parseOrderItemId = (value) => parseUuidBrand(value, unsafeAsOrderItemId);
@@ -558,7 +558,7 @@ function publicEventPricingType(pricing) {
558
558
  case "single_paid":
559
559
  case "ticket_types":
560
560
  case "sliding_scale":
561
- case "course": return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
561
+ case "whole_series": return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
562
562
  case "external": return "external";
563
563
  }
564
564
  }
@@ -569,7 +569,7 @@ function publicEventPricingCurrency(pricing) {
569
569
  case "single_paid":
570
570
  case "ticket_types":
571
571
  case "sliding_scale": return pricing.currency;
572
- case "course": return pricing.display.display.currency;
572
+ case "whole_series": return pricing.display.display.currency;
573
573
  case "external": return null;
574
574
  }
575
575
  }
@@ -583,7 +583,7 @@ function publicEventPricingMode(pricing) {
583
583
  case "ticket_types": return "ticket_types";
584
584
  case "sliding_scale": return "sliding_scale";
585
585
  case "drop_in":
586
- case "course":
586
+ case "whole_series":
587
587
  case "external": return undefined;
588
588
  }
589
589
  }
@@ -593,7 +593,7 @@ function publicEventTicketTypes(pricing) {
593
593
  function isFreePublicEventPriceDisplay(display) {
594
594
  switch (display.kind) {
595
595
  case "free": return true;
596
- case "course": return display.display.kind === "free";
596
+ case "whole_series": return display.display.kind === "free";
597
597
  case "exact":
598
598
  case "from":
599
599
  case "range":
@@ -629,7 +629,7 @@ function formatBookingPriceDisplay(display, options = {}) {
629
629
  case "mixed": return display.paidToAmount > display.paidFromAmount ? `Free / ${formatCurrencyAmount(display.paidFromAmount, display.currency, options)} - ${formatCurrencyAmount(display.paidToAmount, display.currency, options)}` : `Free / ${formatCurrencyAmount(display.paidFromAmount, display.currency, options)}`;
630
630
  case "unavailable": return "Pricing unavailable";
631
631
  case "external": return display.label;
632
- case "course": return formatCoursePriceDisplayLabel(display.display, options);
632
+ case "whole_series": return formatCoursePriceDisplayLabel(display.display, options);
633
633
  default: return assertNever(display);
634
634
  }
635
635
  }
@@ -1628,7 +1628,7 @@ const RECTIFICATION_SURFACES = [
1628
1628
  "customer_profile",
1629
1629
  "booking_identity",
1630
1630
  "event_registration_identity",
1631
- "course_enrollment_identity",
1631
+ "event_series_registration_identity",
1632
1632
  "person_record_entry",
1633
1633
  "booking_question_snapshot",
1634
1634
  "form_submission",
@@ -2141,13 +2141,13 @@ function projectAppointmentParticipantSlot(input) {
2141
2141
  }
2142
2142
  });
2143
2143
  }
2144
- function projectCourseEnrollmentParticipantSlot(input) {
2144
+ function projectEventSeriesRegistrationParticipantSlot(input) {
2145
2145
  return buildSlot({
2146
- slotKey: unsafeAsParticipantSlotKey(`course_enrollment:${input.enrollmentId}`),
2146
+ slotKey: unsafeAsParticipantSlotKey(`event_series_registration:${input.registrationId}`),
2147
2147
  contact: input.customer,
2148
2148
  participation: {
2149
- kind: "course_enrollment",
2150
- enrollmentId: input.enrollmentId
2149
+ kind: "event_series_registration",
2150
+ registrationId: input.registrationId
2151
2151
  }
2152
2152
  });
2153
2153
  }
@@ -2187,20 +2187,20 @@ function projectSingleSubjectParticipantSlot(input) {
2187
2187
  appointmentId: input.target.appointmentId,
2188
2188
  customer: input.customer
2189
2189
  });
2190
- case "course_enrollment": return projectCourseEnrollmentParticipantSlot({
2191
- enrollmentId: input.target.enrollmentId,
2190
+ case "event_series_registration": return projectEventSeriesRegistrationParticipantSlot({
2191
+ registrationId: input.target.registrationId,
2192
2192
  customer: input.customer
2193
2193
  });
2194
2194
  default: return assertNever$1(input.target);
2195
2195
  }
2196
2196
  }
2197
- function projectCourseSessionAttendanceParticipantSlot(input) {
2197
+ function projectEventSeriesSessionAttendanceParticipantSlot(input) {
2198
2198
  return {
2199
- slotKey: unsafeAsParticipantSlotKey(`course_session_attendance:${input.attendeeId}`),
2199
+ slotKey: unsafeAsParticipantSlotKey(`event_series_session_attendance:${input.attendeeId}`),
2200
2200
  participation: {
2201
- kind: "course_session_attendance",
2201
+ kind: "event_series_session_attendance",
2202
2202
  attendeeId: input.attendeeId,
2203
- enrollmentId: input.enrollmentId
2203
+ registrationId: input.registrationId
2204
2204
  }
2205
2205
  };
2206
2206
  }
@@ -4401,19 +4401,35 @@ function maskEmail(email) {
4401
4401
 
4402
4402
  //#endregion
4403
4403
  //#region ../core/src/slug.ts
4404
+ const REMOVED_CHARACTERS = /['\u2019]/g;
4405
+ const COMBINING_DIACRITICS = /[\u0300-\u036f]/g;
4406
+ const SEPARATOR_RUN = /[^a-z0-9]+/g;
4407
+ const TRAILING_SLUG_SEPARATORS = /[-/]+$/g;
4408
+ function slugifySegment(text) {
4409
+ return text.normalize("NFD").replace(COMBINING_DIACRITICS, "").toLowerCase().replace(REMOVED_CHARACTERS, "").replace(SEPARATOR_RUN, "-").replace(/^-+|-+$/g, "");
4410
+ }
4404
4411
  /**
4405
- * Convert a string to a URL-safe slug
4412
+ * Convert a string to a URL-safe slug.
4406
4413
  *
4407
- * @param text - The text to slugify
4408
- * @returns URL-safe slug (lowercase, alphanumeric + hyphens)
4414
+ * Every non-alphanumeric character (underscores included) is a separator and
4415
+ * collapses to a single hyphen, which keeps output inside the `site_routes`
4416
+ * slug constraint `^[a-z0-9]+([a-z0-9\-/]*[a-z0-9])?$`.
4417
+ *
4418
+ * This is the single slug implementation for the monorepo: block-form and the
4419
+ * shop admin catalog delegate here rather than keeping their own variants.
4409
4420
  *
4410
4421
  * @example
4411
4422
  * slugify("Initial Consultation") // "initial-consultation"
4412
- * slugify("90-Minute Deep Tissue") // "90-minute-deep-tissue"
4413
4423
  * slugify("Reiki & Energy Healing") // "reiki-energy-healing"
4424
+ * slugify("Don't Stop") // "dont-stop"
4425
+ * slugify("draft_post") // "draft-post"
4426
+ * slugify("Blog / My Post", { preserveSegments: true }) // "blog/my-post"
4414
4427
  */
4415
- function slugify(text) {
4416
- return text.toString().toLowerCase().trim().replace(/\s+/g, "-").replace(/[^\w\-]+/g, "").replace(/\-\-+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
4428
+ function slugify(text, options = {}) {
4429
+ const source = text.toString().trim();
4430
+ const slug = options.preserveSegments === true ? source.split("/").map(slugifySegment).filter((segment) => segment.length > 0).join("/") : slugifySegment(source);
4431
+ if (options.maxLength === undefined) return slug;
4432
+ return slug.slice(0, options.maxLength).replace(TRAILING_SLUG_SEPARATORS, "");
4417
4433
  }
4418
4434
  /**
4419
4435
  * Generate a unique slug by appending a number if needed