@umituz/react-native-ai-gemini-provider 1.14.26 → 1.14.27

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-gemini-provider",
3
- "version": "1.14.26",
3
+ "version": "1.14.27",
4
4
  "description": "Google Gemini AI provider for React Native applications",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -1,20 +1,9 @@
1
1
  /**
2
2
  * @umituz/react-native-ai-gemini-provider
3
3
  * Google Gemini AI provider for React Native applications
4
- *
5
- * Usage:
6
- * import {
7
- * geminiClientService,
8
- * geminiProviderService,
9
- * useGemini,
10
- * mapGeminiError,
11
- * } from '@umituz/react-native-ai-gemini-provider';
12
4
  */
13
5
 
14
- // =============================================================================
15
- // DOMAIN LAYER - Types
16
- // =============================================================================
17
-
6
+ // Domain Types
18
7
  export type {
19
8
  GeminiConfig,
20
9
  GeminiGenerationConfig,
@@ -42,30 +31,14 @@ export type {
42
31
  VideoResolution,
43
32
  VideoOperationStatus,
44
33
  VeoOperation,
45
- } from "./domain/entities";
46
-
47
- export { GeminiErrorType } from "./domain/entities";
48
-
49
- export type {
50
34
  GeminiErrorInfo,
51
35
  GeminiApiError,
36
+ ResponseModality,
52
37
  } from "./domain/entities";
53
38
 
54
- export { GeminiError } from "./domain/entities";
55
-
56
- // Model Constants
57
- export {
58
- GEMINI_MODELS,
59
- DEFAULT_MODELS,
60
- RESPONSE_MODALITIES,
61
- } from "./domain/entities";
62
-
63
- export type { ResponseModality } from "./domain/entities";
64
-
65
- // =============================================================================
66
- // DOMAIN LAYER - Feature Models
67
- // =============================================================================
39
+ export { GeminiErrorType, GeminiError, GEMINI_MODELS, DEFAULT_MODELS, RESPONSE_MODALITIES } from "./domain/entities";
68
40
 
41
+ // Feature Models
69
42
  export {
70
43
  GEMINI_IMAGE_FEATURE_MODELS,
71
44
  GEMINI_VIDEO_FEATURE_MODELS,
@@ -74,14 +47,9 @@ export {
74
47
  getAllFeatureModels,
75
48
  } from "./domain/constants";
76
49
 
77
- export type {
78
- FeatureModelConfig,
79
- } from "./domain/constants";
80
-
81
- // =============================================================================
82
- // INFRASTRUCTURE LAYER - Services
83
- // =============================================================================
50
+ export type { FeatureModelConfig } from "./domain/constants";
84
51
 
52
+ // Services
85
53
  export {
86
54
  geminiClientCoreService,
87
55
  geminiRetryService,
@@ -109,16 +77,12 @@ export type {
109
77
  RetryOptions,
110
78
  } from "./infrastructure/services";
111
79
 
112
- // =============================================================================
113
- // INFRASTRUCTURE LAYER - Utils
114
- // =============================================================================
115
-
80
+ // Utils
116
81
  export {
117
82
  mapGeminiError,
118
83
  isGeminiErrorRetryable,
119
84
  categorizeGeminiError,
120
85
  createGeminiError,
121
- // Model validation
122
86
  isValidModel,
123
87
  validateModel,
124
88
  getSafeModel,
@@ -128,7 +92,13 @@ export {
128
92
  isVideoGenerationModel,
129
93
  getModelCategory,
130
94
  getAllValidModels,
131
- // Input builders
95
+ measureAsync,
96
+ measureSync,
97
+ debounce,
98
+ throttle,
99
+ PerformanceTimer,
100
+ PerformanceTracker,
101
+ performanceTracker,
132
102
  buildSingleImageInput,
133
103
  buildDualImageInput,
134
104
  buildUpscaleInput,
@@ -145,42 +115,41 @@ export {
145
115
  } from "./infrastructure/utils";
146
116
 
147
117
  export type {
148
- UpscaleOptions as GeminiUpscaleOptions,
149
- PhotoRestoreOptions as GeminiPhotoRestoreOptions,
150
- FaceSwapOptions as GeminiFaceSwapOptions,
151
- AnimeSelfieOptions as GeminiAnimeSelfieOptions,
152
- RemoveBackgroundOptions as GeminiRemoveBackgroundOptions,
153
- RemoveObjectOptions as GeminiRemoveObjectOptions,
154
- ReplaceBackgroundOptions as GeminiReplaceBackgroundOptions,
155
- VideoFromImageOptions as GeminiVideoFromImageOptions,
118
+ PreparedImage,
119
+ UpscaleOptions,
120
+ PhotoRestoreOptions,
121
+ FaceSwapOptions,
122
+ AnimeSelfieOptions,
123
+ RemoveBackgroundOptions,
124
+ RemoveObjectOptions,
125
+ ReplaceBackgroundOptions,
126
+ VideoFromImageOptions,
127
+ PerformanceMetrics,
156
128
  } from "./infrastructure/utils";
157
129
 
158
- // =============================================================================
159
- // PRESENTATION LAYER - Hooks
160
- // =============================================================================
161
-
130
+ // Hooks
162
131
  export { useGemini } from "./presentation/hooks";
163
132
 
164
- export type {
165
- UseGeminiOptions,
166
- UseGeminiReturn,
167
- } from "./presentation/hooks";
168
-
169
- // =============================================================================
170
- // TELEMETRY - Monitoring and Observability
171
- // =============================================================================
133
+ export type { UseGeminiOptions, UseGeminiReturn } from "./presentation/hooks";
172
134
 
135
+ // Telemetry
173
136
  export { telemetryHooks } from "./infrastructure/telemetry";
137
+ export type { TelemetryEvent, TelemetryListener } from "./infrastructure/telemetry";
174
138
 
139
+ // Interceptors
140
+ export { requestInterceptors, responseInterceptors } from "./infrastructure/interceptors";
175
141
  export type {
176
- TelemetryEvent,
177
- TelemetryListener,
178
- } from "./infrastructure/telemetry";
142
+ RequestContext,
143
+ RequestInterceptor,
144
+ ResponseContext,
145
+ ResponseInterceptor,
146
+ } from "./infrastructure/interceptors";
179
147
 
180
- // =============================================================================
181
- // PROVIDER CONFIGURATION - Tier-based Setup
182
- // =============================================================================
148
+ // Cache
149
+ export { SimpleCache, modelSelectionCache } from "./infrastructure/cache";
150
+ export type { CacheOptions } from "./infrastructure/cache";
183
151
 
152
+ // Provider Config
184
153
  export {
185
154
  providerFactory,
186
155
  resolveProviderConfig,
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Simple LRU Cache
3
+ * Least Recently Used cache for performance optimization
4
+ */
5
+
6
+ declare const __DEV__: boolean;
7
+
8
+ interface CacheEntry<V> {
9
+ value: V;
10
+ expiresAt: number;
11
+ }
12
+
13
+ export interface CacheOptions {
14
+ maxSize?: number;
15
+ ttl?: number; // Time to live in milliseconds
16
+ }
17
+
18
+ export class SimpleCache<K, V> {
19
+ private cache = new Map<K, CacheEntry<V>>();
20
+ private maxSize: number;
21
+ private ttl: number;
22
+
23
+ constructor(options: CacheOptions = {}) {
24
+ this.maxSize = options.maxSize ?? 100;
25
+ this.ttl = options.ttl ?? 5 * 60 * 1000; // 5 minutes default
26
+ }
27
+
28
+ /**
29
+ * Set a value in the cache
30
+ */
31
+ set(key: K, value: V, customTtl?: number): void {
32
+ // Remove oldest entry if at capacity
33
+ if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
34
+ const firstKey = this.cache.keys().next().value;
35
+ if (firstKey !== undefined) {
36
+ this.cache.delete(firstKey);
37
+ }
38
+ }
39
+
40
+ const ttl = customTtl ?? this.ttl;
41
+ this.cache.set(key, {
42
+ value,
43
+ expiresAt: Date.now() + ttl,
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Get a value from the cache
49
+ * Returns undefined if not found or expired
50
+ */
51
+ get(key: K): V | undefined {
52
+ const entry = this.cache.get(key);
53
+
54
+ if (!entry) {
55
+ return undefined;
56
+ }
57
+
58
+ // Check if expired
59
+ if (Date.now() > entry.expiresAt) {
60
+ this.cache.delete(key);
61
+ return undefined;
62
+ }
63
+
64
+ // Move to end (most recently used)
65
+ this.cache.delete(key);
66
+ this.cache.set(key, entry);
67
+
68
+ return entry.value;
69
+ }
70
+
71
+ /**
72
+ * Check if a key exists and is not expired
73
+ */
74
+ has(key: K): boolean {
75
+ return this.get(key) !== undefined;
76
+ }
77
+
78
+ /**
79
+ * Delete a specific key
80
+ */
81
+ delete(key: K): boolean {
82
+ return this.cache.delete(key);
83
+ }
84
+
85
+ /**
86
+ * Clear all entries
87
+ */
88
+ clear(): void {
89
+ this.cache.clear();
90
+ }
91
+
92
+ /**
93
+ * Get current cache size
94
+ */
95
+ size(): number {
96
+ // Clean expired entries first
97
+ this.cleanExpired();
98
+ return this.cache.size;
99
+ }
100
+
101
+ /**
102
+ * Remove all expired entries
103
+ */
104
+ private cleanExpired(): void {
105
+ const now = Date.now();
106
+ for (const [key, entry] of this.cache.entries()) {
107
+ if (now > entry.expiresAt) {
108
+ this.cache.delete(key);
109
+ }
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Get all valid keys (not expired)
115
+ */
116
+ keys(): K[] {
117
+ this.cleanExpired();
118
+ return Array.from(this.cache.keys());
119
+ }
120
+
121
+ /**
122
+ * Get cache statistics
123
+ */
124
+ getStats(): {
125
+ size: number;
126
+ maxSize: number;
127
+ keys: K[];
128
+ } {
129
+ return {
130
+ size: this.size(),
131
+ maxSize: this.maxSize,
132
+ keys: this.keys(),
133
+ };
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Global model selection cache
139
+ * Caches model IDs for features to avoid repeated lookups
140
+ */
141
+ class ModelSelectionCache {
142
+ private cache = new SimpleCache<string, string>({
143
+ maxSize: 50,
144
+ ttl: 10 * 60 * 1000, // 10 minutes
145
+ });
146
+
147
+ set(feature: string, model: string): void {
148
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
149
+ // eslint-disable-next-line no-console
150
+ console.log("[ModelSelectionCache] Caching model:", { feature, model });
151
+ }
152
+ this.cache.set(feature, model);
153
+ }
154
+
155
+ get(feature: string): string | undefined {
156
+ const model = this.cache.get(feature);
157
+ if (model && typeof __DEV__ !== "undefined" && __DEV__) {
158
+ // eslint-disable-next-line no-console
159
+ console.log("[ModelSelectionCache] Cache hit:", { feature, model });
160
+ }
161
+ return model;
162
+ }
163
+
164
+ clear(): void {
165
+ this.cache.clear();
166
+ }
167
+
168
+ getStats(): ReturnType<SimpleCache<string, string>["getStats"]> {
169
+ return this.cache.getStats();
170
+ }
171
+ }
172
+
173
+ export const modelSelectionCache = new ModelSelectionCache();
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Cache Module
3
+ * Simple LRU cache for performance optimization
4
+ */
5
+
6
+ export { SimpleCache, modelSelectionCache } from "./SimpleCache";
7
+ export type { CacheOptions } from "./SimpleCache";
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Request Interceptors
3
+ * Allows applications to modify requests before they're sent
4
+ */
5
+
6
+ export interface RequestContext {
7
+ model: string;
8
+ feature?: string;
9
+ payload: Record<string, unknown>;
10
+ timestamp: number;
11
+ }
12
+
13
+ export type RequestInterceptor = (context: RequestContext) => RequestContext | Promise<RequestContext>;
14
+
15
+ class RequestInterceptors {
16
+ private interceptors: RequestInterceptor[] = [];
17
+
18
+ /**
19
+ * Register a request interceptor
20
+ * Interceptors are called in order (first registered = first called)
21
+ */
22
+ use(interceptor: RequestInterceptor): () => void {
23
+ this.interceptors.push(interceptor);
24
+
25
+ // Return unsubscribe function
26
+ return () => {
27
+ const index = this.interceptors.indexOf(interceptor);
28
+ if (index > -1) {
29
+ this.interceptors.splice(index, 1);
30
+ }
31
+ };
32
+ }
33
+
34
+ /**
35
+ * Apply all interceptors to a request context
36
+ */
37
+ async apply(context: RequestContext): Promise<RequestContext> {
38
+ let result = context;
39
+
40
+ for (const interceptor of this.interceptors) {
41
+ try {
42
+ result = await interceptor(result);
43
+ } catch (error) {
44
+ // Interceptor error should fail the request
45
+ throw new Error(`Request interceptor failed: ${error instanceof Error ? error.message : String(error)}`);
46
+ }
47
+ }
48
+
49
+ return result;
50
+ }
51
+
52
+ /**
53
+ * Clear all interceptors
54
+ */
55
+ clear(): void {
56
+ this.interceptors = [];
57
+ }
58
+
59
+ /**
60
+ * Get interceptor count
61
+ */
62
+ count(): number {
63
+ return this.interceptors.length;
64
+ }
65
+ }
66
+
67
+ export const requestInterceptors = new RequestInterceptors();
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Response Interceptors
3
+ * Allows applications to modify responses after they're received
4
+ */
5
+
6
+ export interface ResponseContext<T = unknown> {
7
+ model: string;
8
+ feature?: string;
9
+ data: T;
10
+ duration: number;
11
+ timestamp: number;
12
+ }
13
+
14
+ export type ResponseInterceptor<T = unknown> = (
15
+ context: ResponseContext<T>,
16
+ ) => ResponseContext<T> | Promise<ResponseContext<T>>;
17
+
18
+ class ResponseInterceptors {
19
+ private interceptors: Array<ResponseInterceptor<unknown>> = [];
20
+
21
+ /**
22
+ * Register a response interceptor
23
+ * Interceptors are called in reverse order (last registered = first called)
24
+ */
25
+ use<T = unknown>(interceptor: ResponseInterceptor<T>): () => void {
26
+ this.interceptors.push(interceptor as ResponseInterceptor<unknown>);
27
+
28
+ // Return unsubscribe function
29
+ return () => {
30
+ const index = this.interceptors.indexOf(interceptor as ResponseInterceptor<unknown>);
31
+ if (index > -1) {
32
+ this.interceptors.splice(index, 1);
33
+ }
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Apply all interceptors to a response context
39
+ */
40
+ async apply<T>(context: ResponseContext<T>): Promise<ResponseContext<T>> {
41
+ let result: ResponseContext<unknown> = context;
42
+
43
+ // Apply in reverse order (last added = first processed)
44
+ for (let i = this.interceptors.length - 1; i >= 0; i--) {
45
+ const interceptor = this.interceptors[i];
46
+ try {
47
+ result = await interceptor(result);
48
+ } catch (error) {
49
+ // Interceptor error should fail the response processing
50
+ throw new Error(`Response interceptor failed: ${error instanceof Error ? error.message : String(error)}`);
51
+ }
52
+ }
53
+
54
+ return result as ResponseContext<T>;
55
+ }
56
+
57
+ /**
58
+ * Clear all interceptors
59
+ */
60
+ clear(): void {
61
+ this.interceptors = [];
62
+ }
63
+
64
+ /**
65
+ * Get interceptor count
66
+ */
67
+ count(): number {
68
+ return this.interceptors.length;
69
+ }
70
+ }
71
+
72
+ export const responseInterceptors = new ResponseInterceptors();
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interceptors Module
3
+ * Allows applications to modify requests and responses
4
+ */
5
+
6
+ export { requestInterceptors } from "./RequestInterceptors";
7
+ export { responseInterceptors } from "./ResponseInterceptors";
8
+
9
+ export type {
10
+ RequestContext,
11
+ RequestInterceptor,
12
+ } from "./RequestInterceptors";
13
+
14
+ export type {
15
+ ResponseContext,
16
+ ResponseInterceptor,
17
+ } from "./ResponseInterceptors";
@@ -33,6 +33,17 @@ export {
33
33
  getAllValidModels,
34
34
  } from "./model-validation.util";
35
35
 
36
+ export {
37
+ measureAsync,
38
+ measureSync,
39
+ debounce,
40
+ throttle,
41
+ PerformanceTimer,
42
+ PerformanceTracker,
43
+ performanceTracker,
44
+ } from "./performance.util";
45
+ export type { PerformanceMetrics } from "./performance.util";
46
+
36
47
  // Input builders
37
48
  export {
38
49
  buildSingleImageInput,
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Performance Utilities
3
+ * Tools for measuring and optimizing performance
4
+ */
5
+
6
+ declare const __DEV__: boolean;
7
+
8
+ export interface PerformanceMetrics {
9
+ duration: number;
10
+ timestamp: number;
11
+ metadata?: Record<string, unknown>;
12
+ }
13
+
14
+ export class PerformanceTimer {
15
+ private startTime: number;
16
+ private endTime?: number;
17
+ private metadata?: Record<string, unknown>;
18
+
19
+ constructor(metadata?: Record<string, unknown>) {
20
+ this.startTime = Date.now();
21
+ this.metadata = metadata;
22
+ }
23
+
24
+ stop(): number {
25
+ this.endTime = Date.now();
26
+ return this.duration;
27
+ }
28
+
29
+ get duration(): number {
30
+ const end = this.endTime ?? Date.now();
31
+ return end - this.startTime;
32
+ }
33
+
34
+ getMetrics(): PerformanceMetrics {
35
+ return { duration: this.duration, timestamp: this.startTime, metadata: this.metadata };
36
+ }
37
+
38
+ get isRunning(): boolean {
39
+ return this.endTime === undefined;
40
+ }
41
+ }
42
+
43
+ export async function measureAsync<T>(
44
+ operation: () => Promise<T>,
45
+ metadata?: Record<string, unknown>,
46
+ ): Promise<{ result: T; duration: number }> {
47
+ const timer = new PerformanceTimer(metadata);
48
+ try {
49
+ const result = await operation();
50
+ const duration = timer.stop();
51
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
52
+ // eslint-disable-next-line no-console
53
+ console.log("[Performance] Operation completed:", { duration: `${duration}ms`, metadata });
54
+ }
55
+ return { result, duration };
56
+ } catch (error) {
57
+ timer.stop();
58
+ throw error;
59
+ }
60
+ }
61
+
62
+ export function measureSync<T>(
63
+ operation: () => T,
64
+ metadata?: Record<string, unknown>,
65
+ ): { result: T; duration: number } {
66
+ const timer = new PerformanceTimer(metadata);
67
+ try {
68
+ const result = operation();
69
+ const duration = timer.stop();
70
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
71
+ // eslint-disable-next-line no-console
72
+ console.log("[Performance] Operation completed:", { duration: `${duration}ms`, metadata });
73
+ }
74
+ return { result, duration };
75
+ } catch (error) {
76
+ timer.stop();
77
+ throw error;
78
+ }
79
+ }
80
+
81
+ export function debounce<T extends (...args: never[]) => unknown>(
82
+ func: T,
83
+ wait: number,
84
+ ): (...args: Parameters<T>) => void {
85
+ let timeout: ReturnType<typeof setTimeout> | undefined;
86
+ return (...args: Parameters<T>) => {
87
+ const later = () => {
88
+ clearTimeout(timeout);
89
+ func(...args);
90
+ };
91
+ clearTimeout(timeout);
92
+ timeout = setTimeout(later, wait);
93
+ };
94
+ }
95
+
96
+ export function throttle<T extends (...args: never[]) => unknown>(
97
+ func: T,
98
+ limit: number,
99
+ ): (...args: Parameters<T>) => void {
100
+ let inThrottle: boolean;
101
+ return (...args: Parameters<T>) => {
102
+ if (!inThrottle) {
103
+ func(...args);
104
+ inThrottle = true;
105
+ setTimeout(() => (inThrottle = false), limit);
106
+ }
107
+ };
108
+ }
109
+
110
+ export class PerformanceTracker {
111
+ private metrics = new Map<string, number[]>();
112
+
113
+ record(operation: string, duration: number): void {
114
+ if (!this.metrics.has(operation)) {
115
+ this.metrics.set(operation, []);
116
+ }
117
+ this.metrics.get(operation)!.push(duration);
118
+ }
119
+
120
+ getStats(operation: string): { count: number; avg: number; min: number; max: number } | null {
121
+ const durations = this.metrics.get(operation);
122
+ if (!durations || durations.length === 0) return null;
123
+ return {
124
+ count: durations.length,
125
+ avg: durations.reduce((a, b) => a + b, 0) / durations.length,
126
+ min: Math.min(...durations),
127
+ max: Math.max(...durations),
128
+ };
129
+ }
130
+
131
+ getAllStats(): Record<string, ReturnType<PerformanceTracker["getStats"]>> {
132
+ const stats: Record<string, ReturnType<PerformanceTracker["getStats"]>> = {};
133
+ for (const operation of this.metrics.keys()) {
134
+ stats[operation] = this.getStats(operation);
135
+ }
136
+ return stats;
137
+ }
138
+
139
+ clear(): void {
140
+ this.metrics.clear();
141
+ }
142
+ }
143
+
144
+ export const performanceTracker = new PerformanceTracker();
145
+