@bash-app/bash-common 30.316.0 → 30.318.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.
Files changed (49) hide show
  1. package/dist/__tests__/appleIapProducts.test.d.ts +2 -0
  2. package/dist/__tests__/appleIapProducts.test.d.ts.map +1 -0
  3. package/dist/__tests__/appleIapProducts.test.js +32 -0
  4. package/dist/__tests__/appleIapProducts.test.js.map +1 -0
  5. package/dist/__tests__/hostCrmGrowthPack.test.d.ts +2 -0
  6. package/dist/__tests__/hostCrmGrowthPack.test.d.ts.map +1 -0
  7. package/dist/__tests__/hostCrmGrowthPack.test.js +25 -0
  8. package/dist/__tests__/hostCrmGrowthPack.test.js.map +1 -0
  9. package/dist/__tests__/hostCrmSegments.test.js +10 -0
  10. package/dist/__tests__/hostCrmSegments.test.js.map +1 -1
  11. package/dist/appleIapProducts.d.ts +64 -0
  12. package/dist/appleIapProducts.d.ts.map +1 -0
  13. package/dist/appleIapProducts.js +113 -0
  14. package/dist/appleIapProducts.js.map +1 -0
  15. package/dist/definitions.d.ts +3 -1
  16. package/dist/definitions.d.ts.map +1 -1
  17. package/dist/definitions.js +2 -0
  18. package/dist/definitions.js.map +1 -1
  19. package/dist/extendedSchemas.d.ts +27 -0
  20. package/dist/extendedSchemas.d.ts.map +1 -1
  21. package/dist/extendedSchemas.js.map +1 -1
  22. package/dist/hostCrmAutomation.d.ts +25 -0
  23. package/dist/hostCrmAutomation.d.ts.map +1 -1
  24. package/dist/hostCrmAutomation.js +29 -0
  25. package/dist/hostCrmAutomation.js.map +1 -1
  26. package/dist/hostCrmSegments.d.ts +2 -0
  27. package/dist/hostCrmSegments.d.ts.map +1 -1
  28. package/dist/hostCrmSegments.js +9 -0
  29. package/dist/hostCrmSegments.js.map +1 -1
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/sms/smsTemplates.d.ts +13 -1
  35. package/dist/sms/smsTemplates.d.ts.map +1 -1
  36. package/dist/sms/smsTemplates.js +3 -0
  37. package/dist/sms/smsTemplates.js.map +1 -1
  38. package/package.json +1 -1
  39. package/prisma/schema.prisma +28 -1
  40. package/src/__tests__/appleIapProducts.test.ts +52 -0
  41. package/src/__tests__/hostCrmGrowthPack.test.ts +33 -0
  42. package/src/__tests__/hostCrmSegments.test.ts +13 -0
  43. package/src/appleIapProducts.ts +203 -0
  44. package/src/definitions.ts +2 -0
  45. package/src/extendedSchemas.ts +30 -1
  46. package/src/hostCrmAutomation.ts +59 -0
  47. package/src/hostCrmSegments.ts +12 -0
  48. package/src/index.ts +1 -0
  49. package/src/sms/smsTemplates.ts +6 -0
@@ -77,3 +77,62 @@ export type HostCrmAutomationInput = {
77
77
  cadenceDays?: number | null;
78
78
  enabled?: boolean;
79
79
  };
