riverbankcms 0.11.0 → 0.12.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.
@@ -2770,16 +2770,6 @@ function projectSingleSubjectParticipantSlot(input) {
2770
2770
  default: return assertNever$1(input.target);
2771
2771
  }
2772
2772
  }
2773
- function projectEventSeriesSessionAttendanceParticipantSlot(input) {
2774
- return {
2775
- slotKey: unsafeAsParticipantSlotKey(`event_series_session_attendance:${input.attendeeId}`),
2776
- participation: {
2777
- kind: "event_series_session_attendance",
2778
- attendeeId: input.attendeeId,
2779
- registrationId: input.registrationId
2780
- }
2781
- };
2782
- }
2783
2773
  function projectEventRegistrationParticipantRoster(input) {
2784
2774
  const bookerSlot = buildSlot({
2785
2775
  slotKey: unsafeAsParticipantSlotKey(`event_registration_booker:${input.attendeeId}`),
@@ -2829,43 +2819,6 @@ function reconcileParticipantRoster(input) {
2829
2819
  issues.push(...findDuplicateParticipantEmails(input.slots));
2830
2820
  return issues;
2831
2821
  }
2832
- function planParticipantSubjectResolution(input) {
2833
- const existingParticipantIdByEmail = new Map(input.existingParticipantsByEmail.map((participant) => [participant.email, participant.participantId]));
2834
- const duplicateSlotKeysByEmail = new Map(input.projection.issues.filter((issue) => issue.kind === "duplicate_email_in_booking_context").map((issue) => [issue.email, issue.slotKeys]));
2835
- return input.projection.slots.map((slot) => {
2836
- if (slot.email === null) {
2837
- return {
2838
- kind: "staff_managed_slot",
2839
- slotKey: slot.slotKey
2840
- };
2841
- }
2842
- const duplicateSlotKeys = duplicateSlotKeysByEmail.get(slot.email);
2843
- if (duplicateSlotKeys !== undefined) {
2844
- return {
2845
- kind: "blocked_duplicate_participant_in_booking",
2846
- slotKey: slot.slotKey,
2847
- email: slot.email,
2848
- conflictingSlotKeys: duplicateSlotKeys
2849
- };
2850
- }
2851
- const participantId = existingParticipantIdByEmail.get(slot.email);
2852
- if (participantId !== undefined) {
2853
- return {
2854
- kind: "reuse_participant_by_site_email",
2855
- slotKey: slot.slotKey,
2856
- email: slot.email,
2857
- participantId
2858
- };
2859
- }
2860
- return {
2861
- kind: "create_participant",
2862
- slotKey: slot.slotKey,
2863
- email: slot.email,
2864
- displayName: slot.displayName,
2865
- phone: slot.phone
2866
- };
2867
- });
2868
- }
2869
2822
  function buildSlot(input) {
2870
2823
  const email = normalizeParticipantEmail(input.contact.email);
2871
2824
  return {
@@ -2904,213 +2857,6 @@ function assertNever$1(value) {
2904
2857
  throw new Error(`Unexpected participant variant: ${JSON.stringify(value)}`);
2905
2858
  }
2906
2859
 
2907
- //#endregion
2908
- //#region ../core/src/participant-identity.ts
2909
- function planPersonResolution(input) {
2910
- switch (input.kind) {
2911
- case "with_email":
2912
- if (input.existingParticipantIdByEmail !== null) {
2913
- return {
2914
- kind: "reuse_existing_person_by_email",
2915
- participantId: input.existingParticipantIdByEmail,
2916
- email: input.email
2917
- };
2918
- }
2919
- return {
2920
- kind: "create_contactable_person",
2921
- seed: {
2922
- displayName: input.displayName,
2923
- email: input.email,
2924
- phone: input.phone
2925
- }
2926
- };
2927
- case "without_email": return {
2928
- kind: "create_provisional_person",
2929
- seed: {
2930
- displayName: input.displayName,
2931
- phone: input.phone
2932
- }
2933
- };
2934
- default: return assertNever(input);
2935
- }
2936
- }
2937
- function planCustomerPersonResolution(input) {
2938
- const resolution = planPersonResolution(toCustomerPersonResolutionInput(input));
2939
- switch (resolution.kind) {
2940
- case "reuse_existing_person_by_email": return {
2941
- kind: "link_existing_person_by_email",
2942
- customerId: input.customerId,
2943
- participantId: resolution.participantId,
2944
- email: resolution.email
2945
- };
2946
- case "create_contactable_person": return {
2947
- kind: "create_contactable_person_for_customer",
2948
- customerId: input.customerId,
2949
- seed: resolution.seed
2950
- };
2951
- case "create_provisional_person": return {
2952
- kind: "create_provisional_person_for_customer",
2953
- customerId: input.customerId,
2954
- seed: resolution.seed
2955
- };
2956
- default: return assertNever(resolution);
2957
- }
2958
- }
2959
- function toCustomerPersonResolutionInput(input) {
2960
- switch (input.kind) {
2961
- case "with_email": return {
2962
- kind: "with_email",
2963
- displayName: input.displayName,
2964
- email: input.email,
2965
- phone: input.phone,
2966
- existingParticipantIdByEmail: input.existingParticipantIdByEmail
2967
- };
2968
- case "without_email": return {
2969
- kind: "without_email",
2970
- displayName: input.displayName,
2971
- phone: input.phone
2972
- };
2973
- default: return assertNever(input);
2974
- }
2975
- }
2976
- function planParticipationPersonResolution(input) {
2977
- switch (input.resolution.kind) {
2978
- case "blocked_duplicate_participant_in_booking": return {
2979
- kind: "blocked_duplicate_participant_in_booking",
2980
- slotKey: input.resolution.slotKey,
2981
- email: input.resolution.email,
2982
- conflictingSlotKeys: input.resolution.conflictingSlotKeys
2983
- };
2984
- case "create_participant":
2985
- case "reuse_participant_by_site_email":
2986
- case "staff_managed_slot": return applyParticipationResolutionPlan({
2987
- slotKey: input.resolution.slotKey,
2988
- participation: input.slot.participation,
2989
- resolution: planPersonResolution(toSlotPersonResolutionInput({
2990
- slot: input.slot,
2991
- resolution: input.resolution
2992
- }))
2993
- });
2994
- default: return assertNever(input.resolution);
2995
- }
2996
- }
2997
- function toSlotPersonResolutionInput(input) {
2998
- switch (input.resolution.kind) {
2999
- case "create_participant": return {
3000
- kind: "with_email",
3001
- displayName: input.resolution.displayName,
3002
- email: input.resolution.email,
3003
- phone: input.resolution.phone,
3004
- existingParticipantIdByEmail: null
3005
- };
3006
- case "reuse_participant_by_site_email": return {
3007
- kind: "with_email",
3008
- displayName: input.slot.displayName,
3009
- email: input.resolution.email,
3010
- phone: input.slot.phone,
3011
- existingParticipantIdByEmail: input.resolution.participantId
3012
- };
3013
- case "staff_managed_slot": return {
3014
- kind: "without_email",
3015
- displayName: input.slot.displayName,
3016
- phone: input.slot.phone
3017
- };
3018
- default: return assertNever(input.resolution);
3019
- }
3020
- }
3021
- function applyParticipationResolutionPlan(input) {
3022
- switch (input.resolution.kind) {
3023
- case "reuse_existing_person_by_email": return {
3024
- kind: "reuse_existing_person_for_slot",
3025
- slotKey: input.slotKey,
3026
- participantId: input.resolution.participantId,
3027
- participation: input.participation
3028
- };
3029
- case "create_contactable_person": return {
3030
- kind: "create_contactable_person_for_slot",
3031
- slotKey: input.slotKey,
3032
- seed: input.resolution.seed,
3033
- participation: input.participation
3034
- };
3035
- case "create_provisional_person": return {
3036
- kind: "create_provisional_person_for_slot",
3037
- slotKey: input.slotKey,
3038
- seed: input.resolution.seed,
3039
- participation: input.participation
3040
- };
3041
- default: return assertNever(input.resolution);
3042
- }
3043
- }
3044
- function planSingleSubjectParticipantMaterialization(input) {
3045
- const resolution = planPersonResolution(toSingleSubjectPersonResolutionInput(input));
3046
- switch (resolution.kind) {
3047
- case "reuse_existing_person_by_email": return {
3048
- kind: "reuse_existing_person_and_participation",
3049
- customerId: input.customerId,
3050
- participantId: resolution.participantId,
3051
- participation: input.participation
3052
- };
3053
- case "create_contactable_person": return {
3054
- kind: "create_contactable_person_and_participation",
3055
- customerId: input.customerId,
3056
- seed: resolution.seed,
3057
- participation: input.participation
3058
- };
3059
- case "create_provisional_person": return {
3060
- kind: "create_provisional_person_and_participation",
3061
- customerId: input.customerId,
3062
- seed: resolution.seed,
3063
- participation: input.participation
3064
- };
3065
- default: return assertNever(resolution);
3066
- }
3067
- }
3068
- function toSingleSubjectPersonResolutionInput(input) {
3069
- switch (input.kind) {
3070
- case "participant_subject": return {
3071
- kind: "with_email",
3072
- displayName: input.displayName,
3073
- email: input.email,
3074
- phone: input.phone,
3075
- existingParticipantIdByEmail: input.existingParticipantIdByEmail
3076
- };
3077
- case "provisional_single_subject_participant": return {
3078
- kind: "without_email",
3079
- displayName: input.displayName,
3080
- phone: input.phone
3081
- };
3082
- default: return assertNever(input);
3083
- }
3084
- }
3085
- function planCleanupReadiness(evidence) {
3086
- const blockers = collectCleanupReadinessBlockers(evidence);
3087
- if (blockers.length === 0) {
3088
- return {
3089
- kind: "ready",
3090
- evidence,
3091
- blockers: []
3092
- };
3093
- }
3094
- return {
3095
- kind: "blocked",
3096
- evidence,
3097
- blockers
3098
- };
3099
- }
3100
- function collectCleanupReadinessBlockers(evidence) {
3101
- const blockers = [];
3102
- if (evidence.legacyCustomerEmailCallSiteCount > 0) {
3103
- blockers.push("legacy_customer_email_call_sites_remaining");
3104
- }
3105
- if (evidence.parityFailureSurfaces.length > 0) {
3106
- blockers.push("parity_failures_remaining");
3107
- }
3108
- if (evidence.unresolvedHealthRowCount > 0) {
3109
- blockers.push("unresolved_health_rows_remaining");
3110
- }
3111
- return blockers;
3112
- }
3113
-
3114
2860
  //#endregion
3115
2861
  //#region ../core/src/public-url-validation.ts
3116
2862
  function buildPublicUrlValidationError(message, errorFactory) {
@@ -4836,6 +4582,10 @@ function parseMailingListSiteSetup(value) {
4836
4582
  });
4837
4583
  }
4838
4584
  if (value.tag !== "configured") return setupError("tag");
4585
+ return parseConfiguredSiteSetup(value, siteId.value);
4586
+ }
4587
+ function parseConfiguredSiteSetup(value, siteId) {
4588
+ if (typeof value.bookingOptInEnabled !== "boolean") return setupError("shape");
4839
4589
  const revision = parseMailingListSetupRevision(value.revision);
4840
4590
  if (revision === null) return setupError("revision");
4841
4591
  const form = parseMailingListGlobalForm(value.form);
@@ -4844,8 +4594,9 @@ function parseMailingListSiteSetup(value) {
4844
4594
  if (!provider.ok) return provider;
4845
4595
  return ok({
4846
4596
  tag: "configured",
4847
- siteId: siteId.value,
4597
+ siteId,
4848
4598
  revision,
4599
+ bookingOptInEnabled: value.bookingOptInEnabled,
4849
4600
  form: form.value,
4850
4601
  provider: provider.value
4851
4602
  });
@@ -5164,19 +4915,61 @@ function parseMailingListRuntimeContext(value) {
5164
4915
  if (!isRecord$1(value)) return invalidRuntimeContext();
5165
4916
  if (value.tag === "not_configured") return ok({ tag: "not_configured" });
5166
4917
  if (value.tag !== "configured") return invalidRuntimeContext();
4918
+ return parseConfiguredRuntimeContext(value);
4919
+ }
4920
+ function parseConfiguredRuntimeContext(value) {
5167
4921
  const revision = parseMailingListSetupRevision(value.revision);
5168
4922
  const form = parseMailingListGlobalForm(value.form);
5169
4923
  const provider = parseRuntimeProvider(value.provider);
5170
- if (revision === null || !form.ok || provider === null) {
4924
+ const bookingSignup = parseBookingSignupOffer(value.bookingSignup);
4925
+ if (revision === null || !form.ok || provider === null || bookingSignup === null) {
5171
4926
  return invalidRuntimeContext();
5172
4927
  }
5173
4928
  return ok({
5174
4929
  tag: "configured",
5175
4930
  revision,
4931
+ bookingSignup,
5176
4932
  form: form.value,
5177
4933
  provider
5178
4934
  });
5179
4935
  }
4936
+ /** Destination facts are resolved once by the provider adapter, before projection. */
4937
+ function planBookingSignupOffer(setup, destination) {
4938
+ if (destination === "unavailable") return {
4939
+ tag: "unavailable",
4940
+ reason: "destination"
4941
+ };
4942
+ const required = resolveRequiredGlobalFields(setup.form.fields);
4943
+ if (setup.form.fields.preset !== "emailOnly" && setup.form.fields.preset !== "emailName" || required.some((field) => field !== "name")) {
4944
+ return {
4945
+ tag: "unavailable",
4946
+ reason: "fields"
4947
+ };
4948
+ }
4949
+ return setup.bookingOptInEnabled ? { tag: "offered" } : {
4950
+ tag: "unavailable",
4951
+ reason: "disabled"
4952
+ };
4953
+ }
4954
+ function resolveBookingSignupOffer(context, siteName) {
4955
+ const name = siteName?.trim() ?? "";
4956
+ return context?.tag === "configured" && context.bookingSignup.tag === "offered" ? { siteName: name.length > 0 ? name : "this site" } : null;
4957
+ }
4958
+ function parseBookingSignupOffer(value) {
4959
+ if (value === undefined) return {
4960
+ tag: "unavailable",
4961
+ reason: "disabled"
4962
+ };
4963
+ if (!isRecord$1(value)) return null;
4964
+ if (value.tag === "offered") return { tag: "offered" };
4965
+ if (value.tag === "unavailable" && (value.reason === "disabled" || value.reason === "fields" || value.reason === "destination")) {
4966
+ return {
4967
+ tag: "unavailable",
4968
+ reason: value.reason
4969
+ };
4970
+ }
4971
+ return null;
4972
+ }
5180
4973
  function parseRuntimeProvider(value) {
5181
4974
  if (!isRecord$1(value)) return null;
5182
4975
  switch (value.provider) {
@@ -7137,6 +6930,18 @@ function parseSiteNavigationLocations(rows) {
7137
6930
  return ok(locations);
7138
6931
  }
7139
6932
 
6933
+ //#endregion
6934
+ //#region ../core/src/navigation-portal-labels.ts
6935
+ /**
6936
+ * What a customer sign-in link in a site's menu says when the site hasn't set
6937
+ * its own text. The site renderer falls back to these, and the dashboard's
6938
+ * menu editor shows them, so what an editor sees is what visitors get.
6939
+ */
6940
+ const PORTAL_NAV_DEFAULT_LABELS = {
6941
+ loggedOut: "Login",
6942
+ loggedIn: "My Account"
6943
+ };
6944
+
7140
6945
  //#endregion
7141
6946
  //#region ../core/src/event-preset-vocabulary.ts
7142
6947
  const EVENT_PRESET_VOCABULARY = {
package/dist/testing.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import "./sdk-event-upsert-CRQseim3.mjs";
3
- import "./src-CiZrHLCj.mjs";
4
- import { n as syncLocalMediaForPush, r as syncLocalMediaForPull, y as writeMediaManifest } from "./local-sync-7ecbT9He.mjs";
2
+ import "./sdk-event-upsert-CuDl9Gk1.mjs";
3
+ import "./src-9YtMip19.mjs";
4
+ import { n as syncLocalMediaForPush, r as syncLocalMediaForPull, y as writeMediaManifest } from "./local-sync-CCfQzCgJ.mjs";
5
5
 
6
6
  export { syncLocalMediaForPull, syncLocalMediaForPush, writeMediaManifest };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "riverbankcms",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Riverbank CMS command-line tools for SDK site developers",
5
5
  "bin": {
6
6
  "riverbankcms": "dist/cli/index.mjs"
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { t as loadConfigFile } from "./load-config-B7AiZalH.mjs";
3
-
4
- export { loadConfigFile };