@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.
- package/package.json +1 -4
- package/src/domain/services/ErrorClassificationService.ts +201 -0
- package/src/domain/services/ImageProcessingService.ts +89 -0
- package/src/domain/services/PricingService.ts +101 -0
- package/src/domain/services/ValidationService.ts +132 -0
- package/src/domain/services/index.ts +13 -0
- package/src/index.ts +24 -22
- package/src/infrastructure/utils/fal-error-handler.util.ts +14 -146
- package/src/infrastructure/utils/fal-storage.util.ts +2 -3
- package/src/infrastructure/utils/helpers/index.ts +2 -4
- package/src/infrastructure/utils/image-helpers.util.ts +13 -27
- package/src/infrastructure/utils/input-preprocessor.util.ts +6 -12
- package/src/infrastructure/utils/input-validator.util.ts +17 -156
- package/src/infrastructure/utils/pricing/fal-pricing.util.ts +26 -53
- package/src/infrastructure/utils/type-guards/index.ts +2 -2
- package/src/shared/helpers.ts +149 -0
- package/src/shared/index.ts +8 -0
- package/src/shared/type-guards.ts +122 -0
- package/src/shared/validators.ts +281 -0
- package/src/infrastructure/utils/helpers/calculation-helpers.util.ts +0 -168
- package/src/infrastructure/utils/helpers/error-helpers.util.ts +0 -65
- package/src/infrastructure/utils/helpers/object-helpers.util.ts +0 -44
- package/src/infrastructure/utils/helpers/timing-helpers.util.ts +0 -11
- package/src/infrastructure/utils/type-guards/model-type-guards.util.ts +0 -56
- package/src/infrastructure/utils/type-guards/validation-guards.util.ts +0 -101
- package/src/infrastructure/utils/validators/data-uri-validator.util.ts +0 -91
- 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,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
|
-
}
|