@umituz/react-native-subscription 2.2.33 → 2.2.34
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/package.json +1 -1
- package/src/revenuecat/infrastructure/services/RevenueCatInitializer.ts +2 -7
- package/LICENSE +0 -32
- package/README.md +0 -216
- package/src/application/ports/ISubscriptionRepository.ts +0 -42
- package/src/application/ports/ISubscriptionService.ts +0 -51
- package/src/domain/entities/SubscriptionStatus.ts +0 -74
- package/src/domain/errors/SubscriptionError.ts +0 -43
- package/src/domain/value-objects/SubscriptionConfig.ts +0 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.34",
|
|
4
4
|
"description": "Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -7,7 +7,7 @@ import Purchases from "react-native-purchases";
|
|
|
7
7
|
import type { InitializeResult } from "../../application/ports/IRevenueCatService";
|
|
8
8
|
import type { RevenueCatConfig } from "../../domain/value-objects/RevenueCatConfig";
|
|
9
9
|
import { getErrorMessage } from "../../domain/types/RevenueCatTypes";
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
import { resolveApiKey } from "../utils/ApiKeyResolver";
|
|
12
12
|
|
|
13
13
|
export interface InitializerDeps {
|
|
@@ -63,12 +63,7 @@ export async function initializeSDK(
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
if (__DEV__) {
|
|
68
|
-
console.log("[RevenueCat] Skipping - ExpoGo without test store");
|
|
69
|
-
}
|
|
70
|
-
return { success: false, offering: null, hasPremium: false };
|
|
71
|
-
}
|
|
66
|
+
|
|
72
67
|
|
|
73
68
|
const key = apiKey || resolveApiKey(deps.config);
|
|
74
69
|
if (!key) {
|
package/LICENSE
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 Ümit UZ
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
package/README.md
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
# @umituz/react-native-subscription
|
|
2
|
-
|
|
3
|
-
Subscription management system for React Native apps - Database-first approach with secure validation.
|
|
4
|
-
|
|
5
|
-
Built with **SOLID**, **DRY**, and **KISS** principles.
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @umituz/react-native-subscription
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Peer Dependencies
|
|
14
|
-
|
|
15
|
-
- `react` >= 18.2.0
|
|
16
|
-
- `react-native` >= 0.74.0
|
|
17
|
-
|
|
18
|
-
## Features
|
|
19
|
-
|
|
20
|
-
- ✅ Domain-Driven Design (DDD) architecture
|
|
21
|
-
- ✅ SOLID principles (Single Responsibility, Open/Closed, etc.)
|
|
22
|
-
- ✅ DRY (Don't Repeat Yourself)
|
|
23
|
-
- ✅ KISS (Keep It Simple, Stupid)
|
|
24
|
-
- ✅ **Security**: Database-first approach - Always validate server-side
|
|
25
|
-
- ✅ Type-safe operations
|
|
26
|
-
- ✅ React hooks for easy integration
|
|
27
|
-
- ✅ Works with any database (Firebase, Supabase, etc.)
|
|
28
|
-
|
|
29
|
-
## Important: Database-First Approach
|
|
30
|
-
|
|
31
|
-
**This package follows a database-first approach:**
|
|
32
|
-
|
|
33
|
-
- Subscription status is ALWAYS checked from your database
|
|
34
|
-
- This ensures 10-50x faster subscription checks
|
|
35
|
-
- Works offline (database cache)
|
|
36
|
-
- More reliable than SDK-dependent checks
|
|
37
|
-
- **SECURITY**: Server-side validation always enforced
|
|
38
|
-
|
|
39
|
-
## Usage
|
|
40
|
-
|
|
41
|
-
### 1. Implement Repository Interface
|
|
42
|
-
|
|
43
|
-
First, implement the `ISubscriptionRepository` interface with your database:
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
import type { ISubscriptionRepository } from '@umituz/react-native-subscription';
|
|
47
|
-
import type { SubscriptionStatus } from '@umituz/react-native-subscription';
|
|
48
|
-
|
|
49
|
-
class MySubscriptionRepository implements ISubscriptionRepository {
|
|
50
|
-
async getSubscriptionStatus(userId: string): Promise<SubscriptionStatus | null> {
|
|
51
|
-
// Fetch from your database (Firebase, Supabase, etc.)
|
|
52
|
-
const doc = await db.collection('users').doc(userId).get();
|
|
53
|
-
return doc.data()?.subscription || null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async updateSubscriptionStatus(
|
|
57
|
-
userId: string,
|
|
58
|
-
status: Partial<SubscriptionStatus>,
|
|
59
|
-
): Promise<SubscriptionStatus> {
|
|
60
|
-
// Update in your database
|
|
61
|
-
await db.collection('users').doc(userId).update({
|
|
62
|
-
subscription: status,
|
|
63
|
-
updatedAt: new Date(),
|
|
64
|
-
});
|
|
65
|
-
return await this.getSubscriptionStatus(userId) || createDefaultSubscriptionStatus();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
isSubscriptionValid(status: SubscriptionStatus): boolean {
|
|
69
|
-
if (!status.isPremium) return false;
|
|
70
|
-
if (!status.expiresAt) return true; // Lifetime subscription
|
|
71
|
-
return new Date(status.expiresAt) > new Date();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### 2. Initialize Subscription Service
|
|
77
|
-
|
|
78
|
-
Initialize the service early in your app (e.g., in `App.tsx`):
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
import { initializeSubscriptionService } from '@umituz/react-native-subscription';
|
|
82
|
-
import { MySubscriptionRepository } from './repositories/MySubscriptionRepository';
|
|
83
|
-
|
|
84
|
-
// Initialize Subscription service
|
|
85
|
-
initializeSubscriptionService({
|
|
86
|
-
repository: new MySubscriptionRepository(),
|
|
87
|
-
onStatusChanged: async (userId, status) => {
|
|
88
|
-
// Optional: Sync to analytics, send notifications, etc.
|
|
89
|
-
await analytics.logEvent('subscription_changed', {
|
|
90
|
-
userId,
|
|
91
|
-
isPremium: status.isPremium,
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
onError: async (error, context) => {
|
|
95
|
-
// Optional: Log errors to crash reporting
|
|
96
|
-
await crashlytics.logError(error, context);
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### 3. Use Subscription Hook in Components
|
|
102
|
-
|
|
103
|
-
```typescript
|
|
104
|
-
import { useSubscription } from '@umituz/react-native-subscription';
|
|
105
|
-
import { useAuth } from '@umituz/react-native-auth';
|
|
106
|
-
|
|
107
|
-
function PremiumFeature() {
|
|
108
|
-
const { user } = useAuth();
|
|
109
|
-
const { status, isPremium, loading, loadStatus } = useSubscription();
|
|
110
|
-
|
|
111
|
-
useEffect(() => {
|
|
112
|
-
if (user?.uid) {
|
|
113
|
-
loadStatus(user.uid);
|
|
114
|
-
}
|
|
115
|
-
}, [user?.uid, loadStatus]);
|
|
116
|
-
|
|
117
|
-
if (loading) {
|
|
118
|
-
return <LoadingSpinner />;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (!isPremium) {
|
|
122
|
-
return <UpgradePrompt />;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return <PremiumContent />;
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### 4. Activate/Deactivate Subscription
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
import { getSubscriptionService } from '@umituz/react-native-subscription';
|
|
133
|
-
|
|
134
|
-
const service = getSubscriptionService();
|
|
135
|
-
|
|
136
|
-
// Activate subscription (e.g., after purchase)
|
|
137
|
-
await service.activateSubscription(
|
|
138
|
-
userId,
|
|
139
|
-
'premium_monthly',
|
|
140
|
-
'2024-12-31T23:59:59Z', // or null for lifetime
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
// Deactivate subscription
|
|
144
|
-
await service.deactivateSubscription(userId);
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## API
|
|
148
|
-
|
|
149
|
-
### Functions
|
|
150
|
-
|
|
151
|
-
- `initializeSubscriptionService(config)`: Initialize Subscription service with configuration
|
|
152
|
-
- `getSubscriptionService()`: Get Subscription service instance (throws if not initialized)
|
|
153
|
-
- `resetSubscriptionService()`: Reset service instance (useful for testing)
|
|
154
|
-
|
|
155
|
-
### Hook
|
|
156
|
-
|
|
157
|
-
- `useSubscription()`: React hook for subscription operations
|
|
158
|
-
|
|
159
|
-
### Types
|
|
160
|
-
|
|
161
|
-
- `SubscriptionStatus`: Subscription status entity
|
|
162
|
-
- `SubscriptionConfig`: Configuration interface
|
|
163
|
-
- `ISubscriptionRepository`: Repository interface (must be implemented)
|
|
164
|
-
- `UseSubscriptionResult`: Hook return type
|
|
165
|
-
|
|
166
|
-
### Errors
|
|
167
|
-
|
|
168
|
-
- `SubscriptionError`: Base error class
|
|
169
|
-
- `SubscriptionRepositoryError`: Repository errors
|
|
170
|
-
- `SubscriptionValidationError`: Validation errors
|
|
171
|
-
- `SubscriptionConfigurationError`: Configuration errors
|
|
172
|
-
|
|
173
|
-
## Security Best Practices
|
|
174
|
-
|
|
175
|
-
1. **Database-First**: Always check subscription status from your database, not SDK
|
|
176
|
-
2. **Server-Side Validation**: Always validate subscription expiration server-side
|
|
177
|
-
3. **Error Handling**: Always handle errors gracefully
|
|
178
|
-
4. **Repository Pattern**: Implement repository interface with your database
|
|
179
|
-
5. **Callbacks**: Use callbacks to sync subscription changes to analytics/notifications
|
|
180
|
-
|
|
181
|
-
## Integration with RevenueCat
|
|
182
|
-
|
|
183
|
-
This package works seamlessly with `@umituz/react-native-revenuecat`:
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
import { initializeRevenueCatService } from '@umituz/react-native-revenuecat';
|
|
187
|
-
import { getSubscriptionService } from '@umituz/react-native-subscription';
|
|
188
|
-
|
|
189
|
-
initializeRevenueCatService({
|
|
190
|
-
onPremiumStatusChanged: async (userId, isPremium, productId, expiresAt) => {
|
|
191
|
-
const subscriptionService = getSubscriptionService();
|
|
192
|
-
if (subscriptionService) {
|
|
193
|
-
if (isPremium && productId) {
|
|
194
|
-
await subscriptionService.activateSubscription(userId, productId, expiresAt || null);
|
|
195
|
-
} else {
|
|
196
|
-
await subscriptionService.deactivateSubscription(userId);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
},
|
|
200
|
-
});
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
## License
|
|
204
|
-
|
|
205
|
-
MIT
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subscription Repository Interface
|
|
3
|
-
* Port for database operations
|
|
4
|
-
*
|
|
5
|
-
* SECURITY: Apps must implement this interface with their database.
|
|
6
|
-
* Never expose database credentials or allow direct database access.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { SubscriptionStatus } from '../../domain/entities/SubscriptionStatus';
|
|
10
|
-
|
|
11
|
-
export interface ISubscriptionRepository {
|
|
12
|
-
/**
|
|
13
|
-
* Get subscription status for a user
|
|
14
|
-
* Returns null if user not found
|
|
15
|
-
*/
|
|
16
|
-
getSubscriptionStatus(userId: string): Promise<SubscriptionStatus | null>;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Update subscription status for a user
|
|
20
|
-
*/
|
|
21
|
-
updateSubscriptionStatus(
|
|
22
|
-
userId: string,
|
|
23
|
-
status: Partial<SubscriptionStatus>,
|
|
24
|
-
): Promise<SubscriptionStatus>;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Check if subscription is valid (not expired)
|
|
28
|
-
* SECURITY: Always validate expiration server-side
|
|
29
|
-
*/
|
|
30
|
-
isSubscriptionValid(status: SubscriptionStatus): boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subscription Service Interface
|
|
3
|
-
* Port for subscription operations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { SubscriptionStatus } from '../../domain/entities/SubscriptionStatus';
|
|
7
|
-
|
|
8
|
-
export interface ISubscriptionService {
|
|
9
|
-
/**
|
|
10
|
-
* Get subscription status for a user
|
|
11
|
-
*/
|
|
12
|
-
getSubscriptionStatus(userId: string): Promise<SubscriptionStatus>;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Check if user has active subscription
|
|
16
|
-
*/
|
|
17
|
-
isPremium(userId: string): Promise<boolean>;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Activate subscription
|
|
21
|
-
*/
|
|
22
|
-
activateSubscription(
|
|
23
|
-
userId: string,
|
|
24
|
-
productId: string,
|
|
25
|
-
expiresAt: string | null,
|
|
26
|
-
): Promise<SubscriptionStatus>;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Deactivate subscription
|
|
30
|
-
*/
|
|
31
|
-
deactivateSubscription(userId: string): Promise<SubscriptionStatus>;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Update subscription status
|
|
35
|
-
*/
|
|
36
|
-
updateSubscriptionStatus(
|
|
37
|
-
userId: string,
|
|
38
|
-
updates: Partial<SubscriptionStatus>,
|
|
39
|
-
): Promise<SubscriptionStatus>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subscription Status Entity
|
|
3
|
-
* Represents subscription status for a user
|
|
4
|
-
*
|
|
5
|
-
* SECURITY: This is a read-only entity from database.
|
|
6
|
-
* Never trust client-side subscription status - always validate server-side.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export interface SubscriptionStatus {
|
|
10
|
-
/** Whether user has active subscription */
|
|
11
|
-
isPremium: boolean;
|
|
12
|
-
|
|
13
|
-
/** Subscription expiration date (ISO string) */
|
|
14
|
-
expiresAt: string | null;
|
|
15
|
-
|
|
16
|
-
/** Product ID of the subscription */
|
|
17
|
-
productId: string | null;
|
|
18
|
-
|
|
19
|
-
/** When subscription was purchased (ISO string) */
|
|
20
|
-
purchasedAt: string | null;
|
|
21
|
-
|
|
22
|
-
/** External service customer ID (e.g., RevenueCat customer ID) */
|
|
23
|
-
customerId: string | null;
|
|
24
|
-
|
|
25
|
-
/** Last sync time with external service (ISO string) */
|
|
26
|
-
syncedAt: string | null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Create default subscription status (free user)
|
|
31
|
-
*/
|
|
32
|
-
export function createDefaultSubscriptionStatus(): SubscriptionStatus {
|
|
33
|
-
return {
|
|
34
|
-
isPremium: false,
|
|
35
|
-
expiresAt: null,
|
|
36
|
-
productId: null,
|
|
37
|
-
purchasedAt: null,
|
|
38
|
-
customerId: null,
|
|
39
|
-
syncedAt: null,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Check if subscription status is valid (not expired)
|
|
45
|
-
* SECURITY: Always validate expiration server-side
|
|
46
|
-
*/
|
|
47
|
-
export function isSubscriptionValid(status: SubscriptionStatus | null): boolean {
|
|
48
|
-
if (!status || !status.isPremium) {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (!status.expiresAt) {
|
|
53
|
-
// Lifetime subscription (no expiration)
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const expirationDate = new Date(status.expiresAt);
|
|
58
|
-
const now = new Date();
|
|
59
|
-
|
|
60
|
-
// Add 1 day buffer for clock skew and timezone issues
|
|
61
|
-
const bufferMs = 24 * 60 * 60 * 1000;
|
|
62
|
-
return expirationDate.getTime() > now.getTime() - bufferMs;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subscription Errors
|
|
3
|
-
* Domain-specific errors for subscription operations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export class SubscriptionError extends Error {
|
|
7
|
-
constructor(message: string, public readonly code: string) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = 'SubscriptionError';
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class SubscriptionRepositoryError extends SubscriptionError {
|
|
14
|
-
constructor(message: string) {
|
|
15
|
-
super(message, 'REPOSITORY_ERROR');
|
|
16
|
-
this.name = 'SubscriptionRepositoryError';
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class SubscriptionValidationError extends SubscriptionError {
|
|
21
|
-
constructor(message: string) {
|
|
22
|
-
super(message, 'VALIDATION_ERROR');
|
|
23
|
-
this.name = 'SubscriptionValidationError';
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class SubscriptionConfigurationError extends SubscriptionError {
|
|
28
|
-
constructor(message: string) {
|
|
29
|
-
super(message, 'CONFIGURATION_ERROR');
|
|
30
|
-
this.name = 'SubscriptionConfigurationError';
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subscription Configuration Value Object
|
|
3
|
-
* Configuration for subscription service
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { SubscriptionStatus } from '../entities/SubscriptionStatus';
|
|
7
|
-
import type { ISubscriptionRepository } from '../../application/ports/ISubscriptionRepository';
|
|
8
|
-
|
|
9
|
-
export interface SubscriptionConfig {
|
|
10
|
-
/** Repository implementation for database operations */
|
|
11
|
-
repository: ISubscriptionRepository;
|
|
12
|
-
|
|
13
|
-
/** Optional callback when subscription status changes */
|
|
14
|
-
onStatusChanged?: (
|
|
15
|
-
userId: string,
|
|
16
|
-
status: SubscriptionStatus,
|
|
17
|
-
) => Promise<void> | void;
|
|
18
|
-
|
|
19
|
-
/** Optional callback for error logging */
|
|
20
|
-
onError?: (error: Error, context: string) => Promise<void> | void;
|
|
21
|
-
}
|
|
22
|
-
|