@umituz/react-native-ai-fal-provider 3.2.51 → 3.2.53

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 (27) hide show
  1. package/package.json +1 -4
  2. package/src/domain/services/ErrorClassificationService.ts +201 -0
  3. package/src/domain/services/ImageProcessingService.ts +89 -0
  4. package/src/domain/services/PricingService.ts +101 -0
  5. package/src/domain/services/ValidationService.ts +132 -0
  6. package/src/domain/services/index.ts +13 -0
  7. package/src/index.ts +24 -22
  8. package/src/infrastructure/utils/fal-error-handler.util.ts +14 -146
  9. package/src/infrastructure/utils/fal-storage.util.ts +2 -3
  10. package/src/infrastructure/utils/helpers/index.ts +2 -4
  11. package/src/infrastructure/utils/image-helpers.util.ts +13 -27
  12. package/src/infrastructure/utils/input-preprocessor.util.ts +6 -12
  13. package/src/infrastructure/utils/input-validator.util.ts +17 -156
  14. package/src/infrastructure/utils/pricing/fal-pricing.util.ts +26 -53
  15. package/src/infrastructure/utils/type-guards/index.ts +2 -2
  16. package/src/shared/helpers.ts +149 -0
  17. package/src/shared/index.ts +8 -0
  18. package/src/shared/type-guards.ts +122 -0
  19. package/src/shared/validators.ts +281 -0
  20. package/src/infrastructure/utils/helpers/calculation-helpers.util.ts +0 -168
  21. package/src/infrastructure/utils/helpers/error-helpers.util.ts +0 -65
  22. package/src/infrastructure/utils/helpers/object-helpers.util.ts +0 -44
  23. package/src/infrastructure/utils/helpers/timing-helpers.util.ts +0 -11
  24. package/src/infrastructure/utils/type-guards/model-type-guards.util.ts +0 -56
  25. package/src/infrastructure/utils/type-guards/validation-guards.util.ts +0 -101
  26. package/src/infrastructure/utils/validators/data-uri-validator.util.ts +0 -91
  27. package/src/infrastructure/utils/validators/string-validator.util.ts +0 -64