80
+
81
+ /**
82
+ * "Growth pack" — the one-click Host CRM automation pair (win-back + post-event
83
+ * thank-you). Specs live here so API enable, legacy backfill, and UI detection
84
+ * cannot drift apart.
85
+ */
86
+ export const HOST_CRM_GROWTH_PACK_WINBACK_PRESET_ID = "lapsed_180";
87
+ export const HOST_CRM_GROWTH_PACK_WINBACK_NAME = "Win-back email";
88
+ export const HOST_CRM_GROWTH_PACK_POST_EVENT_NAME = "Post-event thank-you";
89
+
90
+ /** Shared with the live win-back blast defaults — keep in lockstep. */
91
+ export const HOST_CRM_WINBACK_DEFAULT_SUBJECT =
92
+ "We miss you — come back out with us";
93
+ export const HOST_CRM_WINBACK_DEFAULT_BODY =
94
+ "It's been a while since your last bash with us. We'd love to see you again.";
95
+
96
+ /** Post-event cron substitutes {{eventTitle}}, {{firstName}}, {{bashFeedUrl}}. */
97
+ export const HOST_CRM_GROWTH_PACK_POST_EVENT_SUBJECT =
98
+ "Thank you for coming to {{eventTitle}}";
99
+ export const HOST_CRM_GROWTH_PACK_POST_EVENT_BODY =
100
+ "Hi {{firstName}},\n\nThanks so much for being part of {{eventTitle}} — it wouldn't have been the same without you. Hope to see you at the next one!\n\n{{bashFeedUrl}}";
101
+
102
+ type GrowthPackAutomationShape = {
103
+ trigger: string;
104
+ channel: string;
105
+ audiencePresetId?: string | null;
106
+ };
107
+
108
+ /** True when a Recurring Email + lapsed_180 win-back automation already exists. */
109
+ export function hostCrmHasWinBackPackAutomation(
110
+ automations: GrowthPackAutomationShape[]
111
+ ): boolean {
112
+ return automations.some(
113
+ (a) =>
114
+ a.trigger === HostCrmAutomationTrigger.Recurring &&
115
+ a.channel === HostCrmAutomationChannel.Email &&
116
+ a.audiencePresetId === HOST_CRM_GROWTH_PACK_WINBACK_PRESET_ID
117
+ );
118
+ }
119
+
120
+ /** True when a PostEvent Email thank-you automation already exists. */
121
+ export function hostCrmHasPostEventPackAutomation(
122
+ automations: GrowthPackAutomationShape[]
123
+ ): boolean {
124
+ return automations.some(
125
+ (a) =>
126
+ a.trigger === HostCrmAutomationTrigger.PostEvent &&
127
+ a.channel === HostCrmAutomationChannel.Email
128
+ );
129
+ }
130
+
131
+ export function hostCrmGrowthPackIsComplete(
132
+ automations: GrowthPackAutomationShape[]
133
+ ): boolean {
134
+ return (
135
+ hostCrmHasWinBackPackAutomation(automations) &&
136
+ hostCrmHasPostEventPackAutomation(automations)
137
+ );
138
+ }
@@ -10,6 +10,8 @@ export type HostCrmSegmentRules = {
10
10
  tag?: string;
11
11
  cadence?: SocialEventCadence;
12
12
  minEventCount?: number;
13
+ /** First-timers-style segment: attended at most this many of the host's bashes. */
14
+ maxEventCount?: number;
13
15
  lapsedDays?: number;
14
16
  /** Ticket buyers for this bash event id */
15
17
  sourceEventId?: string;
@@ -107,6 +109,10 @@ export function applyHostCrmSegmentRules<T extends HostCrmAudienceMember>(
107
109
  rows = rows.filter((r) => r.eventCount >= rules.minEventCount!);
108
110
  }
109
111
 
112
+ if (typeof rules.maxEventCount === "number" && rules.maxEventCount > 0) {
113
+ rows = rows.filter((r) => r.eventCount <= rules.maxEventCount!);
114
+ }
115
+
110
116
  if (typeof rules.lapsedDays === "number" && rules.lapsedDays > 0) {
111
117
  const cutoff = now.getTime() - rules.lapsedDays * 24 * 60 * 60 * 1000;
112
118
  rows = rows.filter((r) => {
@@ -200,6 +206,12 @@ export const HOST_CRM_PRESET_SEGMENTS: Array<{
200
206
  description: "People who have been to at least three of your bashes",
201
207
  rules: { minEventCount: 3 },
202
208
  },
209
+ {
210
+ id: "first_timers",
211
+ label: "First-timers",
212
+ description: "Came to exactly one of your bashes and haven't been back",
213
+ rules: { maxEventCount: 1 },
214
+ },
203
215
  {
204
216
  id: "lapsed_90",
205
217
  label: "Haven't been in 90 days",
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ export * from "./storeTypes.js";
19
19
  export * from "./storePrintArtworkUtils.js";
20
20
  export * from "./bashFeedTypes.js";
21
21
  export * from "./membershipDefinitions.js";
22
+ export * from "./appleIapProducts.js";
22
23
  export * from "./onSaleCapabilityRecommendations.js";
23
24
  export * from "./ticketBnplPaymentMethods.js";
24
25
  export * from "./aiApproval.js";
@@ -3,6 +3,9 @@
3
3
  * Consumers use these keys for type-safe `sendTemplatedSms` calls.
4
4
  */
5
5
  export const SMS_TEMPLATE_KEYS = [
6
+ "EVENT_REMINDER_1WEEK",
7
+ "EVENT_REMINDER_24H",
8
+ "EVENT_REMINDER_3H",
6
9
  "EVENT_REMINDER_1H",
7
10
  "EVENT_VENUE_CHANGED",
8
11
  "EVENT_WAITLIST_APPROVED",
@@ -13,6 +16,9 @@ export type SmsTemplateKey = (typeof SMS_TEMPLATE_KEYS)[number];
13
16
 
14
17
  /** Typed context per template (API maps these to final message strings). */
15
18
  export type SmsTemplateContext = {
19
+ EVENT_REMINDER_1WEEK: { eventTitle: string; shortUrl: string };
20
+ EVENT_REMINDER_24H: { eventTitle: string; shortUrl: string };
21
+ EVENT_REMINDER_3H: { eventTitle: string; shortUrl: string };
16
22
  EVENT_REMINDER_1H: { eventTitle: string; shortUrl: string };
17
23
  EVENT_VENUE_CHANGED: { eventTitle: string; shortUrl: string };
18
24
  EVENT_WAITLIST_APPROVED: { eventTitle: string; shortUrl: string };