@bash-app/bash-common 30.59.4 → 30.59.6
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/definitions.d.ts +15 -12
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +16 -12
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +36 -58
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +1 -1
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/membershipDefinitions.d.ts +50 -2
- package/dist/membershipDefinitions.d.ts.map +1 -1
- package/dist/membershipDefinitions.js +3 -0
- package/dist/membershipDefinitions.js.map +1 -1
- package/dist/utils/urlUtils.d.ts +34 -0
- package/dist/utils/urlUtils.d.ts.map +1 -1
- package/dist/utils/urlUtils.js +94 -1
- package/dist/utils/urlUtils.js.map +1 -1
- package/package.json +1 -1
- package/prisma/schema.prisma +10 -1
- package/src/definitions.ts +27 -22
- package/src/extendedSchemas.ts +2 -70
- package/src/membershipDefinitions.ts +56 -2
- package/src/utils/urlUtils.ts +114 -1
|
@@ -1,7 +1,61 @@
|
|
|
1
1
|
// Membership tier definitions and constants shared between frontend and backend
|
|
2
|
-
import {
|
|
2
|
+
import { MembershipTier } from '@prisma/client';
|
|
3
3
|
|
|
4
|
-
export {
|
|
4
|
+
export { MembershipTier };
|
|
5
|
+
|
|
6
|
+
export type MembershipBillingInterval = 'Monthly' | 'Yearly';
|
|
7
|
+
|
|
8
|
+
export interface MembershipTierInfo {
|
|
9
|
+
tier: MembershipTier;
|
|
10
|
+
name: string;
|
|
11
|
+
monthlyPrice: number;
|
|
12
|
+
yearlyPrice: number;
|
|
13
|
+
features: string[];
|
|
14
|
+
limits: {
|
|
15
|
+
bashEventsPerMonth?: number;
|
|
16
|
+
featuredEventsPerMonth?: number;
|
|
17
|
+
analyticsAccess: boolean;
|
|
18
|
+
vendorDirectoryAccess: boolean;
|
|
19
|
+
prioritySupport: boolean;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// API-related interfaces
|
|
24
|
+
export interface UserMembershipStatus {
|
|
25
|
+
currentTier: MembershipTier;
|
|
26
|
+
expiresAt?: string;
|
|
27
|
+
autoRenew: boolean;
|
|
28
|
+
billingInterval?: MembershipBillingInterval;
|
|
29
|
+
featuredEventsUsed: number;
|
|
30
|
+
stripeSubscriptionId?: string;
|
|
31
|
+
canUpgrade: boolean;
|
|
32
|
+
canDowngrade: boolean;
|
|
33
|
+
features: string[];
|
|
34
|
+
subscriptionStatus: string;
|
|
35
|
+
nextBilling?: Date | null;
|
|
36
|
+
isActive: boolean;
|
|
37
|
+
currentPeriodStart?: number;
|
|
38
|
+
currentPeriodEnd?: number;
|
|
39
|
+
cancelAtPeriodEnd?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface CreateMembershipSubscriptionArgs {
|
|
43
|
+
tierName: string;
|
|
44
|
+
interval?: "monthly" | "yearly";
|
|
45
|
+
paymentMethodId?: string;
|
|
46
|
+
userId?: string; // For API usage
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface MembershipSubscriptionResult {
|
|
50
|
+
subscriptionId: string;
|
|
51
|
+
tier: MembershipTier;
|
|
52
|
+
interval: "monthly" | "yearly";
|
|
53
|
+
status: string;
|
|
54
|
+
currentPeriodStart: number;
|
|
55
|
+
currentPeriodEnd: number;
|
|
56
|
+
cancelAtPeriodEnd?: boolean;
|
|
57
|
+
clientSecret?: string;
|
|
58
|
+
}
|
|
5
59
|
|
|
6
60
|
// Pricing in cents (for Stripe)
|
|
7
61
|
export const MEMBERSHIP_PRICING = {
|
package/src/utils/urlUtils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isProduction } from "./apiUtils";
|
|
2
|
-
import { BASH_DETAIL_URL } from "../definitions";
|
|
2
|
+
import { BASH_DETAIL_URL, STRIPE_CHECKOUT_TIMEOUT_MS, STRIPE_REDIRECT_TIMEOUT_MS } from "../definitions";
|
|
3
|
+
import { generateBashDetailUrl } from "./slugUtils";
|
|
3
4
|
|
|
4
5
|
const API_HOST = process.env.REACT_APP_API ?? "http://localhost:3500";
|
|
5
6
|
|
|
@@ -86,3 +87,115 @@ export function urlRemoveQueryParam(url: string, keys: string[]): string {
|
|
|
86
87
|
|
|
87
88
|
return newUrl;
|
|
88
89
|
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Constructs a full Stripe checkout URL by combining bash event detail URL with checkout path
|
|
93
|
+
* Used by backend to create success/cancel URLs for Stripe checkout sessions
|
|
94
|
+
*
|
|
95
|
+
* @param bashEventId - The bash event ID
|
|
96
|
+
* @param slug - The bash event slug
|
|
97
|
+
* @param checkoutPath - Base checkout path (e.g., CHECKOUT_RETURN_SUCCESS_URL)
|
|
98
|
+
* @param baseUrl - Frontend base URL (e.g., "https://yourdomain.com")
|
|
99
|
+
* @returns Full URL for Stripe checkout session
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* buildStripeCheckoutUrl("123", "my-event", "/checkout-success/{CHECKOUT_SESSION_ID}", "https://bash.com")
|
|
103
|
+
* // Returns: "https://bash.com/bash/123-my-event/checkout-success/{CHECKOUT_SESSION_ID}"
|
|
104
|
+
*/
|
|
105
|
+
export function buildStripeCheckoutUrl(
|
|
106
|
+
bashEventId: string,
|
|
107
|
+
slug: string,
|
|
108
|
+
checkoutPath: string,
|
|
109
|
+
baseUrl: string
|
|
110
|
+
): string {
|
|
111
|
+
// Use the existing generateBashDetailUrl function
|
|
112
|
+
const bashDetailPath = generateBashDetailUrl(bashEventId, slug);
|
|
113
|
+
return `${baseUrl}${bashDetailPath}${checkoutPath}`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Executes a function with a timeout and retry mechanism
|
|
118
|
+
* Used for Stripe checkout operations that might be slow
|
|
119
|
+
*
|
|
120
|
+
* @param operation - The async operation to execute
|
|
121
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
122
|
+
* @param onTimeout - Callback when timeout occurs
|
|
123
|
+
* @param maxRetries - Maximum number of retries (default: 1)
|
|
124
|
+
* @returns Promise that resolves/rejects based on operation success
|
|
125
|
+
*/
|
|
126
|
+
export async function executeWithTimeout<T>(
|
|
127
|
+
operation: () => Promise<T>,
|
|
128
|
+
timeoutMs: number = STRIPE_CHECKOUT_TIMEOUT_MS,
|
|
129
|
+
onTimeout?: (retryCount: number) => void | Promise<void>,
|
|
130
|
+
maxRetries: number = 1
|
|
131
|
+
): Promise<T> {
|
|
132
|
+
let lastError: Error | undefined;
|
|
133
|
+
|
|
134
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
135
|
+
try {
|
|
136
|
+
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
reject(new Error(`Operation timed out after ${timeoutMs}ms`));
|
|
139
|
+
}, timeoutMs);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const operationPromise = operation();
|
|
143
|
+
|
|
144
|
+
return await Promise.race([operationPromise, timeoutPromise]);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
lastError = error as Error;
|
|
147
|
+
|
|
148
|
+
if (attempt < maxRetries) {
|
|
149
|
+
console.warn(`Attempt ${attempt + 1} failed, retrying...`, error);
|
|
150
|
+
if (onTimeout) {
|
|
151
|
+
await onTimeout(attempt);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
throw lastError || new Error('Operation failed after all retries');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Redirects to Stripe checkout with timeout and fallback
|
|
162
|
+
*
|
|
163
|
+
* @param redirectUrl - The Stripe checkout URL
|
|
164
|
+
* @param timeoutMs - Timeout for redirect
|
|
165
|
+
* @param onTimeout - Callback when redirect times out
|
|
166
|
+
*/
|
|
167
|
+
export function redirectToStripeWithTimeout(
|
|
168
|
+
redirectUrl: string,
|
|
169
|
+
timeoutMs: number = STRIPE_REDIRECT_TIMEOUT_MS,
|
|
170
|
+
onTimeout?: () => void
|
|
171
|
+
): void {
|
|
172
|
+
let redirectCompleted = false;
|
|
173
|
+
|
|
174
|
+
// Set up timeout
|
|
175
|
+
const timeoutId = setTimeout(() => {
|
|
176
|
+
if (!redirectCompleted) {
|
|
177
|
+
console.warn('Stripe redirect timed out, forcing refresh...');
|
|
178
|
+
if (onTimeout) {
|
|
179
|
+
onTimeout();
|
|
180
|
+
} else {
|
|
181
|
+
// Default behavior: refresh the page
|
|
182
|
+
window.location.reload();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}, timeoutMs);
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
// Attempt redirect
|
|
189
|
+
window.location.href = redirectUrl;
|
|
190
|
+
redirectCompleted = true;
|
|
191
|
+
clearTimeout(timeoutId);
|
|
192
|
+
} catch (error) {
|
|
193
|
+
console.error('Failed to redirect to Stripe:', error);
|
|
194
|
+
clearTimeout(timeoutId);
|
|
195
|
+
if (onTimeout) {
|
|
196
|
+
onTimeout();
|
|
197
|
+
} else {
|
|
198
|
+
window.location.reload();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|