@@ -1,168 +0,0 @@
1
- /**
2
- * Calculation Helper Utilities
3
- * Centralized calculation functions for consistent metrics across the codebase
4
- */
5
-
6
- /**
7
- * Calculate elapsed time in milliseconds from a start timestamp
8
- *
9
- * @param startTime - Start timestamp in milliseconds (from Date.now())
10
- * @returns Elapsed time in milliseconds
11
- *
12
- * @example
13
- * ```typescript
14
- * const start = Date.now();
15
- * // ... do work ...
16
- * const elapsed = getElapsedTime(start); // e.g., 1234
17
- * ```
18
- */
19
- export function getElapsedTime(startTime: number): number {
20
- return Date.now() - startTime;
21
- }
22
-
23
- /**
24
- * Format elapsed time in milliseconds to human-readable string
25
- *
26
- * @param elapsedMs - Elapsed time in milliseconds
27
- * @returns Formatted string (e.g., "1234ms", "1.2s")
28
- *
29
- * @example
30
- * ```typescript
31
- * formatDuration(1234); // "1234ms"
32
- * formatDuration(1200); // "1.2s"
33
- * formatDuration(1500); // "1.5s"
34
- * ```
35
- */
36
- export function formatDuration(elapsedMs: number): string {
37
- if (elapsedMs < 1000) {
38
- return `${Math.round(elapsedMs)}ms`;
39
- }
40
- return `${(elapsedMs / 1000).toFixed(1)}s`;
41
- }
42
-
43
- /**
44
- * Convert bytes to kilobytes (KB)
45
- *
46
- * @param bytes - Size in bytes
47
- * @returns Size in kilobytes (rounded)
48
- *
49
- * @example
50
- * ```typescript
51
- * bytesToKB(5000); // 5
52
- * bytesToKB(1536); // 2
53
- * ```
54
- */
55
- export function bytesToKB(bytes: number): number {
56
- return Math.round(bytes / 1024);
57
- }
58
-
59
- /**
60
- * Calculate actual file size from base64 string
61
- * Base64 encoding inflates size by ~33%, so actual size is ~75% of base64 length
62
- *
63
- * @param base64String - Base64 encoded string
64
- * @returns Actual size in kilobytes (rounded)
65
- *
66
- * @example
67
- * ```typescript
68
- * getActualSizeKB("data:image/png;base64,iVBOR..."); // ~3KB for 4KB base64
69
- * ```
70
- */
71
- export function getActualSizeKB(base64String: string): number {
72
- const base64SizeKB = Math.round(base64String.length / 1024);
73
- // Base64 inflates by ~33%, so actual size is ~75%
74
- return Math.round(base64SizeKB * 0.75);
75
- }
76
-
77
- /**
78
- * Calculate base64 size in KB (before inflation adjustment)
79
- *
80
- * @param base64String - Base64 encoded string
81
- * @returns Size in kilobytes (rounded)
82
- *
83
- * @example
84
- * ```typescript
85
- * getBase64SizeKB("data:image/png;base64,iVBOR..."); // 4
86
- * ```
87
- */
88
- export function getBase64SizeKB(base64String: string): number {
89
- return Math.round(base64String.length / 1024);
90
- }
91
-
92
- /**
93
- * Calculate success rate as percentage
94
- *
95
- * @param successCount - Number of successful operations
96
- * @param totalCount - Total number of operations
97
- * @returns Success rate as percentage (0-100)
98
- *
99
- * @example
100
- * ```typescript
101
- * getSuccessRate(8, 10); // 80
102
- * getSuccessRate(5, 5); // 100
103
- * getSuccessRate(0, 10); // 0
104
- * ```
105
- */
106
- export function getSuccessRate(successCount: number, totalCount: number): number {
107
- if (totalCount === 0) return 0;
108
- return Math.round((successCount / totalCount) * 100);
109
- }
110
-
111
- /**
112
- * Format bytes to human-readable size
113
- *
114
- * @param bytes - Size in bytes
115
- * @returns Formatted string (e.g., "1.5KB", "2.3MB")
116
- *
117
- * @example
118
- * ```typescript
119
- * formatBytes(1536); // "1.5KB"
120
- * formatBytes(2048000); // "2.0MB"
121
- * formatBytes(500); // "500B"
122
- * ```
123
- */
124
- export function formatBytes(bytes: number): string {
125
- if (bytes < 1024) return `${bytes}B`;
126
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
127
- return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
128
- }
129
-
130
- /**
131
- * Calculate retry count suffix for logging
132
- *
133
- * @param attempt - Current attempt number (0-indexed)
134
- * @param totalAttempts - Total number of attempts
135
- * @returns Formatted suffix string
136
- *
137
- * @example
138
- * ```typescript
139
- * getRetrySuffix(1, 2); // " (succeeded on retry 1)"
140
- * getRetrySuffix(0, 1); // ""
141
- * ```
142
- */
143
- export function getRetrySuffix(attempt: number, _totalAttempts: number): string {
144
- if (attempt > 0) {
145
- return ` (succeeded on retry ${attempt})`;
146
- }
147
- return "";
148
- }
149
-
150
- /**
151
- * Calculate failure info string for logging
152
- *
153
- * @param attempt - Current attempt number (0-indexed)
154
- * @param totalAttempts - Total number of attempts
155
- * @returns Formatted failure info string
156
- *
157
- * @example
158
- * ```typescript
159
- * getFailureInfo(1, 2); // " after 2 attempts"
160
- * getFailureInfo(0, 1); // ""
161
- * ```
162
- */
163
- export function getFailureInfo(attempt: number, _totalAttempts: number): string {
164
- if (attempt > 0) {
165
- return ` after ${attempt + 1} attempts`;
166
- }
167
- return "";
168
- }
@@ -1,65 +0,0 @@
1
- /**
2
- * Error Helper Utilities
3
- * Centralized error message extraction and formatting
4
- *
5
- * This utility eliminates the repeated pattern:
6
- * `error instanceof Error ? error.message : String(error)`
7
- * which appeared 8 times across 6 files in the codebase.
8
- */
9
-
10
- /**
11
- * Extract error message from any error type
12
- * Handles Error instances, strings, and unknown types
13
- *
14
- * @param error - The error to extract message from
15
- * @returns The error message as a string
16
- *
17
- * @example
18
- * ```typescript
19
- * try {
20
- * await riskyOperation();
21
- * } catch (error) {
22
- * console.error('Operation failed:', getErrorMessage(error));
23
- * }
24
- * ```
25
- */
26
- export function getErrorMessage(error: unknown): string {
27
- return error instanceof Error ? error.message : String(error);
28
- }
29
-
30
- /**
31
- * Extract error message with fallback
32
- * Returns fallback if error message is empty or whitespace-only
33
- *
34
- * @param error - The error to extract message from
35
- * @param fallback - Fallback message if error message is empty
36
- * @returns The error message or fallback
37
- *
38
- * @example
39
- * ```typescript
40
- * const message = getErrorMessageOr(error, 'An unknown error occurred');
41
- * ```
42
- */
43
- export function getErrorMessageOr(error: unknown, fallback: string): string {
44
- const message = getErrorMessage(error);
45
- return message && message.trim().length > 0 ? message : fallback;
46
- }
47
-
48
- /**
49
- * Create error message with context prefix
50
- * Useful for adding operation context to error messages
51
- *
52
- * @param error - The error to extract message from
53
- * @param context - Context to prepend to the error message
54
- * @returns Formatted error message with context
55
- *
56
- * @example
57
- * ```typescript
58
- * throw new Error(formatErrorMessage(error, 'Failed to upload image'));
59
- * // Output: "Failed to upload image: Network timeout"
60
- * ```
61
- */
62
- export function formatErrorMessage(error: unknown, context: string): string {
63
- return `${context}: ${getErrorMessage(error)}`;
64
- }
65
-
@@ -1,44 +0,0 @@
1
- /**
2
- * Object Helper Utilities
3
- * Object manipulation and validation helpers
4
- */
5
-
6
- /**
7
- * Build error message with context
8
- */
9
- export function buildErrorMessage(
10
- type: string,
11
- context: Record<string, unknown>
12
- ): string {
13
- const contextStr = Object.entries(context)
14
- .map(([key, value]) => `${key}=${JSON.stringify(value)}`)
15
- .join(", ");
16
- return `${type}${contextStr ? ` (${contextStr})` : ""}`;
17
- }
18
-
19
- /**
20
- * Check if value is defined (not null or undefined)
21
- */
22
- export function isDefined<T>(value: T | null | undefined): value is T {
23
- return value !== null && value !== undefined;
24
- }
25
-
26
- /**
27
- * Filter out null and undefined values from object
28
- */
29
- export function removeNullish<T extends Record<string, unknown>>(
30
- obj: T
31
- ): Partial<T> {
32
- return Object.fromEntries(
33
- Object.entries(obj).filter(([_, value]) => isDefined(value))
34
- ) as Partial<T>;
35
- }
36
-
37
- /**
38
- * Generate unique ID
39
- */
40
- export function generateUniqueId(prefix: string = ""): string {
41
- const timestamp = Date.now().toString(36);
42
- const randomStr = Math.random().toString(36).substring(2, 9);
43
- return prefix ? `${prefix}_${timestamp}${randomStr}` : `${timestamp}${randomStr}`;
44
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Timing Helper Utilities
3
- * Sleep utility for async delays
4
- */
5
-
6
- /**
7
- * Sleep for specified milliseconds
8
- */
9
- export function sleep(ms: number): Promise<void> {
10
- return new Promise((resolve) => setTimeout(resolve, ms));
11
- }
@@ -1,56 +0,0 @@
1
- /**
2
- * Model Type Guards
3
- * Runtime type checking for model types
4
- */
5
-
6
- import type { FalModelType } from "../../../domain/entities/fal.types";
7
- import type { ModelType } from "../../../domain/types/model-selection.types";
8
- import { FalErrorType } from "../../../domain/entities/error.types";
9
-
10
- /**
11
- * Check if a string is a valid FalModelType
12
- */
13
- export function isFalModelType(value: unknown): value is FalModelType {
14
- const validTypes: ReadonlyArray<FalModelType> = [
15
- "text-to-image",
16
- "text-to-video",
17
- "text-to-voice",
18
- "image-to-video",
19
- "image-to-image",
20
- "text-to-text",
21
- ];
22
- return typeof value === "string" && validTypes.includes(value as FalModelType);
23
- }
24
-
25
- /**
26
- * Check if a string is a valid ModelType
27
- */
28
- export function isModelType(value: unknown): value is ModelType {
29
- const validTypes: ReadonlyArray<ModelType> = [
30
- "text-to-image",
31
- "text-to-video",
32
- "image-to-video",
33
- "text-to-voice",
34
- ];
35
- return typeof value === "string" && validTypes.includes(value as ModelType);
36
- }
37
-
38
- /**
39
- * Check if error is a FalErrorType
40
- */
41
- export function isFalErrorType(value: unknown): value is FalErrorType {
42
- const validTypes: ReadonlyArray<FalErrorType> = [
43
- FalErrorType.NETWORK,
44
- FalErrorType.TIMEOUT,
45
- FalErrorType.API_ERROR,
46
- FalErrorType.VALIDATION,
47
- FalErrorType.IMAGE_TOO_SMALL,
48
- FalErrorType.CONTENT_POLICY,
49
- FalErrorType.RATE_LIMIT,
50
- FalErrorType.AUTHENTICATION,
51
- FalErrorType.QUOTA_EXCEEDED,
52
- FalErrorType.MODEL_NOT_FOUND,
53
- FalErrorType.UNKNOWN,
54
- ];
55
- return typeof value === "string" && validTypes.includes(value as FalErrorType);
56
- }
@@ -1,101 +0,0 @@
1
- /**
2
- * Validation Guards
3
- * Runtime validation for values and formats
4
- */
5
-
6
- import {
7
- MIN_BASE64_IMAGE_LENGTH,
8
- MIN_MODEL_ID_LENGTH,
9
- MAX_PROMPT_LENGTH,
10
- MAX_TIMEOUT_MS,
11
- MAX_RETRY_COUNT,
12
- } from './constants';
13
- import { isNonEmptyString } from '../validators/string-validator.util';
14
-
15
- /**
16
- * Validate base64 image string
17
- */
18
- export function isValidBase64Image(value: unknown): boolean {
19
- if (typeof value !== "string") {
20
- return false;
21
- }
22
-
23
- // Check data URI prefix - use direct check instead of type guard to avoid type narrowing issues
24
- if (value.startsWith("data:image/")) {
25
- const parts = value.split("base64,");
26
- // Ensure split produced at least 2 parts and the second part exists
27
- if (parts.length < 2) return false;
28
- const base64Part = parts[1];
29
- if (!base64Part) return false;
30
- return base64Part.length >= MIN_BASE64_IMAGE_LENGTH;
31
- }
32
-
33
- // Check if it's a valid base64 string with minimum length
34
- const base64Pattern = /^[A-Za-z0-9+/]+=*$/;
35
- return base64Pattern.test(value) && value.length >= MIN_BASE64_IMAGE_LENGTH;
36
- }
37
-
38
- /**
39
- * Validate API key format
40
- */
41
- export function isValidApiKey(value: unknown): boolean {
42
- return typeof value === "string" && value.length > 0;
43
- }
44
-
45
- /**
46
- * Validate model ID format
47
- * Pattern: org/model or org/model/sub1/sub2/... (multiple path segments)
48
- * Allows dots for versions (e.g., v1.5) but prevents path traversal (..)
49
- * Examples:
50
- * - xai/grok-imagine-video/text-to-video
51
- * - fal-ai/minimax/hailuo-02/standard/image-to-video
52
- */
53
- const MODEL_ID_PATTERN = /^[a-zA-Z0-9-_]+\/[a-zA-Z0-9-_.]+(\/[a-zA-Z0-9-_.]+)*$/;
54
-
55
- export function isValidModelId(value: unknown): boolean {
56
- if (typeof value !== "string") {
57
- return false;
58
- }
59
-
60
- // Prevent path traversal attacks
61
- if (value.includes('..')) {
62
- return false;
63
- }
64
-
65
- // Ensure it doesn't start or end with dots
66
- if (value.startsWith('.') || value.endsWith('.')) {
67
- return false;
68
- }
69
-
70
- return MODEL_ID_PATTERN.test(value) && value.length >= MIN_MODEL_ID_LENGTH;
71
- }
72
-
73
- /**
74
- * Validate prompt string
75
- */
76
- export function isValidPrompt(value: unknown): boolean {
77
- // Use type guard first, then check length
78
- if (!isNonEmptyString(value)) return false;
79
- return value.length <= MAX_PROMPT_LENGTH;
80
- }
81
-
82
- /**
83
- * Validate timeout value
84
- */
85
- export function isValidTimeout(value: unknown): boolean {
86
- return typeof value === "number" && !isNaN(value) && isFinite(value) && value > 0 && value <= MAX_TIMEOUT_MS;
87
- }
88
-
89
- /**
90
- * Validate retry count
91
- */
92
- export function isValidRetryCount(value: unknown): boolean {
93
- return (
94
- typeof value === "number" &&
95
- !isNaN(value) &&
96
- isFinite(value) &&
97
- Number.isInteger(value) &&
98
- value >= 0 &&
99
- value <= MAX_RETRY_COUNT
100
- );
101
- }
@@ -1,91 +0,0 @@
1
- /**
2
- * Data URI Validation Utilities
3
- * Centralized data URI format checking and validation
4
- *
5
- * Eliminates the duplicated pattern:
6
- * `value.startsWith("data:image/")`
7
- * which appeared in 4 different files.
8
- */
9
-
10
- /**
11
- * Check if value is a data URI (any type)
12
- *
13
- * @param value - Value to check
14
- * @returns Type guard indicating if the value is a data URI string
15
- *
16
- * @example
17
- * ```typescript
18
- * isDataUri("data:text/plain;base64,SGVsbG8="); // true
19
- * isDataUri("https://example.com/image.png"); // false
20
- * ```
21
- */
22
- export function isDataUri(value: unknown): value is string {
23
- return typeof value === "string" && value.startsWith("data:");
24
- }
25
-
26
- /**
27
- * Check if value is an image data URI
28
- *
29
- * @param value - Value to check
30
- * @returns Type guard indicating if the value is an image data URI string
31
- *
32
- * @example
33
- * ```typescript
34
- * isImageDataUri("data:image/png;base64,iVBOR..."); // true
35
- * isImageDataUri("data:text/plain;base64,SGVsbG8="); // false
36
- * isImageDataUri("https://example.com/image.png"); // false
37
- * ```
38
- */
39
- export function isImageDataUri(value: unknown): value is string {
40
- return typeof value === "string" && value.startsWith("data:image/");
41
- }
42
-
43
- /**
44
- * Check if value is a base64-encoded data URI
45
- *
46
- * @param value - Value to check
47
- * @returns Type guard indicating if the value contains base64 encoding
48
- *
49
- * @example
50
- * ```typescript
51
- * isBase64DataUri("data:image/png;base64,iVBOR..."); // true
52
- * isBase64DataUri("data:image/svg+xml,<svg>...</svg>"); // false
53
- * ```
54
- */
55
- export function isBase64DataUri(value: unknown): value is string {
56
- return isDataUri(value) && value.includes("base64,");
57
- }
58
-
59
- /**
60
- * Extract MIME type from data URI
61
- *
62
- * @param dataUri - Data URI string
63
- * @returns MIME type or null if not found
64
- *
65
- * @example
66
- * ```typescript
67
- * extractMimeType("data:image/png;base64,iVBOR..."); // "image/png"
68
- * extractMimeType("data:text/plain;charset=utf-8,Hello"); // "text/plain"
69
- * ```
70
- */
71
- export function extractMimeType(dataUri: string): string | null {
72
- const match = dataUri.match(/^data:([^;,]+)/);
73
- return match ? match[1] : null;
74
- }
75
-
76
- /**
77
- * Extract base64 content from data URI
78
- *
79
- * @param dataUri - Data URI string
80
- * @returns Base64 content or null if not base64-encoded
81
- *
82
- * @example
83
- * ```typescript
84
- * extractBase64Content("data:image/png;base64,iVBOR..."); // "iVBOR..."
85
- * extractBase64Content("data:text/plain,Hello"); // null
86
- * ```
87
- */
88
- export function extractBase64Content(dataUri: string): string | null {
89
- const parts = dataUri.split("base64,");
90
- return parts.length === 2 ? parts[1] : null;
91
- }
@@ -1,64 +0,0 @@
1
- /**
2
- * String Validation Utilities
3
- * Common string validation patterns
4
- *
5
- * Eliminates the duplicated pattern:
6
- * `value.trim().length === 0`
7
- * which appeared in 3+ files.
8
- */
9
-
10
- /**
11
- * Check if string is empty or whitespace-only
12
- *
13
- * @param value - Value to check
14
- * @returns True if the value is an empty string or contains only whitespace
15
- *
16
- * @example
17
- * ```typescript
18
- * isEmptyString(""); // true
19
- * isEmptyString(" "); // true
20
- * isEmptyString("Hello"); // false
21
- * isEmptyString(null); // false
22
- * ```
23
- */
24
- export function isEmptyString(value: unknown): boolean {
25
- return typeof value === "string" && value.trim().length === 0;
26
- }
27
-
28
- /**
29
- * Check if value is a non-empty string
30
- * Type guard version for better TypeScript inference
31
- *
32
- * @param value - Value to check
33
- * @returns Type guard indicating if the value is a non-empty string
34
- *
35
- * @example
36
- * ```typescript
37
- * if (isNonEmptyString(input)) {
38
- * // TypeScript knows input is a string here
39
- * console.log(input.toUpperCase());
40
- * }
41
- * ```
42
- */
43
- export function isNonEmptyString(value: unknown): value is string {
44
- return typeof value === "string" && value.trim().length > 0;
45
- }
46
-
47
- /**
48
- * Check if value is a string (empty or non-empty)
49
- * Basic type guard for string validation
50
- *
51
- * @param value - Value to check
52
- * @returns Type guard indicating if the value is a string
53
- *
54
- * @example
55
- * ```typescript
56
- * if (isString(value)) {
57
- * // TypeScript knows value is a string here
58
- * console.log(value.length);
59
- * }
60
- * ```
61
- */
62
- export function isString(value: unknown): value is string {
63
- return typeof value === "string";
64
- }