@umituz/react-native-ai-generation-content 1.17.68 → 1.17.70

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.17.68",
3
+ "version": "1.17.70",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
package/src/index.ts CHANGED
@@ -516,3 +516,8 @@ export * from "./features/text-to-voice";
516
516
 
517
517
  export * from "./features/hd-touch-up";
518
518
 
519
+ // =============================================================================
520
+ // INFRASTRUCTURE - Orchestration
521
+ // =============================================================================
522
+
523
+ export * from "./infrastructure/orchestration";
@@ -0,0 +1,251 @@
1
+ /**
2
+ * AI Generation Orchestrator
3
+ * Single Responsibility: Orchestrate common AI generation business operations
4
+ *
5
+ * Generic orchestrator for 100+ apps with dependency injection
6
+ * Handles: Network check, content moderation, credit processing, refunds
7
+ */
8
+
9
+ import { contentModerationService, ContentPolicyViolationError } from '../../domains/content-moderation';
10
+
11
+ declare const __DEV__: boolean;
12
+
13
+ export interface CreditService {
14
+ getBalance(userId: string): Promise<number>;
15
+ deduct(userId: string, amount: number): Promise<boolean>;
16
+ add(userId: string, amount: number): Promise<void>;
17
+ }
18
+
19
+ export interface PaywallService {
20
+ show(requiredCredits: number): void;
21
+ }
22
+
23
+ export interface NetworkService {
24
+ isOnline(): boolean;
25
+ }
26
+
27
+ export interface AuthService {
28
+ getUserId(): string | null;
29
+ isAuthenticated(): boolean;
30
+ }
31
+
32
+ export interface GenerationMetadata {
33
+ creditCost?: number;
34
+ numImages?: number;
35
+ duration?: number;
36
+ isPremium?: boolean;
37
+ [key: string]: unknown;
38
+ }
39
+
40
+ export type GenerationCapability =
41
+ | 'text-to-image'
42
+ | 'text-to-video'
43
+ | 'image-to-video'
44
+ | 'text-to-voice';
45
+
46
+ export class NetworkUnavailableError extends Error {
47
+ constructor() {
48
+ super('No internet connection. Please check your network and try again.');
49
+ this.name = 'NetworkUnavailableError';
50
+ }
51
+ }
52
+
53
+ export class InsufficientCreditsError extends Error {
54
+ constructor(
55
+ public required: number,
56
+ public current: number,
57
+ public capability: string,
58
+ ) {
59
+ super(
60
+ `Insufficient credits. Required: ${required}, Current: ${current}`,
61
+ );
62
+ this.name = 'InsufficientCreditsError';
63
+ }
64
+ }
65
+
66
+ export class AuthenticationRequiredError extends Error {
67
+ constructor() {
68
+ super('User not authenticated. This operation requires authentication.');
69
+ this.name = 'AuthenticationRequiredError';
70
+ }
71
+ }
72
+
73
+ export interface OrchestratorConfig {
74
+ creditService: CreditService;
75
+ paywallService: PaywallService;
76
+ networkService: NetworkService;
77
+ authService: AuthService;
78
+ calculateCreditCost: (
79
+ capability: GenerationCapability,
80
+ metadata?: GenerationMetadata,
81
+ ) => number;
82
+ }
83
+
84
+ export class GenerationOrchestrator {
85
+ constructor(private config: OrchestratorConfig) {}
86
+
87
+ /**
88
+ * Require authenticated user - throws if not authenticated
89
+ */
90
+ private requireAuthenticatedUser(): string {
91
+ const { authService } = this.config;
92
+ const isAuthenticated = authService.isAuthenticated();
93
+ const userId = authService.getUserId();
94
+
95
+ if (!isAuthenticated || !userId) {
96
+ throw new AuthenticationRequiredError();
97
+ }
98
+
99
+ return userId;
100
+ }
101
+
102
+ /**
103
+ * Check network availability - throws if offline
104
+ */
105
+ requireNetwork(): void {
106
+ if (!this.config.networkService.isOnline()) {
107
+ throw new NetworkUnavailableError();
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Moderate content before generation
113
+ */
114
+ async moderateContent(
115
+ _userId: string,
116
+ contentType: 'text' | 'image',
117
+ content: string,
118
+ metadata?: GenerationMetadata,
119
+ ): Promise<void> {
120
+ const actualUserId = this.requireAuthenticatedUser();
121
+
122
+ const moderationResult = await contentModerationService.moderate({
123
+ userId: actualUserId,
124
+ contentType,
125
+ content,
126
+ metadata,
127
+ });
128
+
129
+ if (!moderationResult.isAllowed) {
130
+ throw new ContentPolicyViolationError(
131
+ moderationResult.violations,
132
+ moderationResult.violations[0]?.suggestion,
133
+ );
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Calculate credit cost for generation
139
+ */
140
+ calculateCreditCost(
141
+ capability: GenerationCapability,
142
+ metadata?: GenerationMetadata,
143
+ ): number {
144
+ if (metadata?.creditCost && typeof metadata.creditCost === 'number') {
145
+ return metadata.creditCost;
146
+ }
147
+
148
+ return this.config.calculateCreditCost(capability, metadata);
149
+ }
150
+
151
+ /**
152
+ * Check credits BEFORE generation starts
153
+ * Shows paywall if insufficient
154
+ * @returns true if can proceed, false if paywall was shown
155
+ */
156
+ async checkCreditsAndShowPaywall(
157
+ capability: GenerationCapability,
158
+ metadata?: GenerationMetadata,
159
+ ): Promise<boolean> {
160
+ const creditCost = this.calculateCreditCost(capability, metadata);
161
+ const actualUserId = this.requireAuthenticatedUser();
162
+
163
+ const currentCredits =
164
+ await this.config.creditService.getBalance(actualUserId);
165
+
166
+ if (currentCredits < creditCost) {
167
+ this.config.paywallService.show(creditCost);
168
+ return false;
169
+ }
170
+
171
+ return true;
172
+ }
173
+
174
+ /**
175
+ * Process credits (deduct) for generation
176
+ * @returns deducted amount
177
+ */
178
+ async processCredits(
179
+ _userId: string,
180
+ capability: GenerationCapability,
181
+ metadata?: GenerationMetadata,
182
+ ): Promise<number> {
183
+ const actualUserId = this.requireAuthenticatedUser();
184
+ const creditCost = this.calculateCreditCost(capability, metadata);
185
+
186
+ const currentCredits =
187
+ await this.config.creditService.getBalance(actualUserId);
188
+
189
+ const success = await this.config.creditService.deduct(
190
+ actualUserId,
191
+ creditCost,
192
+ );
193
+
194
+ if (!success) {
195
+ this.config.paywallService.show(creditCost);
196
+ throw new InsufficientCreditsError(
197
+ creditCost,
198
+ currentCredits,
199
+ capability,
200
+ );
201
+ }
202
+
203
+ return creditCost;
204
+ }
205
+
206
+ /**
207
+ * Refund credits after generation failure
208
+ * Default behavior: REFUND all errors except user-caused ones
209
+ */
210
+ async refundCreditsIfApplicable(
211
+ _userId: string,
212
+ amount: number,
213
+ error: unknown,
214
+ ): Promise<void> {
215
+ if (amount <= 0) return;
216
+
217
+ // Non-refundable errors: User's fault or policy violations
218
+ const isNonRefundable =
219
+ error instanceof ContentPolicyViolationError ||
220
+ error instanceof InsufficientCreditsError ||
221
+ (error instanceof Error &&
222
+ (error.message.toLowerCase().includes('invalid input') ||
223
+ error.message.toLowerCase().includes('cancelled') ||
224
+ error.message.toLowerCase().includes('user cancel')));
225
+
226
+ if (__DEV__) {
227
+ // eslint-disable-next-line no-console
228
+ console.log('[GenerationOrchestrator] 🔄 Refund check:', {
229
+ amount,
230
+ isNonRefundable,
231
+ errorType: error instanceof Error ? error.name : typeof error,
232
+ errorMessage: error instanceof Error ? error.message : String(error),
233
+ });
234
+ }
235
+
236
+ // Default: REFUND all errors except user-caused ones
237
+ if (!isNonRefundable) {
238
+ const actualUserId = this.requireAuthenticatedUser();
239
+
240
+ if (__DEV__) {
241
+ // eslint-disable-next-line no-console
242
+ console.log('[GenerationOrchestrator] ✅ Refunding credits:', {
243
+ userId: actualUserId,
244
+ amount,
245
+ });
246
+ }
247
+
248
+ await this.config.creditService.add(actualUserId, amount);
249
+ }
250
+ }
251
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Orchestration Module
3
+ * Exports generic orchestration utilities for AI generation
4
+ */
5
+
6
+ export * from './GenerationOrchestrator';
@@ -40,8 +40,6 @@ export * from "./selectors/StyleSelector";
40
40
  export * from "./selectors/factories";
41
41
  export * from "./selectors/types";
42
42
  export * from "./PromptInput";
43
- export * from "./ExamplePrompts";
44
- export * from "./ModerationSummary";
45
43
  export * from "./image-picker";
46
44
  export * from "./buttons";
47
45
  export * from "./display";