@umituz/react-native-ai-gemini-provider 3.0.40 → 3.0.42

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.
Files changed (89) hide show
  1. package/package.json +1 -4
  2. package/src/application/builders/config-builder.ts +102 -0
  3. package/src/application/builders/index.ts +8 -0
  4. package/src/application/dtos/generation-request.dto.ts +89 -0
  5. package/src/application/dtos/index.ts +8 -0
  6. package/src/application/index.ts +16 -0
  7. package/src/application/providers/gemini-provider.ts +135 -0
  8. package/src/application/providers/index.ts +6 -0
  9. package/src/application/use-cases/generate-json.use-case.ts +73 -0
  10. package/src/application/use-cases/generate-text.use-case.ts +81 -0
  11. package/src/application/use-cases/index.ts +20 -0
  12. package/src/application/use-cases/stream-content.use-case.ts +46 -0
  13. package/src/domain/entities/error.types.ts +0 -5
  14. package/src/domain/entities/gemini.types.ts +3 -1
  15. package/src/domain/index.ts +16 -0
  16. package/src/domain/repositories/index.ts +19 -0
  17. package/src/domain/repositories/streaming.repository.ts +41 -0
  18. package/src/domain/repositories/structured-text.repository.ts +41 -0
  19. package/src/domain/repositories/text-generation.repository.ts +38 -0
  20. package/src/domain/services/validation.service.ts +157 -0
  21. package/src/domain/value-objects/api-key.vo.ts +55 -0
  22. package/src/domain/value-objects/index.ts +8 -0
  23. package/src/domain/value-objects/model-name.vo.ts +66 -0
  24. package/src/domain/value-objects/timeout.vo.ts +69 -0
  25. package/src/index.ts +110 -25
  26. package/src/infrastructure/external/gemini-client.singleton.ts +49 -0
  27. package/src/infrastructure/external/gemini-sdk.adapter.ts +143 -0
  28. package/src/infrastructure/external/index.ts +7 -0
  29. package/src/infrastructure/index.ts +16 -0
  30. package/src/infrastructure/mappers/content.mapper.ts +80 -0
  31. package/src/infrastructure/mappers/error.mapper.ts +152 -0
  32. package/src/infrastructure/mappers/index.ts +7 -0
  33. package/src/infrastructure/mappers/response.mapper.ts +165 -0
  34. package/src/infrastructure/repositories/base-gemini.repository.ts +94 -0
  35. package/src/infrastructure/repositories/gemini-streaming.repository.impl.ts +119 -0
  36. package/src/infrastructure/repositories/gemini-structured-text.repository.impl.ts +108 -0
  37. package/src/infrastructure/repositories/gemini-text.repository.impl.ts +76 -0
  38. package/src/infrastructure/repositories/index.ts +10 -0
  39. package/src/infrastructure/utils/index.ts +6 -0
  40. package/src/presentation/hooks/index.ts +8 -0
  41. package/src/presentation/hooks/use-gemini.hook.ts +181 -0
  42. package/src/presentation/hooks/use-operation-manager.hook.ts +67 -0
  43. package/src/presentation/index.ts +10 -0
  44. package/src/presentation/providers/gemini-provider.tsx +93 -0
  45. package/src/presentation/providers/index.ts +10 -0
  46. package/dist/domain/entities/error.types.d.ts +0 -96
  47. package/dist/domain/entities/gemini.types.d.ts +0 -128
  48. package/dist/domain/entities/index.d.ts +0 -6
  49. package/dist/domain/entities/models.d.ts +0 -23
  50. package/dist/index.d.ts +0 -15
  51. package/dist/infrastructure/services/BaseService.d.ts +0 -29
  52. package/dist/infrastructure/services/ChatSession.d.ts +0 -63
  53. package/dist/infrastructure/services/GeminiClient.d.ts +0 -16
  54. package/dist/infrastructure/services/GeminiProvider.d.ts +0 -10
  55. package/dist/infrastructure/services/Streaming.d.ts +0 -7
  56. package/dist/infrastructure/services/StructuredText.d.ts +0 -6
  57. package/dist/infrastructure/services/TextGeneration.d.ts +0 -8
  58. package/dist/infrastructure/services/index.d.ts +0 -6
  59. package/dist/infrastructure/telemetry/TelemetryHooks.d.ts +0 -41
  60. package/dist/infrastructure/telemetry/index.d.ts +0 -4
  61. package/dist/infrastructure/utils/async/execute-state.util.d.ts +0 -49
  62. package/dist/infrastructure/utils/async/index.d.ts +0 -4
  63. package/dist/infrastructure/utils/content-mapper.util.d.ts +0 -45
  64. package/dist/infrastructure/utils/error-mapper.util.d.ts +0 -2
  65. package/dist/infrastructure/utils/gemini-data-transformer.util.d.ts +0 -2
  66. package/dist/infrastructure/utils/json-parser.util.d.ts +0 -9
  67. package/dist/infrastructure/utils/stream-processor.util.d.ts +0 -14
  68. package/dist/presentation/hooks/index.d.ts +0 -1
  69. package/dist/presentation/hooks/useGemini.d.ts +0 -17
  70. package/dist/presentation/hooks/useOperationManager.d.ts +0 -23
  71. package/dist/providers/ConfigBuilder.d.ts +0 -46
  72. package/dist/providers/ProviderFactory.d.ts +0 -25
  73. package/dist/providers/index.d.ts +0 -7
  74. package/src/infrastructure/services/BaseService.ts +0 -53
  75. package/src/infrastructure/services/ChatSession.ts +0 -199
  76. package/src/infrastructure/services/GeminiClient.ts +0 -112
  77. package/src/infrastructure/services/Streaming.ts +0 -56
  78. package/src/infrastructure/services/StructuredText.ts +0 -57
  79. package/src/infrastructure/services/TextGeneration.ts +0 -57
  80. package/src/infrastructure/telemetry/TelemetryHooks.ts +0 -110
  81. package/src/infrastructure/utils/async/execute-state.util.ts +0 -93
  82. package/src/infrastructure/utils/content-mapper.util.ts +0 -175
  83. package/src/infrastructure/utils/error-mapper.util.ts +0 -145
  84. package/src/infrastructure/utils/gemini-data-transformer.util.ts +0 -40
  85. package/src/infrastructure/utils/text-calculations.util.ts +0 -70
  86. package/src/presentation/hooks/useGemini.ts +0 -125
  87. package/src/presentation/hooks/useOperationManager.ts +0 -88
  88. package/src/providers/ConfigBuilder.ts +0 -112
  89. package/src/providers/ProviderFactory.ts +0 -65
