riverbankcms 0.17.1 → 0.18.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.
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env node
2
+ import { z } from "zod";
3
+
2
4
  //#region ../core/src/result.ts
3
5
  function ok(value) {
4
6
  return {
@@ -3928,7 +3930,7 @@ function parsePositiveInteger(value) {
3928
3930
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
3929
3931
  }
3930
3932
  function parseNewsletterListId(value) {
3931
- return parseTrimmedMatchingString(value, UUID_PATTERN);
3933
+ return parseTrimmedMatchingString(typeof value === "string" ? value.toLowerCase() : value, UUID_PATTERN);
3932
3934
  }
3933
3935
  function parseMailchimpConnectionId(value) {
3934
3936
  return parseTrimmedMatchingString(value, UUID_PATTERN);
@@ -3972,7 +3974,7 @@ function sameMailingListPlacementTargeting(left, right) {
3972
3974
  }
3973
3975
  function mailingListTargetingChoiceIds(targeting) {
3974
3976
  switch (targeting.provider) {
3975
- case "native": return targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
3977
+ case "native": return targeting.selection.tag === "general" ? [] : targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
3976
3978
  case "brevo": return targeting.selection.tag === "fixed" ? targeting.selection.listIds : targeting.selection.offeredListIds;
3977
3979
  case "mailchimp": return targeting.selection.tag === "fixed" ? targeting.selection.interestIds : targeting.selection.offeredInterestIds;
3978
3980
  }
@@ -4002,7 +4004,10 @@ function resolveDefaultTarget(setup) {
4002
4004
  switch (setup.provider) {
4003
4005
  case "native": return {
4004
4006
  provider: "native",
4005
- topicIds: [setup.defaultTopicId]
4007
+ audience: setup.defaultAudience.kind === "general" ? { kind: "general" } : {
4008
+ kind: "topics",
4009
+ topicIds: [setup.defaultAudience.topicId]
4010
+ }
4006
4011
  };
4007
4012
  case "brevo": return {
4008
4013
  provider: "brevo",
@@ -4023,16 +4028,28 @@ function resolveCustomTarget(targeting, visitorSelection) {
4023
4028
  }
4024
4029
  }
4025
4030
  function resolveNativeTarget(targeting, selection) {
4031
+ if (targeting.selection.tag === "general") {
4032
+ return selection === undefined ? ok({
4033
+ provider: "native",
4034
+ audience: { kind: "general" }
4035
+ }) : err({ tag: "visitor_selection_not_allowed" });
4036
+ }
4026
4037
  if (targeting.selection.tag === "fixed") {
4027
4038
  return selection === undefined ? ok({
4028
4039
  provider: "native",
4029
- topicIds: targeting.selection.topicIds
4040
+ audience: {
4041
+ kind: "topics",
4042
+ topicIds: targeting.selection.topicIds
4043
+ }
4030
4044
  }) : err({ tag: "visitor_selection_not_allowed" });
4031
4045
  }
4032
4046
  if (selection === undefined) {
4033
4047
  return targeting.selection.offeredTopicIds.length === 1 ? ok({
4034
4048
  provider: "native",
4035
- topicIds: targeting.selection.offeredTopicIds
4049
+ audience: {
4050
+ kind: "topics",
4051
+ topicIds: targeting.selection.offeredTopicIds
4052
+ }
4036
4053
  }) : err({ tag: "visitor_selection_required" });
4037
4054
  }
4038
4055
  if (selection.provider !== "native") {
@@ -4041,7 +4058,10 @@ function resolveNativeTarget(targeting, selection) {
4041
4058
  const selected = selectedNonEmptySubset(selection.topicIds, targeting.selection.offeredTopicIds);
4042
4059
  return selected.ok ? ok({
4043
4060
  provider: "native",
4044
- topicIds: selected.value
4061
+ audience: {
4062
+ kind: "topics",
4063
+ topicIds: selected.value
4064
+ }
4045
4065
  }) : err({ tag: "visitor_selection_outside_offer" });
4046
4066
  }
4047
4067
  function resolveBrevoTarget(targeting, selection) {
@@ -4100,45 +4120,34 @@ function selectedNonEmptySubset(selected, offered) {
4100
4120
  return ok([first, ...rest]);
4101
4121
  }
4102
4122
  function planMailingListChoicePresentation(targeting) {
4103
- if (targeting.mode === "default" || targeting.selection.tag === "fixed") {
4123
+ if (targeting.mode === "default" || targeting.selection.tag === "fixed" || targeting.selection.tag === "general") {
4104
4124
  return { tag: "hidden" };
4105
4125
  }
4106
4126
  switch (targeting.provider) {
4107
- case "native": return targeting.selection.offeredTopicIds.length === 1 ? {
4108
- tag: "automatic",
4109
- selection: {
4110
- provider: "native",
4111
- topicIds: targeting.selection.offeredTopicIds
4112
- }
4113
- } : {
4114
- tag: "visitor_choice",
4127
+ case "native": return presentVisitorSelection({
4115
4128
  provider: "native",
4116
- optionCount: targeting.selection.offeredTopicIds.length
4117
- };
4118
- case "brevo": return targeting.selection.offeredListIds.length === 1 ? {
4119
- tag: "automatic",
4120
- selection: {
4121
- provider: "brevo",
4122
- listIds: targeting.selection.offeredListIds
4123
- }
4124
- } : {
4125
- tag: "visitor_choice",
4129
+ topicIds: targeting.selection.offeredTopicIds
4130
+ }, targeting.selection.offeredTopicIds.length);
4131
+ case "brevo": return presentVisitorSelection({
4126
4132
  provider: "brevo",
4127
- optionCount: targeting.selection.offeredListIds.length
4128
- };
4129
- case "mailchimp": return targeting.selection.offeredInterestIds.length === 1 ? {
4130
- tag: "automatic",
4131
- selection: {
4132
- provider: "mailchimp",
4133
- interestIds: targeting.selection.offeredInterestIds
4134
- }
4135
- } : {
4136
- tag: "visitor_choice",
4133
+ listIds: targeting.selection.offeredListIds
4134
+ }, targeting.selection.offeredListIds.length);
4135
+ case "mailchimp": return presentVisitorSelection({
4137
4136
  provider: "mailchimp",
4138
- optionCount: targeting.selection.offeredInterestIds.length
4139
- };
4137
+ interestIds: targeting.selection.offeredInterestIds
4138
+ }, targeting.selection.offeredInterestIds.length);
4140
4139
  }
4141
4140
  }
4141
+ function presentVisitorSelection(selection, optionCount) {
4142
+ return optionCount === 1 ? {
4143
+ tag: "automatic",
4144
+ selection
4145
+ } : {
4146
+ tag: "visitor_choice",
4147
+ provider: selection.provider,
4148
+ optionCount
4149
+ };
4150
+ }
4142
4151
 
4143
4152
  //#endregion
4144
4153
  //#region ../core/src/mailing-list-targeting-parser.ts
@@ -4159,6 +4168,7 @@ function parseMailingListVisitorSelection(value) {
4159
4168
  if (!isRecord$6(value)) return visitorSelectionError("shape");
4160
4169
  switch (value.provider) {
4161
4170
  case "native": {
4171
+ if (Object.keys(value).some((key) => key !== "provider" && key !== "topicIds")) return visitorSelectionError("shape");
4162
4172
  const topicIds = parseVisitorIds(value.topicIds, parseNewsletterListId);
4163
4173
  return topicIds === null ? visitorSelectionError("targets") : ok({
4164
4174
  provider: "native",
@@ -4183,6 +4193,13 @@ function parseMailingListVisitorSelection(value) {
4183
4193
  }
4184
4194
  }
4185
4195
  function parseNativeTargeting(selection) {
4196
+ if (selection.tag === "general") {
4197
+ return Object.keys(selection).length === 1 ? ok({
4198
+ mode: "custom",
4199
+ provider: "native",
4200
+ selection: { tag: "general" }
4201
+ }) : targetingError("selection");
4202
+ }
4186
4203
  if (selection.tag === "fixed") {
4187
4204
  const topicIds = parseNonEmptyUniqueIds(selection.topicIds, parseNewsletterListId);
4188
4205
  return topicIds.ok ? ok({
@@ -4966,6 +4983,9 @@ function mailingListProviderName(provider) {
4966
4983
  case "brevo": return "Brevo";
4967
4984
  }
4968
4985
  }
4986
+ function sameNewsletterAudience(left, right) {
4987
+ return left.kind === right.kind && (left.kind === "general" || right.kind === "topic" && left.topicId === right.topicId);
4988
+ }
4969
4989
  const DEFAULT_MAILING_LIST_SUCCESS_MESSAGE = "Thanks — you're on the list.";
4970
4990
  /**
4971
4991
  * Seeded into a new setup so every signup form carries a preferences/unsubscribe
@@ -5097,6 +5117,15 @@ function countDefaultMailingListPlacements(placementModes) {
5097
5117
 
5098
5118
  //#endregion
5099
5119
  //#region ../core/src/mailing-list-setup-parser.ts
5120
+ const newsletterAudienceSchema = z.unknown().transform((value, ctx) => {
5121
+ const parsed = parseNewsletterAudience(value);
5122
+ if (parsed.ok) return parsed.value;
5123
+ ctx.addIssue({
5124
+ code: "custom",
5125
+ message: "Choose a valid newsletter audience."
5126
+ });
5127
+ return z.NEVER;
5128
+ });
5100
5129
  function parseMailingListGlobalForm(value) {
5101
5130
  if (!isRecord$2(value)) return formError("shape");
5102
5131
  const fields = parseGlobalFields(value.fields);
@@ -5153,51 +5182,69 @@ function parseConfiguredMailingListProvider(value) {
5153
5182
  return setupError("provider");
5154
5183
  }
5155
5184
  switch (value.provider) {
5156
- case "native": {
5157
- const defaultTopicId = parseNewsletterListId(value.defaultTopicId);
5158
- if (defaultTopicId === null) return setupError("defaultTargetId");
5159
- const confirmation = parseToggleConfirmation(value.confirmation);
5160
- return confirmation === null ? setupError("confirmation") : ok({
5161
- provider: "native",
5162
- defaultTopicId,
5163
- confirmation
5164
- });
5165
- }
5166
- case "mailchimp": {
5167
- const connectionId = parseMailchimpConnectionId(value.connectionId);
5168
- if (connectionId === null) return setupError("connectionId");
5169
- const accountId = parseMailchimpAccountId(value.accountId);
5170
- if (accountId === null) return setupError("accountId");
5171
- const defaultAudienceId = parseMailchimpAudienceId(value.defaultAudienceId);
5172
- if (defaultAudienceId === null) return setupError("defaultTargetId");
5173
- const confirmation = parseToggleConfirmation(value.confirmation);
5174
- return confirmation === null ? setupError("confirmation") : ok({
5175
- provider: "mailchimp",
5176
- connectionId,
5177
- accountId,
5178
- defaultAudienceId,
5179
- confirmation
5180
- });
5181
- }
5182
- case "brevo": {
5183
- const connectionId = parseBrevoConnectionId(value.connectionId);
5184
- if (connectionId === null) return setupError("connectionId");
5185
- const accountId = parseBrevoAccountId(value.accountId);
5186
- if (accountId === null) return setupError("accountId");
5187
- const defaultListId = parseBrevoListId(value.defaultListId);
5188
- if (defaultListId === null) return setupError("defaultTargetId");
5189
- const confirmation = parseBrevoConfirmation(value.confirmation);
5190
- return confirmation === null ? setupError("confirmation") : ok({
5191
- provider: "brevo",
5192
- connectionId,
5193
- accountId,
5194
- defaultListId,
5195
- confirmation
5196
- });
5197
- }
5185
+ case "native": return parseNativeSetup(value);
5186
+ case "mailchimp": return parseMailchimpSetup(value);
5187
+ case "brevo": return parseBrevoSetup(value);
5198
5188
  default: return setupError("provider");
5199
5189
  }
5200
5190
  }
5191
+ function parseNativeSetup(value) {
5192
+ if ("defaultTopicId" in value) return setupError("defaultTargetId");
5193
+ const defaultAudience = parseNewsletterAudience(value.defaultAudience);
5194
+ if (!defaultAudience.ok) return setupError("defaultTargetId");
5195
+ const confirmation = parseToggleConfirmation(value.confirmation);
5196
+ return confirmation === null ? setupError("confirmation") : ok({
5197
+ provider: "native",
5198
+ defaultAudience: defaultAudience.value,
5199
+ confirmation
5200
+ });
5201
+ }
5202
+ function parseMailchimpSetup(value) {
5203
+ const connectionId = parseMailchimpConnectionId(value.connectionId);
5204
+ if (connectionId === null) return setupError("connectionId");
5205
+ const accountId = parseMailchimpAccountId(value.accountId);
5206
+ if (accountId === null) return setupError("accountId");
5207
+ const defaultAudienceId = parseMailchimpAudienceId(value.defaultAudienceId);
5208
+ if (defaultAudienceId === null) return setupError("defaultTargetId");
5209
+ const confirmation = parseToggleConfirmation(value.confirmation);
5210
+ return confirmation === null ? setupError("confirmation") : ok({
5211
+ provider: "mailchimp",
5212
+ connectionId,
5213
+ accountId,
5214
+ defaultAudienceId,
5215
+ confirmation
5216
+ });
5217
+ }
5218
+ function parseBrevoSetup(value) {
5219
+ const connectionId = parseBrevoConnectionId(value.connectionId);
5220
+ if (connectionId === null) return setupError("connectionId");
5221
+ const accountId = parseBrevoAccountId(value.accountId);
5222
+ if (accountId === null) return setupError("accountId");
5223
+ const defaultListId = parseBrevoListId(value.defaultListId);
5224
+ if (defaultListId === null) return setupError("defaultTargetId");
5225
+ const confirmation = parseBrevoConfirmation(value.confirmation);
5226
+ return confirmation === null ? setupError("confirmation") : ok({
5227
+ provider: "brevo",
5228
+ connectionId,
5229
+ accountId,
5230
+ defaultListId,
5231
+ confirmation
5232
+ });
5233
+ }
5234
+ function parseNewsletterAudience(value) {
5235
+ if (!isRecord$2(value)) return err("invalid_newsletter_audience");
5236
+ if (value.kind === "general" && Object.keys(value).length === 1) {
5237
+ return ok({ kind: "general" });
5238
+ }
5239
+ if (value.kind !== "topic" || Object.keys(value).some((key) => key !== "kind" && key !== "topicId")) {
5240
+ return err("invalid_newsletter_audience");
5241
+ }
5242
+ const topicId = parseNewsletterListId(value.topicId);
5243
+ return topicId === null ? err("invalid_newsletter_audience") : ok({
5244
+ kind: "topic",
5245
+ topicId
5246
+ });
5247
+ }
5201
5248
  function parseGlobalFields(value) {
5202
5249
  if (!isRecord$2(value) || typeof value.preset !== "string") return null;
5203
5250
  switch (value.preset) {
@@ -5281,7 +5328,13 @@ function setupError(field) {
5281
5328
  //#region ../core/src/mailing-list-targeting-availability.ts
5282
5329
  function resolveMailingListDefaultDestination(provider) {
5283
5330
  switch (provider.provider) {
5284
- case "native": return provider.topics.find((item) => item.id === provider.defaultTopicId) ?? null;
5331
+ case "native": {
5332
+ const audience = provider.defaultAudience;
5333
+ return audience.kind === "general" ? {
5334
+ id: "general",
5335
+ name: "General mailing list"
5336
+ } : provider.topics.find((item) => item.id === audience.topicId) ?? null;
5337
+ }
5285
5338
  case "brevo": return provider.lists.find((item) => item.id === provider.defaultListId) ?? null;
5286
5339
  case "mailchimp": return provider.audiences.find((item) => item.id === provider.defaultAudienceId) ?? null;
5287
5340
  }
@@ -5446,11 +5499,12 @@ function parseRuntimeProvider(value) {
5446
5499
  }
5447
5500
  }
5448
5501
  function parseNativeRuntimeProvider(value) {
5449
- const defaultTopicId = parseNewsletterListId(value.defaultTopicId);
5502
+ if ("defaultTopicId" in value) return null;
5503
+ const defaultAudience = parseNewsletterAudience(value.defaultAudience);
5450
5504
  const topics = parseNamedItems(value.topics, parseNewsletterListId);
5451
- return defaultTopicId !== null && topics !== null ? {
5505
+ return defaultAudience.ok && topics !== null ? {
5452
5506
  provider: "native",
5453
- defaultTopicId,
5507
+ defaultAudience: defaultAudience.value,
5454
5508
  topics
5455
5509
  } : null;
5456
5510
  }
package/dist/testing.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import "./sdk-event-upsert-JKXlp2Ct.mjs";
3
- import "./src-JsJh7WAb.mjs";
4
- import { n as syncLocalMediaForPush, r as syncLocalMediaForPull, y as writeMediaManifest } from "./local-sync-C0m2pobl.mjs";
2
+ import "./sdk-event-upsert-BamyD2d6.mjs";
3
+ import "./src-BhrSG8A4.mjs";
4
+ import { n as syncLocalMediaForPush, r as syncLocalMediaForPull, y as writeMediaManifest } from "./local-sync-B3naCvSc.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.17.1",
3
+ "version": "0.18.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-DR5qJgmx.mjs";
3
-
4
- export { loadConfigFile };