@bash-app/bash-common 30.58.0 → 30.59.1
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.
- package/dist/extendedSchemas.d.ts +58 -0
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +1 -0
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/membershipDefinitions.d.ts +60 -0
- package/dist/membershipDefinitions.d.ts.map +1 -0
- package/dist/membershipDefinitions.js +189 -0
- package/dist/membershipDefinitions.js.map +1 -0
- package/package.json +1 -1
- package/prisma/migrations/20250721130031_add_membership_fields/migration.sql +2825 -0
- package/prisma/migrations/20250721131052_fix_volunteer_service_user_cascade/migration.sql +1 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +5 -0
- package/src/extendedSchemas.ts +70 -0
- package/src/index.ts +1 -0
- package/src/membershipDefinitions.ts +206 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
-- This is an empty migration.
|
package/prisma/schema.prisma
CHANGED
|
@@ -372,6 +372,11 @@ model BashEvent {
|
|
|
372
372
|
venue Venue? @relation(fields: [venueId], references: [id])
|
|
373
373
|
userPromoCodeRedemption UserPromoCodeRedemption[]
|
|
374
374
|
averageRating Float? @default(0)
|
|
375
|
+
allowDonations Boolean? @default(true)
|
|
376
|
+
suggestedDonationAmount Int? // stored in cents like other prices
|
|
377
|
+
donationDetails String?
|
|
378
|
+
absorbDonationFees Boolean @default(false)
|
|
379
|
+
absorbTicketFees Boolean @default(false)
|
|
375
380
|
serviceBookings ServiceBooking[] // Add this field to create the reverse relation
|
|
376
381
|
userReport UserReport[]
|
|
377
382
|
favoritedBy UserFavorite[]
|
package/src/extendedSchemas.ts
CHANGED
|
@@ -997,3 +997,73 @@ export interface BlogTagFormData {
|
|
|
997
997
|
slug?: string;
|
|
998
998
|
color?: string;
|
|
999
999
|
}
|
|
1000
|
+
//------------------------------------------------------membership system------------------------------------------------------
|
|
1001
|
+
export type MembershipTier = 'Guest' | 'Creator' | 'Pro' | 'Elite' | 'Legend';
|
|
1002
|
+
export type MembershipBillingInterval = 'Monthly' | 'Yearly';
|
|
1003
|
+
|
|
1004
|
+
export interface MembershipTierInfo {
|
|
1005
|
+
tier: MembershipTier;
|
|
1006
|
+
name: string;
|
|
1007
|
+
monthlyPrice: number;
|
|
1008
|
+
yearlyPrice: number;
|
|
1009
|
+
features: string[];
|
|
1010
|
+
limits: {
|
|
1011
|
+
bashEventsPerMonth?: number;
|
|
1012
|
+
featuredEventsPerMonth?: number;
|
|
1013
|
+
analyticsAccess: boolean;
|
|
1014
|
+
vendorDirectoryAccess: boolean;
|
|
1015
|
+
prioritySupport: boolean;
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
export interface UserMembershipStatus {
|
|
1020
|
+
currentTier: MembershipTier;
|
|
1021
|
+
expiresAt?: string;
|
|
1022
|
+
autoRenew: boolean;
|
|
1023
|
+
billingInterval?: MembershipBillingInterval;
|
|
1024
|
+
featuredEventsUsed: number;
|
|
1025
|
+
stripeSubscriptionId?: string;
|
|
1026
|
+
canUpgrade: boolean;
|
|
1027
|
+
canDowngrade: boolean;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
export interface MembershipUpgradeRequest {
|
|
1031
|
+
targetTier: Exclude<MembershipTier, 'Guest'>;
|
|
1032
|
+
billingInterval: MembershipBillingInterval;
|
|
1033
|
+
paymentMethodId?: string;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
export interface MembershipUpgradeResult {
|
|
1037
|
+
success: boolean;
|
|
1038
|
+
requiresPayment: boolean;
|
|
1039
|
+
clientSecret?: string;
|
|
1040
|
+
redirectUrl?: string;
|
|
1041
|
+
newTier?: MembershipTier;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
export interface MembershipPaymentIntentRequest {
|
|
1045
|
+
targetTier: Exclude<MembershipTier, 'Guest'>;
|
|
1046
|
+
billingInterval: MembershipBillingInterval;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
export interface MembershipPaymentIntentResult {
|
|
1050
|
+
clientSecret: string;
|
|
1051
|
+
amount: number;
|
|
1052
|
+
currency: string;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
export interface MembershipFeatureAccessCheck {
|
|
1056
|
+
hasAccess: boolean;
|
|
1057
|
+
requiredTier?: MembershipTier;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
export interface CreateMembershipPaymentIntentArgs {
|
|
1061
|
+
targetTier: Exclude<MembershipTier, 'Guest'>;
|
|
1062
|
+
billingInterval: MembershipBillingInterval;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
export interface ConfirmMembershipPaymentArgs {
|
|
1066
|
+
paymentIntentId: string;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
//-------------------------------------------------------------------------------------------------------------------------------
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// Membership tier definitions and constants shared between frontend and backend
|
|
2
|
+
import { MembershipBillingInterval, MembershipTier, MembershipTierInfo } from './extendedSchemas';
|
|
3
|
+
|
|
4
|
+
export { MembershipBillingInterval, MembershipTier };
|
|
5
|
+
|
|
6
|
+
// Pricing in cents (for Stripe)
|
|
7
|
+
export const MEMBERSHIP_PRICING = {
|
|
8
|
+
Guest: { monthly: 0, yearly: 0 },
|
|
9
|
+
Creator: { monthly: 2499, yearly: 20000 }, // $24.99/month, $200/year
|
|
10
|
+
Pro: { monthly: 9900, yearly: 99900 }, // $99/month, $999/year
|
|
11
|
+
Elite: { monthly: 49900, yearly: 500000 }, // $499/month, $5,000/year
|
|
12
|
+
Legend: { monthly: 99900, yearly: 1000000 }, // $999/month, $10,000/year
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const MEMBERSHIP_TIER_HIERARCHY: MembershipTier[] = [
|
|
16
|
+
'Guest', 'Creator', 'Pro', 'Elite', 'Legend'
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export const MEMBERSHIP_FEATURES = {
|
|
20
|
+
// Core Creator features
|
|
21
|
+
NO_MINIMUM_TICKET_PRICE: 'no_minimum_ticket_price',
|
|
22
|
+
CREATOR_ONLY_EVENTS: 'creator_only_events',
|
|
23
|
+
FEATURED_EVENTS_PAID: 'featured_events_paid',
|
|
24
|
+
BETA_FEATURES: 'beta_features',
|
|
25
|
+
BASIC_NOTIFICATIONS: 'basic_notifications',
|
|
26
|
+
|
|
27
|
+
// Pro features
|
|
28
|
+
FREE_FEATURED_EVENTS: 'free_featured_events',
|
|
29
|
+
SEARCH_PRIORITY: 'search_priority',
|
|
30
|
+
BASIC_ANALYTICS: 'basic_analytics',
|
|
31
|
+
VENDOR_DIRECTORY: 'vendor_directory',
|
|
32
|
+
TIER_BADGE: 'tier_badge',
|
|
33
|
+
|
|
34
|
+
// Elite features
|
|
35
|
+
ELITE_EVENTS: 'elite_events',
|
|
36
|
+
BASH_SPONSORED_INVITES: 'bash_sponsored_invites',
|
|
37
|
+
ADVANCED_ANALYTICS: 'advanced_analytics',
|
|
38
|
+
CONCIERGE_SUPPORT: 'concierge_support',
|
|
39
|
+
MONETIZATION_TOOLS: 'monetization_tools',
|
|
40
|
+
HOMEPAGE_VISIBILITY: 'homepage_visibility',
|
|
41
|
+
|
|
42
|
+
// Legend features
|
|
43
|
+
LEGEND_EVENTS: 'legend_events',
|
|
44
|
+
EXCLUSIVE_MERCH: 'exclusive_merch',
|
|
45
|
+
NETWORKING_MIXERS: 'networking_mixers',
|
|
46
|
+
INVESTMENT_DEALS: 'investment_deals',
|
|
47
|
+
MAGAZINE_FEATURES: 'magazine_features',
|
|
48
|
+
HOMEPAGE_ROTATION: 'homepage_rotation',
|
|
49
|
+
VIP_SUPPORT: 'vip_support',
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Check if a tier has access to a specific feature
|
|
54
|
+
*/
|
|
55
|
+
export function hasFeatureAccess(userTier: MembershipTier, feature: string): boolean {
|
|
56
|
+
const tierIndex = MEMBERSHIP_TIER_HIERARCHY.indexOf(userTier);
|
|
57
|
+
|
|
58
|
+
switch (feature) {
|
|
59
|
+
case MEMBERSHIP_FEATURES.NO_MINIMUM_TICKET_PRICE:
|
|
60
|
+
case MEMBERSHIP_FEATURES.CREATOR_ONLY_EVENTS:
|
|
61
|
+
case MEMBERSHIP_FEATURES.FEATURED_EVENTS_PAID:
|
|
62
|
+
case MEMBERSHIP_FEATURES.BETA_FEATURES:
|
|
63
|
+
case MEMBERSHIP_FEATURES.BASIC_NOTIFICATIONS:
|
|
64
|
+
return tierIndex >= 1; // Creator+
|
|
65
|
+
|
|
66
|
+
case MEMBERSHIP_FEATURES.FREE_FEATURED_EVENTS:
|
|
67
|
+
case MEMBERSHIP_FEATURES.SEARCH_PRIORITY:
|
|
68
|
+
case MEMBERSHIP_FEATURES.BASIC_ANALYTICS:
|
|
69
|
+
case MEMBERSHIP_FEATURES.VENDOR_DIRECTORY:
|
|
70
|
+
case MEMBERSHIP_FEATURES.TIER_BADGE:
|
|
71
|
+
return tierIndex >= 2; // Pro+
|
|
72
|
+
|
|
73
|
+
case MEMBERSHIP_FEATURES.ELITE_EVENTS:
|
|
74
|
+
case MEMBERSHIP_FEATURES.BASH_SPONSORED_INVITES:
|
|
75
|
+
case MEMBERSHIP_FEATURES.ADVANCED_ANALYTICS:
|
|
76
|
+
case MEMBERSHIP_FEATURES.CONCIERGE_SUPPORT:
|
|
77
|
+
case MEMBERSHIP_FEATURES.MONETIZATION_TOOLS:
|
|
78
|
+
case MEMBERSHIP_FEATURES.HOMEPAGE_VISIBILITY:
|
|
79
|
+
return tierIndex >= 3; // Elite+
|
|
80
|
+
|
|
81
|
+
case MEMBERSHIP_FEATURES.LEGEND_EVENTS:
|
|
82
|
+
case MEMBERSHIP_FEATURES.EXCLUSIVE_MERCH:
|
|
83
|
+
case MEMBERSHIP_FEATURES.NETWORKING_MIXERS:
|
|
84
|
+
case MEMBERSHIP_FEATURES.INVESTMENT_DEALS:
|
|
85
|
+
case MEMBERSHIP_FEATURES.MAGAZINE_FEATURES:
|
|
86
|
+
case MEMBERSHIP_FEATURES.HOMEPAGE_ROTATION:
|
|
87
|
+
case MEMBERSHIP_FEATURES.VIP_SUPPORT:
|
|
88
|
+
return tierIndex >= 4; // Legend only
|
|
89
|
+
|
|
90
|
+
default:
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get the minimum tier required for a feature
|
|
97
|
+
*/
|
|
98
|
+
export function getRequiredTierForFeature(feature: string): MembershipTier | null {
|
|
99
|
+
for (const tier of MEMBERSHIP_TIER_HIERARCHY) {
|
|
100
|
+
if (hasFeatureAccess(tier, feature)) {
|
|
101
|
+
return tier;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Complete tier definitions with features and pricing
|
|
108
|
+
export const MEMBERSHIP_TIER_INFO: Record<MembershipTier, MembershipTierInfo> = {
|
|
109
|
+
Guest: {
|
|
110
|
+
tier: 'Guest',
|
|
111
|
+
name: 'Guest',
|
|
112
|
+
monthlyPrice: MEMBERSHIP_PRICING.Guest.monthly,
|
|
113
|
+
yearlyPrice: MEMBERSHIP_PRICING.Guest.yearly,
|
|
114
|
+
features: [
|
|
115
|
+
'Browse and attend public events',
|
|
116
|
+
'Host your own events with a $5 minimum ticket required',
|
|
117
|
+
'Limited visibility and no access to exclusive features'
|
|
118
|
+
],
|
|
119
|
+
limits: {
|
|
120
|
+
featuredEventsPerMonth: 0,
|
|
121
|
+
analyticsAccess: false,
|
|
122
|
+
vendorDirectoryAccess: false,
|
|
123
|
+
prioritySupport: false,
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
Creator: {
|
|
127
|
+
tier: 'Creator',
|
|
128
|
+
name: 'Creator',
|
|
129
|
+
monthlyPrice: MEMBERSHIP_PRICING.Creator.monthly,
|
|
130
|
+
yearlyPrice: MEMBERSHIP_PRICING.Creator.yearly,
|
|
131
|
+
features: [
|
|
132
|
+
'Host without the $5 cover minimum — set your own price',
|
|
133
|
+
'Access to Creator-Only and Premium-only events',
|
|
134
|
+
'Eligible to pay to feature your events on the homepage',
|
|
135
|
+
'Early access to beta tools and features',
|
|
136
|
+
'Basic event engagement notifications'
|
|
137
|
+
],
|
|
138
|
+
limits: {
|
|
139
|
+
featuredEventsPerMonth: 0,
|
|
140
|
+
analyticsAccess: false,
|
|
141
|
+
vendorDirectoryAccess: false,
|
|
142
|
+
prioritySupport: false,
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
Pro: {
|
|
146
|
+
tier: 'Pro',
|
|
147
|
+
name: 'Pro',
|
|
148
|
+
monthlyPrice: MEMBERSHIP_PRICING.Pro.monthly,
|
|
149
|
+
yearlyPrice: MEMBERSHIP_PRICING.Pro.yearly,
|
|
150
|
+
features: [
|
|
151
|
+
'All Creator features',
|
|
152
|
+
'1 free featured event/month',
|
|
153
|
+
'Priority placement in search and event discovery',
|
|
154
|
+
'Access to basic analytics (views, clicks, RSVPs)',
|
|
155
|
+
'Ability to list your services in vendor directory',
|
|
156
|
+
'Tier badge displayed on your profile and events'
|
|
157
|
+
],
|
|
158
|
+
limits: {
|
|
159
|
+
featuredEventsPerMonth: 1,
|
|
160
|
+
analyticsAccess: true,
|
|
161
|
+
vendorDirectoryAccess: true,
|
|
162
|
+
prioritySupport: false,
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
Elite: {
|
|
166
|
+
tier: 'Elite',
|
|
167
|
+
name: 'Elite',
|
|
168
|
+
monthlyPrice: MEMBERSHIP_PRICING.Elite.monthly,
|
|
169
|
+
yearlyPrice: MEMBERSHIP_PRICING.Elite.yearly,
|
|
170
|
+
features: [
|
|
171
|
+
'All Pro features',
|
|
172
|
+
'Access to Elite-Only events and creator lounges',
|
|
173
|
+
'Free invites to select Bash-sponsored bashes',
|
|
174
|
+
'Advanced analytics with conversion trends and heatmaps',
|
|
175
|
+
'Concierge support via live chat and email',
|
|
176
|
+
'First access to new monetization tools',
|
|
177
|
+
'Gold tier badge + increased homepage visibility'
|
|
178
|
+
],
|
|
179
|
+
limits: {
|
|
180
|
+
analyticsAccess: true,
|
|
181
|
+
vendorDirectoryAccess: true,
|
|
182
|
+
prioritySupport: true,
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
Legend: {
|
|
186
|
+
tier: 'Legend',
|
|
187
|
+
name: 'Legend',
|
|
188
|
+
monthlyPrice: MEMBERSHIP_PRICING.Legend.monthly,
|
|
189
|
+
yearlyPrice: MEMBERSHIP_PRICING.Legend.yearly,
|
|
190
|
+
features: [
|
|
191
|
+
'All Elite features',
|
|
192
|
+
'Access to Legend-Only parties and high-profile bashes',
|
|
193
|
+
'Exclusive gift boxes and seasonal merch drops',
|
|
194
|
+
'Invite-only Legend networking mixers',
|
|
195
|
+
'First-look deals on investment opportunities',
|
|
196
|
+
'Annual profile feature in Bash magazine',
|
|
197
|
+
'Red crown badge and automatic homepage rotation',
|
|
198
|
+
'VIP concierge & brand manager access'
|
|
199
|
+
],
|
|
200
|
+
limits: {
|
|
201
|
+
analyticsAccess: true,
|
|
202
|
+
vendorDirectoryAccess: true,
|
|
203
|
+
prioritySupport: true,
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|