@umituz/react-native-ai-gemini-provider 2.1.12 → 3.0.0

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": "2.1.12",
3
+ "version": "3.0.0",
4
4
  "description": "Google Gemini AI text generation provider for React Native applications",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -27,13 +27,12 @@ export {
27
27
  DEFAULT_MODELS
28
28
  } from "./domain/entities";
29
29
 
30
- // Main Service
31
- export {
32
- geminiProviderService,
33
- GeminiProvider,
34
- } from "./infrastructure/services";
35
-
36
- export type { GeminiProviderConfig } from "./infrastructure/services";
30
+ // Services
31
+ export { geminiClient } from "./infrastructure/services/GeminiClient";
32
+ export { textGeneration } from "./infrastructure/services/TextGeneration";
33
+ export { structuredText } from "./infrastructure/services/StructuredText";
34
+ export { streaming } from "./infrastructure/services/Streaming";
35
+ export { geminiProvider, GeminiProvider } from "./infrastructure/services/GeminiProvider";
37
36
 
38
37
  // React Hook
39
38
  export { useGemini } from "./presentation/hooks";
@@ -1,17 +1,9 @@
1
- /**
2
- * Base Gemini Service
3
- * Common functionality for all Gemini services to eliminate code duplication
4
- */
5
-
6
- import { geminiClientCoreService } from "./gemini-client-core.service";
1
+ import { geminiClient } from "./GeminiClient";
7
2
  import { toSdkContent } from "../utils/content-mapper.util";
8
3
  import { createGeminiError } from "../utils/error-mapper.util";
9
4
  import type { GeminiContent, GeminiGenerationConfig } from "../../domain/entities";
10
5
  import type { GenerativeModel } from "@google/generative-ai";
11
6
 