@@ -1,125 +0,0 @@
1
- import { useState, useCallback, useMemo } from "react";
2
- import type { GeminiGenerationConfig } from "../../domain/entities";
3
- import { DEFAULT_MODELS } from "../../domain/entities";
4
- import { textGeneration } from "../../infrastructure/services/TextGeneration";
5
- import { structuredText } from "../../infrastructure/services/StructuredText";
6
- import { executeWithState, type AsyncStateSetters } from "../../infrastructure/utils/async/execute-state.util";
7
- import { useOperationManager } from "./useOperationManager";
8
-
9
- export interface UseGeminiOptions {
10
- model?: string;
11
- generationConfig?: GeminiGenerationConfig;
12
- onSuccess?: (result: string) => void;
13
- onError?: (error: string) => void;
14
- }
15
-
16
- export interface UseGeminiReturn {
17
- generate: (prompt: string) => Promise<void>;
18
- generateJSON: <T>(prompt: string, schema: Record<string, unknown>) => Promise<T | null>;
19
- result: string | null;
20
- jsonResult: unknown;
21
- isGenerating: boolean;
22
- error: string | null;
23
- reset: () => void;
24
- }
25
-
26
- export function useGemini(options: UseGeminiOptions = {}): UseGeminiReturn {
27
- const [result, setResult] = useState<string | null>(null);
28
- const [jsonResult, setJsonResult] = useState<unknown>(null);
29
- const [isGenerating, setIsGenerating] = useState(false);
30
- const [error, setError] = useState<string | null>(null);
31
-
32
- const { executeOperation, abort } = useOperationManager();
33
-
34
- const setters: AsyncStateSetters<string, unknown> = useMemo(
35
- () => ({
36
- setIsLoading: setIsGenerating,
37
- setError,
38
- setResult,
39
- setSecondaryResult: setJsonResult,
40
- }),
41
- []
42
- );
43
-
44
- const callbacks = useMemo(
45
- () => ({ onSuccess: options.onSuccess, onError: options.onError }),
46
- [options.onSuccess, options.onError]
47
- );
48
-
49
- const model = options.model ?? DEFAULT_MODELS.TEXT;
50
-
51
- const generate = useCallback(
52
- async (prompt: string) => {
53
- await executeOperation(async (signal, _operationId) => {
54
- await executeWithState(
55
- setters,
56
- callbacks,
57
- async () => {
58
- return textGeneration.generateText(
59
- model,
60
- prompt,
61
- options.generationConfig,
62
- signal
63
- );
64
- },
65
- (text: string) => {
66
- setResult(text);
67
- }
68
- );
69
- });
70
- },
71
- [model, options.generationConfig, setters, callbacks, executeOperation]
72
- );
73
-
74
- const generateJSON = useCallback(
75
- async <T>(prompt: string, schema: Record<string, unknown>): Promise<T | null> => {
76
- return executeOperation(async (signal, _operationId) => {
77
- const jsonSetters: AsyncStateSetters<unknown, unknown> = {
78
- setIsLoading: setIsGenerating,
79
- setError,
80
- setResult: setJsonResult,
81
- setSecondaryResult: (value) =>
82
- setResult(typeof value === "string" ? value : JSON.stringify(value)),
83
- };
84
-
85
- const jsonCallbacks = {
86
- onSuccess: options.onSuccess
87
- ? (result: unknown) => options.onSuccess?.(JSON.stringify(result))
88
- : undefined,
89
- onError: options.onError,
90
- };
91
-
92
- const operationResult = await executeWithState<unknown>(
93
- jsonSetters,
94
- jsonCallbacks,
95
- async () => {
96
- return structuredText.generateStructuredText<T>(
97
- model,
98
- prompt,
99
- schema,
100
- options.generationConfig,
101
- signal
102
- );
103
- },
104
- (parsed: unknown) => {
105
- setJsonResult(parsed);
106
- setResult(JSON.stringify(parsed, null, 2));
107
- }
108
- );
109
-
110
- return operationResult as T | null;
111
- });
112
- },
113
- [model, options.generationConfig, callbacks, executeOperation]
114
- );
115
-
116
- const reset = useCallback(() => {
117
- abort();
118
- setResult(null);
119
- setJsonResult(null);
120
- setIsGenerating(false);
121
- setError(null);
122
- }, [abort]);
123
-
124
- return { generate, generateJSON, result, jsonResult, isGenerating, error, reset };
125
- }
@@ -1,88 +0,0 @@
1
- /**
2
- * Operation Manager Hook
3
- * Reusable abort controller and operation ID management
4
- * Eliminates code duplication in hooks
5
- */
6
-
7
- import { useRef, useCallback, useEffect } from "react";
8
-
9
- export interface OperationManager {
10
- /**
11
- * Execute an operation with abort support and operation ID tracking
12
- */
13
- executeOperation: <T>(
14
- operation: (signal: AbortSignal, operationId: number) => Promise<T>
15
- ) => Promise<T>;
16
-
17
- /**
18
- * Abort current operation
19
- */
20
- abort: () => void;
21
-
22
- /**
23
- * Check if current operation is active
24
- */
25
- isOperationActive: (operationId: number) => boolean;
26
- }
27
-
28
- /**
29
- * Hook for managing operations with abort control
30
- */
31
- export function useOperationManager(): OperationManager {
32
- const abortControllerRef = useRef<AbortController | null>(null);
33
- const operationIdRef = useRef(0);
34
-
35
- const abort = useCallback(() => {
36
- if (abortControllerRef.current) {
37
- abortControllerRef.current.abort();
38
- abortControllerRef.current = null;
39
- }
40
- operationIdRef.current++;
41
- }, []);
42
-
43
- const isOperationActive = useCallback((operationId: number): boolean => {
44
- return operationId === operationIdRef.current;
45
- }, []);
46
-
47
- const executeOperation = useCallback(
48
- async <T>(
49
- operation: (signal: AbortSignal, operationId: number) => Promise<T>
50
- ): Promise<T> => {
51
- // Abort any existing operation
52
- if (abortControllerRef.current) {
53
- abortControllerRef.current.abort();
54
- }
55
-
56
- // Create new controller and increment operation ID
57
- const controller = new AbortController();
58
- abortControllerRef.current = controller;
59
- const currentOpId = ++operationIdRef.current;
60
-
61
- try {
62
- return await operation(controller.signal, currentOpId);
63
- } finally {
64
- // Clean up only if this is still the current operation
65
- if (currentOpId === operationIdRef.current) {
66
- abortControllerRef.current = null;
67
- }
68
- }
69
- },
70
- []
71
- );
72
-
73
- // Cleanup on unmount
74
- useEffect(() => {
75
- return () => {
76
- if (abortControllerRef.current) {
77
- abortControllerRef.current.abort();
78
- }
79
- operationIdRef.current++;
80
- };
81
- }, []);
82
-
83
- return {
84
- executeOperation,
85
- abort,
86
- isOperationActive,
87
- };
88
- }
@@ -1,112 +0,0 @@
1
- /**
2
- * Config Builder Pattern
3
- * Fluent API for building provider configuration
4
- */
5
-
6
- import { DEFAULT_MODELS } from "../domain/entities";
7
- import type { GeminiConfig } from "../domain/entities";
8
-
9
- export interface ProviderConfig {
10
- apiKey: string;
11
- textModel: string;
12
- timeout: number;
13
- strategy?: "cost" | "quality";
14
- }
15
-
16
- /**
17
- * Builder for constructing provider configuration
18
- * Provides a fluent API with validation and defaults
19
- */
20
- export class ConfigBuilder {
21
- private config: Omit<Partial<ProviderConfig>, 'textModel' | 'timeout'> & {
22
- textModel: string;
23
- timeout: number;
24
- } = {
25
- textModel: DEFAULT_MODELS.TEXT,
26
- timeout: 30000,
27
- };
28
-
29
- /**
30
- * Set API key (required)
31
- */
32
- withApiKey(apiKey: string): this {
33
- if (!apiKey || typeof apiKey !== "string" || apiKey.trim().length === 0) {
34
- throw new Error("API key must be a non-empty string");
35
- }
36
- this.config.apiKey = apiKey.trim();
37
- return this;
38
- }
39
-
40
- /**
41
- * Set text model
42
- */
43
- withTextModel(model: string): this {
44
- if (!model || !model.startsWith("gemini-")) {
45
- throw new Error("Invalid model name");
46
- }
47
- this.config.textModel = model;
48
- return this;
49
- }
50
-
51
- /**
52
- * Set request timeout (ms)
53
- */
54
- withTimeout(timeout: number): this {
55
- if (timeout <= 0 || timeout > 300000) {
56
- throw new Error("Timeout must be between 1ms and 300000ms (5 minutes)");
57
- }
58
- this.config.timeout = timeout;
59
- return this;
60
- }
61
-
62
- /**
63
- * Set strategy (applies preset timeout)
64
- */
65
- withStrategy(strategy: "cost" | "quality"): this {
66
- this.config.strategy = strategy;
67
-
68
- // Apply strategy-based defaults
69
- if (strategy === "quality") {
70
- this.config.timeout = 60000;
71
- } else {
72
- this.config.timeout = 30000;
73
- }
74
-
75
- return this;
76
- }
77
-
78
- /**
79
- * Build final configuration
80
- */
81
- build(): ProviderConfig {
82
- if (!this.config.apiKey) {
83
- throw new Error("API key is required. Call withApiKey() before build()");
84
- }
85
-
86
- return {
87
- apiKey: this.config.apiKey,
88
- textModel: this.config.textModel,
89
- timeout: this.config.timeout,
90
- strategy: this.config.strategy,
91
- };
92
- }
93
-
94
- /**
95
- * Convert to GeminiConfig format
96
- */
97
- toGeminiConfig(): GeminiConfig {
98
- const config = this.build();
99
- return {
100
- apiKey: config.apiKey,
101
- textModel: config.textModel,
102
- defaultTimeoutMs: config.timeout,
103
- };
104
- }
105
-
106
- /**
107
- * Create a new builder instance
108
- */
109
- static create(): ConfigBuilder {
110
- return new ConfigBuilder();
111
- }
112
- }
@@ -1,65 +0,0 @@
1
- import { geminiClient } from "../infrastructure/services/GeminiClient";
2
- import { ConfigBuilder, type ProviderConfig } from "./ConfigBuilder";
3
-
4
- // Re-export for public API
5
- export { ConfigBuilder } from "./ConfigBuilder";
6
- export type { ProviderConfig } from "./ConfigBuilder";
7
-
8
- export interface ProviderFactoryOptions {
9
- apiKey: string;
10
- timeout?: number;
11
- textModel?: string;
12
- strategy?: "cost" | "quality";
13
- }
14
-
15
- class ProviderFactory {
16
- private currentConfig: ProviderConfig | null = null;
17
-
18
- /**
19
- * Initialize provider with configuration
20
- */
21
- initialize(options: ProviderFactoryOptions): void {
22
- // Build configuration using builder pattern (inline, no state needed)
23
- const builder = ConfigBuilder.create().withApiKey(options.apiKey);
24
-
25
- if (options.strategy) {
26
- builder.withStrategy(options.strategy);
27
- }
28
-
29
- if (options.textModel) {
30
- builder.withTextModel(options.textModel);
31
- }
32
-
33
- if (options.timeout) {
34
- builder.withTimeout(options.timeout);
35
- }
36
-
37
- this.currentConfig = builder.build();
38
-
39
- // Initialize Gemini client
40
- const geminiConfig = builder.toGeminiConfig();
41
- geminiClient.initialize(geminiConfig);
42
- }
43
-
44
- /**
45
- * Check if provider is initialized
46
- */
47
- isInitialized(): boolean {
48
- return this.currentConfig !== null;
49
- }
50
-
51
- /**
52
- * Update configuration
53
- * API key changes require re-initialization
54
- */
55
- updateConfig(updates: Partial<ProviderFactoryOptions>): void {
56
- if (!this.currentConfig) {
57
- throw new Error("Provider not initialized. Call initialize() first.");
58
- }
59
-
60
- // Re-initialize with merged config to ensure GeminiClient is updated
61
- this.initialize({ ...this.currentConfig, ...updates });
62
- }
63
- }
64
-
65
- export const providerFactory = new ProviderFactory();