12
- /**
13
- * Base request options structure
14
- */
15
7
  export interface BaseRequestOptions {
16
8
  model: string;
17
9
  contents: GeminiContent[];
@@ -19,64 +11,41 @@ export interface BaseRequestOptions {
19
11
  signal?: AbortSignal;
20
12
  }
21
13
 
22
- /**
23
- * Abstract base service with common patterns
24
- */
25
14
  export abstract class BaseGeminiService {
26
- /**
27
- * Validate and prepare request
28
- * Eliminates duplicate validation and abort checks
29
- */
30
15
  protected validateAndPrepare(options: BaseRequestOptions): {
31
16
  genModel: GenerativeModel;
32
17
  sdkContents: Array<{ role: string; parts: Array<{ text: string }> }>;
33
18
  } {
34
- // Validate contents
35
19
  if (!options.contents || options.contents.length === 0) {
36
20
  throw new Error("Contents array cannot be empty");
37
21
  }
38
22
 
39
- // Check for early abort
40
23
  if (options.signal?.aborted) {
41
24
  throw new Error("Request was aborted");
42
25
  }
43
26
 
44
- const genModel = geminiClientCoreService.getModel(options.model);
27
+ const genModel = geminiClient.getModel(options.model);
45
28
  const sdkContents = toSdkContent(options.contents);
46
29
 
47
30
  return { genModel, sdkContents };
48
31
  }
49
32
 
50
- /**
51
- * Handle errors uniformly across all services
52
- * Eliminates duplicate error handling logic
53
- */
54
33
  protected handleError(error: unknown, abortMessage: string): never {
55
- // Re-throw as GeminiError if it's already an API error
56
34
  if (error instanceof Error && error.name === "GeminiError") {
57
35
  throw error;
58
36
  }
59
37
 
60
- // Check for abort error
61
38
  if (error instanceof Error && error.name === "AbortError") {
62
39
  throw new Error(abortMessage);
63
40
  }
64
41
 
65
- // Wrap other errors
66
42
  throw createGeminiError(error);
67
43
  }
68
44
 
69
- /**
70
- * Create typed request options for SDK
71
- * Type-safe request creation
72
- */
73
45
  protected createRequestOptions(
74
46
  sdkContents: Array<{ role: string; parts: Array<{ text: string }> }>,
75
47
  generationConfig?: GeminiGenerationConfig
76
48
  ) {
77
- return {
78
- contents: sdkContents,
79
- generationConfig,
80
- };
49
+ return { contents: sdkContents, generationConfig };
81
50
  }
82
51
  }
@@ -1,29 +1,22 @@
1
1
  import { GoogleGenerativeAI, type GenerativeModel } from "@google/generative-ai";
2
2
  import { DEFAULT_MODELS } from "../../domain/entities";
3
3
  import type { GeminiConfig } from "../../domain/entities";
4
- import { validateModelName, validateApiKey } from "../utils/validation.util";
5
4
 
6
5
  const DEFAULT_CONFIG: Partial<GeminiConfig> = {
7
6
  textModel: DEFAULT_MODELS.TEXT,
8
7
  };
9
8
 
10
- class GeminiClientCoreService {
9
+ class GeminiClient {
11
10
  private client: GoogleGenerativeAI | null = null;
12
11
  private config: GeminiConfig | null = null;
13
12
  private initialized = false;
14
13
 
15
- /**
16
- * Initialize the Gemini client with configuration
17
- *
18
- * @throws {Error} If already initialized or API key is invalid
19
- */
20
14
  initialize(config: GeminiConfig): void {
21
- if (this.initialized) {
22
- throw new Error("Gemini client already initialized. Call reset() before re-initializing with new config.");
23
- }
15
+ if (this.initialized) return;
24
16
 
25
- // Validate API key
26
- validateApiKey(config.apiKey);
17
+ if (!config.apiKey || config.apiKey.trim().length < 10) {
18
+ throw new Error("API key is required and must be at least 10 characters");
19
+ }
27
20
 
28
21
  this.client = new GoogleGenerativeAI(config.apiKey);
29
22
  this.config = { ...DEFAULT_CONFIG, ...config };
@@ -42,24 +35,16 @@ class GeminiClientCoreService {
42
35
  return this.client;
43
36
  }
44
37
 
45
- validateInitialization(): void {
38
+ getModel(modelName?: string): GenerativeModel {
46
39
  if (!this.client || !this.initialized) {
47
40
  throw new Error("Gemini client not initialized. Call initialize() first.");
48
41
  }
49
- }
50
-
51
-
52
- getModel(modelName?: string): GenerativeModel {
53
- this.validateInitialization();
54
-
55
- if (!this.client) {
56
- throw new Error("Gemini client not available");
57
- }
58
42
 
59
43
  const effectiveModel = modelName || this.config?.textModel || DEFAULT_MODELS.TEXT;
60
44
 
61
- // Validate model name format
62
- validateModelName(effectiveModel);
45
+ if (!effectiveModel.startsWith("gemini-")) {
46
+ throw new Error('Model name must start with "gemini-"');
47
+ }
63
48
 
64
49
  return this.client.getGenerativeModel({ model: effectiveModel });
65
50
  }
@@ -71,4 +56,4 @@ class GeminiClientCoreService {
71
56
  }
72
57
  }
73
58
 
74
- export const geminiClientCoreService = new GeminiClientCoreService();
59
+ export const geminiClient = new GeminiClient();
@@ -0,0 +1,38 @@
1
+ import type { GeminiConfig } from "../../domain/entities";
2
+ import { geminiClient } from "./GeminiClient";
3
+ import { structuredText } from "./StructuredText";
4
+
5
+ export class GeminiProvider {
6
+ readonly providerId = "gemini";
7
+ readonly providerName = "Google Gemini";
8
+
9
+ initialize(config: GeminiConfig): void {
10
+ geminiClient.initialize(config);
11
+ }
12
+
13
+ isInitialized(): boolean {
14
+ return geminiClient.isInitialized();
15
+ }
16
+
17
+ reset(): void {
18
+ geminiClient.reset();
19
+ }
20
+
21
+ async generateStructuredText<T>(
22
+ prompt: string,
23
+ schema: Record<string, unknown>,
24
+ model: string,
25
+ ): Promise<T> {
26
+ if (!prompt || prompt.trim().length < 3) {
27
+ throw new Error("Prompt must be at least 3 characters");
28
+ }
29
+
30
+ if (!this.isInitialized()) {
31
+ throw new Error("Provider not initialized. Call initialize() first.");
32
+ }
33
+
34
+ return structuredText.generateStructuredText<T>(model, prompt, schema);
35
+ }
36
+ }
37
+
38
+ export const geminiProvider = new GeminiProvider();
@@ -1,4 +1,4 @@
1
- import { BaseGeminiService } from "./base-gemini.service";
1
+ import { BaseGeminiService } from "./BaseService";
2
2
  import { telemetryHooks } from "../telemetry";
3
3
  import { processStream } from "../utils/stream-processor.util";
4
4
  import type {
@@ -6,22 +6,7 @@ import type {
6
6
  GeminiGenerationConfig,
7
7
  } from "../../domain/entities";
8
8
 
9
- class GeminiStreamingService extends BaseGeminiService {
10
- /**
11
- * Stream content generation
12
- *
13
- * @throws {GeminiError} For API-specific errors
14
- * @throws {Error} For validation or network errors
15
- *
16
- * @example
17
- * ```ts
18
- * const fullText = await streamContent(
19
- * "gemini-2.5-flash-lite",
20
- * [{ parts: [{ text: "Hello" }], role: "user" }],
21
- * (chunk) => console.log(chunk)
22
- * );
23
- * ```
24
- */
9
+ class StreamingService extends BaseGeminiService {
25
10
  async streamContent(
26
11
  model: string,
27
12
  contents: GeminiContent[],
@@ -29,7 +14,6 @@ class GeminiStreamingService extends BaseGeminiService {
29
14
  generationConfig?: GeminiGenerationConfig,
30
15
  signal?: AbortSignal,
31
16
  ): Promise<string> {
32
- // Validate callback
33
17
  if (typeof onChunk !== "function") {
34
18
  throw new Error("onChunk must be a function");
35
19
  }
@@ -51,27 +35,22 @@ class GeminiStreamingService extends BaseGeminiService {
51
35
  return await processStream(
52
36
  result.stream,
53
37
  onChunk,
54
- (error, context) => this.logStreamError(model, error, context)
38
+ (error, context) => {
39
+ try {
40
+ telemetryHooks.logError(
41
+ model,
42
+ error instanceof Error ? error : new Error(String(error)),
43
+ context
44
+ );
45
+ } catch {
46
+ // Silently ignore telemetry errors
47
+ }
48
+ }
55
49
  );
56
50
  } catch (error) {
57
51
  return this.handleError(error, "Stream generation was aborted");
58
52
  }
59
53
  }
60
-
61
- /**
62
- * Log stream errors via telemetry
63
- */
64
- private logStreamError(model: string, error: unknown, context?: string): void {
65
- try {
66
- telemetryHooks.logError(
67
- model,
68
- error instanceof Error ? error : new Error(String(error)),
69
- context
70
- );
71
- } catch {
72
- // Silently ignore telemetry errors
73
- }
74
- }
75
54
  }
76
55
 
77
- export const geminiStreamingService = new GeminiStreamingService();
56
+ export const streaming = new StreamingService();
@@ -1,8 +1,6 @@
1
-
2
- import { geminiTextGenerationService } from "./gemini-text-generation.service";
1
+ import { textGeneration } from "./TextGeneration";
3
2
  import { parseJsonResponse } from "../utils/json-parser.util";
4
3
  import { extractTextFromParts } from "../utils/content-mapper.util";
5
- import { validateSchema } from "../utils/validation.util";
6
4
  import type { GenerationConfig } from "@google/generative-ai";
7
5
  import type {
8
6
  GeminiContent,
@@ -10,11 +8,7 @@ import type {
10
8
  GeminiResponse,
11
9
  } from "../../domain/entities";
12
10
 
13
-
14
- class GeminiStructuredTextService {
15
- /**
16
- * Generate structured JSON response with schema
17
- */
11
+ class StructuredTextService {
18
12
  async generateStructuredText<T>(
19
13
  model: string,
20
14
  prompt: string,
@@ -22,7 +16,9 @@ class GeminiStructuredTextService {
22
16
  config?: Omit<GeminiGenerationConfig, "responseMimeType" | "responseSchema">,
23
17
  signal?: AbortSignal,
24
18
  ): Promise<T> {
25
- validateSchema(schema);
19
+ if (!schema || typeof schema !== "object" || Object.keys(schema).length === 0) {
20
+ throw new Error("Schema must be a non-empty object");
21
+ }
26
22
 
27
23
  const generationConfig: GeminiGenerationConfig = {
28
24
  ...config,
@@ -34,7 +30,7 @@ class GeminiStructuredTextService {
34
30
  { parts: [{ text: prompt }], role: "user" },
35
31
  ];
36
32
 
37
- const response = await geminiTextGenerationService.generateContent(
33
+ const response = await textGeneration.generateContent(
38
34
  model,
39
35
  contents,
40
36
  generationConfig,
@@ -44,9 +40,6 @@ class GeminiStructuredTextService {
44
40
  return this.parseJSONResponse<T>(response);
45
41
  }
46
42
 
47
- /**
48
- * Parse JSON response from Gemini
49
- */
50
43
  private parseJSONResponse<T>(response: GeminiResponse): T {
51
44
  const candidates = response.candidates;
52
45
 
@@ -64,4 +57,4 @@ class GeminiStructuredTextService {
64
57
  }
65
58
  }
66
59
 
67
- export const geminiStructuredTextService = new GeminiStructuredTextService();
60
+ export const structuredText = new StructuredTextService();
@@ -1,20 +1,13 @@
1
- import { BaseGeminiService } from "./base-gemini.service";
1
+ import { BaseGeminiService } from "./BaseService";
2
2
  import { extractTextFromResponse } from "../utils/gemini-data-transformer.util";
3
3
  import { transformResponse, createTextContent } from "../utils/content-mapper.util";
4
- import { validatePrompt } from "../utils/validation.util";
5
4
  import type {
6
5
  GeminiContent,
7
6
  GeminiGenerationConfig,
8
7
  GeminiResponse,
9
8
  } from "../../domain/entities";
10
9
 
11
- class GeminiTextGenerationService extends BaseGeminiService {
12
- /**
13
- * Generate content (text, with optional images)
14
- *
15
- * @throws {GeminiError} For API-specific errors
16
- * @throws {Error} For validation or network errors
17
- */
10
+ class TextGenerationService extends BaseGeminiService {
18
11
  async generateContent(
19
12
  model: string,
20
13
  contents: GeminiContent[],
@@ -35,38 +28,30 @@ class GeminiTextGenerationService extends BaseGeminiService {
35
28
  ? await genModel.generateContent(requestOptions, { signal })
36
29
  : await genModel.generateContent(requestOptions);
37
30
 
38
- const response = result.response;
39
-
40
- if (!response) {
31
+ if (!result.response) {
41
32
  throw new Error("No response received from Gemini API");
42
33
  }
43
34
 
44
- return transformResponse(response);
35
+ return transformResponse(result.response);
45
36
  } catch (error) {
46
37
  return this.handleError(error, "Request was aborted");
47
38
  }
48
39
  }
49
40
 
50
- /**
51
- * Generate text from prompt
52
- *
53
- * @throws {GeminiError} For API-specific errors
54
- * @throws {Error} For validation or network errors
55
- */
56
41
  async generateText(
57
42
  model: string,
58
43
  prompt: string,
59
44
  config?: GeminiGenerationConfig,
60
45
  signal?: AbortSignal,
61
46
  ): Promise<string> {
62
- // Validate prompt
63
- validatePrompt(prompt);
47
+ if (!prompt || prompt.trim().length < 3) {
48
+ throw new Error("Prompt must be at least 3 characters");
49
+ }
64
50
 
65
51
  const contents: GeminiContent[] = [createTextContent(prompt, "user")];
66
-
67
52
  const response = await this.generateContent(model, contents, config, signal);
68
53
  return extractTextFromResponse(response);
69
54
  }
70
55
  }
71
56
 
72
- export const geminiTextGenerationService = new GeminiTextGenerationService();
57
+ export const textGeneration = new TextGenerationService();
@@ -1,21 +1,6 @@
1
- /**
2
- * Infrastructure Services - Internal Use Only
3
- */
4
-
5
- // Internal base classes
6
- export { BaseGeminiService } from "./base-gemini.service";
7
- export type { BaseRequestOptions } from "./base-gemini.service";
8
-
9
- // Internal services
10
- export { geminiClientCoreService } from "./gemini-client-core.service";
11
- export { geminiTextGenerationService } from "./gemini-text-generation.service";
12
- export { geminiStructuredTextService } from "./gemini-structured-text.service";
13
- export { geminiStreamingService } from "./gemini-streaming.service";
14
-
15
- // Main Provider - Public API
16
- export {
17
- geminiProviderService,
18
- GeminiProvider,
19
- } from "./gemini-provider";
20
- export type { GeminiProviderConfig } from "./gemini-provider";
21
-
1
+ export { geminiClient } from "./GeminiClient";
2
+ export { textGeneration } from "./TextGeneration";
3
+ export { structuredText } from "./StructuredText";
4
+ export { streaming } from "./Streaming";
5
+ export { geminiProvider, GeminiProvider } from "./GeminiProvider";
6
+ export { BaseGeminiService, type BaseRequestOptions } from "./BaseService";
@@ -1,9 +1,3 @@
1
- /**
2
- * Utility Functions - Internal Use Only
3
- * These are internal implementation details and should not be used directly by consumers
4
- */
5
-
6
- // Error handling (internal)
7
1
  export {
8
2
  mapGeminiError,
9
3
  isGeminiErrorRetryable,
@@ -11,14 +5,15 @@ export {
11
5
  createGeminiError
12
6
  } from "./error-mapper.util";
13
7
 
14
- // Data transformation (internal)
15
8
  export { extractTextFromResponse } from "./gemini-data-transformer.util";
9
+
16
10
  export {
17
11
  cleanJsonText,
18
12
  parseJsonResponse,
19
13
  safeParseJson,
20
14
  extractJsonFromText
21
15
  } from "./json-parser.util";
16
+
22
17
  export {
23
18
  toSdkContent,
24
19
  createTextContent,
@@ -27,18 +22,17 @@ export {
27
22
  extractTextFromParts
28
23
  } from "./content-mapper.util";
29
24
 
30
- // Validation (internal)
31
25
  export {
32
26
  validateModelName,
33
27
  validateApiKey,
34
28
  validateSchema,
35
29
  validatePrompt,
36
- validateTimeout,
37
- isValidObject,
38
- validateRequiredFields
39
- } from "./validation.util";
30
+ validateOrThrow,
31
+ validators,
32
+ compose,
33
+ type ValidationRule,
34
+ } from "./validation";
40
35
 
41
- // Async state management (internal)
42
36
  export {
43
37
  executeWithState,
44
38
  type AsyncStateCallbacks,
@@ -1,6 +1,5 @@
1
1
  /**
2
- * Validation Composers
3
- * Composable validation rules for clean, reusable validation
2
+ * Validation utilities
4
3
  */
5
4
 
6
5
  export type ValidationRule<T = unknown> = (value: T) => string | null;
@@ -158,3 +157,19 @@ export const validators = {
158
157
 
159
158
  schema: isValidSchema(),
160
159
  };
160
+
161
+ export function validateModelName(modelName: string): void {
162
+ validateOrThrow(modelName, validators.modelName);
163
+ }
164
+
165
+ export function validateApiKey(apiKey: string): void {
166
+ validateOrThrow(apiKey, validators.apiKey);
167
+ }
168
+
169
+ export function validateSchema(schema: Record<string, unknown>): void {
170
+ validateOrThrow(schema, validators.schema);
171
+ }
172
+
173
+ export function validatePrompt(prompt: string): void {
174
+ validateOrThrow(prompt, validators.prompt);
175
+ }
@@ -1,11 +1,2 @@
1
- /**
2
- * React Hooks - Public API
3
- */
4
-
5
- // Internal - not exported from main index
6
- export { useOperationManager } from "./use-operation-manager";
7
- export type { OperationManager } from "./use-operation-manager";
8
-
9
- // Public API
10
- export { useGemini } from "./use-gemini";
11
- export type { UseGeminiOptions, UseGeminiReturn } from "./use-gemini";
1
+ export { useOperationManager, type OperationManager } from "./useOperationManager";
2
+ export { useGemini, type UseGeminiOptions, type UseGeminiReturn } from "./useGemini";
@@ -1,10 +1,10 @@
1
1
  import { useState, useCallback, useMemo } from "react";
2
2
  import type { GeminiGenerationConfig } from "../../domain/entities";
3
3
  import { DEFAULT_MODELS } from "../../domain/entities";
4
- import { geminiTextGenerationService, geminiStructuredTextService } from "../../infrastructure/services";
4
+ import { textGeneration, structuredText } from "../../infrastructure/services";
5
5
  import { executeWithState, type AsyncStateSetters } from "../../infrastructure/utils/async";
6
6
  import { parseJsonResponse } from "../../infrastructure/utils/json-parser.util";
7
- import { useOperationManager } from "./use-operation-manager";
7
+ import { useOperationManager } from "./useOperationManager";
8
8
 
9
9
  export interface UseGeminiOptions {
10
10
  model?: string;
@@ -55,7 +55,7 @@ export function useGemini(options: UseGeminiOptions = {}): UseGeminiReturn {
55
55
  setters,
56
56
  callbacks,
57
57
  async () => {
58
- return geminiTextGenerationService.generateText(
58
+ return textGeneration.generateText(
59
59
  model,
60
60
  prompt,
61
61
  options.generationConfig,
@@ -95,7 +95,7 @@ export function useGemini(options: UseGeminiOptions = {}): UseGeminiReturn {
95
95
  jsonCallbacks,
96
96
  async () => {
97
97
  if (schema) {
98
- return geminiStructuredTextService.generateStructuredText<T>(
98
+ return structuredText.generateStructuredText<T>(
99
99
  model,
100
100
  prompt,
101
101
  schema,
@@ -104,7 +104,7 @@ export function useGemini(options: UseGeminiOptions = {}): UseGeminiReturn {
104
104
  );
105
105
  }
106
106
 
107
- const text = await geminiTextGenerationService.generateText(
107
+ const text = await textGeneration.generateText(
108
108
  model,
109
109
  prompt,
110
110
  { ...options.generationConfig, responseMimeType: "application/json" },
@@ -1,4 +1,4 @@
1
- import { geminiClientCoreService } from "../infrastructure/services/gemini-client-core.service";
1
+ import { geminiClient } from "../infrastructure/services/GeminiClient";
2
2
  import { ConfigBuilder, type ProviderConfig } from "./ConfigBuilder";
3
3
 
4
4
  // Re-export for public API
@@ -40,7 +40,7 @@ class ProviderFactory {
40
40
 
41
41
  // Initialize Gemini client
42
42
  const geminiConfig = this.builder.toGeminiConfig();
43
- geminiClientCoreService.initialize(geminiConfig);
43
+ geminiClient.initialize(geminiConfig);
44
44
  }
45
45
 
46
46
  /**
@@ -1,62 +0,0 @@
1
-
2
- import type { GeminiConfig } from "../../domain/entities";
3
- import { geminiClientCoreService } from "./gemini-client-core.service";
4
- import { geminiStructuredTextService } from "./gemini-structured-text.service";
5
- import { validatePrompt } from "../utils/validation.util";
6
-
7
- export type GeminiProviderConfig = GeminiConfig;
8
-
9
- export class GeminiProvider {
10
- readonly providerId = "gemini";
11
- readonly providerName = "Google Gemini";
12
-
13
- /**
14
- * Initialize the Gemini provider
15
- *
16
- * @throws {Error} If already initialized or configuration is invalid
17
- */
18
- initialize(config: GeminiProviderConfig): void {
19
- if (geminiClientCoreService.isInitialized()) {
20
- throw new Error("Provider already initialized. Call reset() before re-initializing with new config.");
21
- }
22
- geminiClientCoreService.initialize(config);
23
- }
24
-
25
- /**
26
- * Check if provider is initialized
27
- */
28
- isInitialized(): boolean {
29
- return geminiClientCoreService.isInitialized();
30
- }
31
-
32
- /**
33
- * Reset the provider to uninitialized state
34
- */
35
- reset(): void {
36
- geminiClientCoreService.reset();
37
- }
38
-
39
- /**
40
- * Generate structured JSON response
41
- *
42
- * @throws {GeminiError} For API-specific errors
43
- * @throws {Error} For validation or network errors
44
- */
45
- async generateStructuredText<T>(
46
- prompt: string,
47
- schema: Record<string, unknown>,
48
- model: string,
49
- ): Promise<T> {
50
- // Validate inputs
51
- validatePrompt(prompt);
52
-
53
- // Check if initialized
54
- if (!this.isInitialized()) {
55
- throw new Error("Provider not initialized. Call initialize() first.");
56
- }
57
-
58
- return geminiStructuredTextService.generateStructuredText<T>(model, prompt, schema);
59
- }
60
- }
61
-
62
- export const geminiProviderService = new GeminiProvider();
@@ -1,73 +0,0 @@
1
- /**
2
- * Validation Utilities (Legacy)
3
- * Maintained for backward compatibility
4
- * New code should use validation-composer.util.ts
5
- */
6
-
7
- import { validateOrThrow, validators } from "./validation-composer.util";
8
-
9
- /**
10
- * Validate model name format
11
- * @throws Error if model name is invalid
12
- */
13
- export function validateModelName(modelName: string): void {
14
- validateOrThrow(modelName, validators.modelName);
15
- }
16
-
17
- /**
18
- * Validate API key format
19
- * @throws Error if API key is invalid
20
- */
21
- export function validateApiKey(apiKey: string): void {
22
- validateOrThrow(apiKey, validators.apiKey);
23
- }
24
-
25
- /**
26
- * Validate schema object for structured generation
27
- * @throws Error if schema is invalid
28
- */
29
- export function validateSchema(schema: Record<string, unknown>): void {
30
- validateOrThrow(schema, validators.schema);
31
- }
32
-
33
- /**
34
- * Validate prompt text
35
- * @throws Error if prompt is invalid
36
- */
37
- export function validatePrompt(prompt: string): void {
38
- validateOrThrow(prompt, validators.prompt);
39
- }
40
-
41
- /**
42
- * Validate timeout value
43
- * @throws Error if timeout is invalid
44
- */
45
- export function validateTimeout(timeout: number): void {
46
- validateOrThrow(timeout, validators.timeout);
47
- }
48
-
49
- /**
50
- * Check if a value is a valid object
51
- */
52
- export function isValidObject(value: unknown): value is Record<string, unknown> {
53
- return (
54
- value !== null &&
55
- typeof value === "object" &&
56
- !Array.isArray(value) &&
57
- Object.keys(value).length > 0
58
- );
59
- }
60
-
61
- /**
62
- * Validate required fields in an object
63
- */
64
- export function validateRequiredFields(
65
- obj: Record<string, unknown>,
66
- requiredFields: string[]
67
- ): void {
68
- const missing = requiredFields.filter((field) => !(field in obj) || obj[field] === undefined);
69
-
70
- if (missing.length > 0) {
71
- throw new Error(`Missing required fields: ${missing.join(", ")}`);
72
- }
73
- }