@umituz/react-native-ai-generation-content 1.65.0 → 1.65.2
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 -1
- package/src/domain/constants/processing-modes-catalog.constants.ts +97 -0
- package/src/domain/constants/processing-modes-filters.ts +34 -0
- package/src/domain/constants/processing-modes-getters.ts +20 -0
- package/src/domain/constants/processing-modes.constants.ts +8 -134
- package/src/domain/entities/feature-flow-config.types.ts +17 -0
- package/src/domain/entities/flow-actions.types.ts +26 -0
- package/src/domain/entities/flow-config-data.types.ts +41 -0
- package/src/domain/entities/flow-config.types.ts +17 -169
- package/src/domain/entities/flow-configuration.types.ts +44 -0
- package/src/domain/entities/flow-state.types.ts +30 -0
- package/src/domain/entities/flow-step.types.ts +56 -0
- package/src/domain/entities/scenario-step-config.types.ts +32 -0
- package/src/domain/entities/step-config.types.ts +14 -129
- package/src/domain/entities/step-definition.types.ts +50 -0
- package/src/domain/entities/step-input-config.types.ts +36 -0
- package/src/domain/entities/step-upload-config.types.ts +17 -0
- package/src/domain/interfaces/ai-provider-capabilities.types.ts +27 -0
- package/src/domain/interfaces/ai-provider-config.types.ts +30 -0
- package/src/domain/interfaces/ai-provider-feature-types.ts +22 -0
- package/src/domain/interfaces/ai-provider-input.types.ts +28 -0
- package/src/domain/interfaces/ai-provider-progress.types.ts +37 -0
- package/src/domain/interfaces/ai-provider-status.types.ts +41 -0
- package/src/domain/interfaces/ai-provider.interface.ts +32 -142
- package/src/domain/types/result-constructors.ts +20 -0
- package/src/domain/types/result-guards.ts +20 -0
- package/src/domain/types/result-transformers.ts +36 -0
- package/src/domain/types/result-type-definitions.ts +27 -0
- package/src/domain/types/result-unwrappers.ts +28 -0
- package/src/domain/types/result.types.ts +11 -100
- package/src/domains/background/infrastructure/utils/polling-interval.util.ts +3 -8
- package/src/domains/background/infrastructure/utils/result-validation-logic.ts +88 -0
- package/src/domains/background/infrastructure/utils/result-validator-constants.ts +18 -0
- package/src/domains/background/infrastructure/utils/result-validator.types.ts +16 -0
- package/src/domains/background/infrastructure/utils/result-validator.util.ts +8 -109
- package/src/domains/background/infrastructure/utils/status-checker.types.ts +11 -0
- package/src/domains/background/infrastructure/utils/status-checker.util.ts +9 -119
- package/src/domains/background/infrastructure/utils/status-error-detector.ts +61 -0
- package/src/domains/background/infrastructure/utils/status-extraction-helpers.ts +25 -0
- package/src/domains/background/infrastructure/utils/status-predicates.ts +37 -0
- package/src/domains/creations/domain-exports.ts +79 -0
- package/src/domains/creations/index.ts +9 -169
- package/src/domains/creations/infrastructure/repositories/creation-create.operations.ts +40 -0
- package/src/domains/creations/infrastructure/repositories/creation-delete.operations.ts +63 -0
- package/src/domains/creations/infrastructure/repositories/creation-update.operations.ts +77 -0
- package/src/domains/creations/infrastructure/repositories/creations-operations.ts +9 -210
- package/src/domains/creations/infrastructure-exports.ts +9 -0
- package/src/domains/creations/presentation-exports.ts +59 -0
- package/src/domains/generation/infrastructure/executors/text-to-image-executor.helpers.ts +81 -0
- package/src/domains/generation/infrastructure/executors/text-to-image-executor.ts +4 -100
- package/src/domains/generation/infrastructure/executors/text-to-image-executor.types.ts +19 -0
- package/src/domains/generation/infrastructure/flow/use-flow-store.types.ts +19 -0
- package/src/domains/generation/infrastructure/flow/useFlowStore.ts +33 -65
- package/src/domains/generation/wizard/domain/entities/wizard-config-builder.ts +75 -0
- package/src/domains/generation/wizard/domain/entities/wizard-feature-config.types.ts +29 -0
- package/src/domains/generation/wizard/domain/entities/wizard-feature.types.ts +9 -114
- package/src/domains/generation/wizard/domain/entities/wizard-presets.constants.ts +23 -0
- package/src/domains/generation/wizard/infrastructure/strategies/shared/unified-prompt-builder.ts +1 -1
- package/src/domains/generation/wizard/infrastructure/utils/creation-persistence-factory.ts +33 -0
- package/src/domains/generation/wizard/infrastructure/utils/creation-persistence.types.ts +22 -0
- package/src/domains/generation/wizard/infrastructure/utils/creation-persistence.util.ts +11 -135
- package/src/domains/generation/wizard/infrastructure/utils/creation-save-operations.ts +48 -0
- package/src/domains/generation/wizard/infrastructure/utils/creation-update-operations.ts +72 -0
- package/src/domains/generation/wizard/presentation/hooks/use-video-queue-generation.types.ts +21 -0
- package/src/domains/generation/wizard/presentation/hooks/useVideoQueueGeneration.ts +14 -35
- package/src/domains/image-to-video/domain/types/image-to-video-callbacks.types.ts +33 -0
- package/src/domains/image-to-video/domain/types/image-to-video-config.types.ts +29 -0
- package/src/domains/image-to-video/domain/types/image-to-video-request.types.ts +31 -0
- package/src/domains/image-to-video/domain/types/image-to-video-result.types.ts +17 -0
- package/src/domains/image-to-video/domain/types/image-to-video-state.types.ts +24 -0
- package/src/domains/image-to-video/domain/types/image-to-video.types.ts +24 -114
- package/src/domains/image-to-video/infrastructure/services/image-to-video-executor.ts +26 -99
- package/src/domains/image-to-video/infrastructure/services/image-to-video-executor.types.ts +15 -0
- package/src/domains/prompts/domain/base/constants.ts +47 -0
- package/src/domains/prompts/domain/base/creators.ts +76 -0
- package/src/domains/prompts/domain/base/types.ts +10 -0
- package/src/domains/prompts/domain/entities/MultiPersonPromptStructure.ts +1 -1
- package/src/domains/prompts/index.ts +4 -2
- package/src/domains/prompts/infrastructure/services/ImagePromptBuilder.ts +2 -72
- package/src/domains/prompts/infrastructure/services/image-prompt-builder.types.ts +17 -0
- package/src/domains/result-preview/presentation/types/result-components.types.ts +47 -0
- package/src/domains/result-preview/presentation/types/result-creation.types.ts +14 -0
- package/src/domains/result-preview/presentation/types/result-data.types.ts +35 -0
- package/src/domains/result-preview/presentation/types/result-hooks.types.ts +35 -0
- package/src/domains/result-preview/presentation/types/result-preview.types.ts +19 -182
- package/src/domains/result-preview/presentation/types/result-screen.types.ts +69 -0
- package/src/domains/text-to-image/domain-exports.ts +50 -0
- package/src/domains/text-to-image/index.ts +11 -102
- package/src/domains/text-to-image/infrastructure-exports.ts +6 -0
- package/src/domains/text-to-image/presentation/hooks/useFormState.ts +39 -24
- package/src/domains/text-to-image/presentation/hooks/useGeneration.ts +5 -3
- package/src/domains/text-to-image/presentation-exports.ts +41 -0
- package/src/domains/text-to-video/domain/types/action-component.types.ts +15 -0
- package/src/domains/text-to-video/domain/types/component.types.ts +16 -103
- package/src/domains/text-to-video/domain/types/content-component.types.ts +30 -0
- package/src/domains/text-to-video/domain/types/panel-component.types.ts +24 -0
- package/src/domains/text-to-video/domain/types/selector-component.types.ts +31 -0
- package/src/domains/text-to-video/domain/types/tab-component.types.ts +26 -0
- package/src/index.ts +0 -10
- package/src/infrastructure/executors/base-executor.ts +40 -112
- package/src/infrastructure/executors/base-executor.types.ts +10 -0
- package/src/infrastructure/http/http-client-methods.ts +73 -0
- package/src/infrastructure/http/http-client.util.ts +8 -163
- package/src/infrastructure/http/http-fetch-handler.ts +53 -0
- package/src/infrastructure/http/http-methods.constants.ts +23 -0
- package/src/infrastructure/http/http-request-executor.ts +49 -0
- package/src/infrastructure/http/http-response-parser.ts +53 -0
- package/src/infrastructure/orchestration/GenerationOrchestrator.ts +8 -43
- package/src/infrastructure/utils/classifier-helpers.ts +36 -0
- package/src/infrastructure/utils/content-validators.ts +92 -0
- package/src/infrastructure/utils/domain-guards.ts +22 -0
- package/src/infrastructure/utils/error-classification.ts +122 -0
- package/src/infrastructure/utils/error-classifier.util.ts +8 -181
- package/src/infrastructure/utils/error-classifiers.ts +49 -0
- package/src/infrastructure/utils/error-extractors.ts +42 -0
- package/src/infrastructure/utils/error-factory.ts +25 -0
- package/src/infrastructure/utils/error-handlers.ts +51 -0
- package/src/infrastructure/utils/error-handling.util.ts +7 -186
- package/src/infrastructure/utils/error-message-extractor.util.ts +10 -172
- package/src/infrastructure/utils/error-retry.ts +44 -0
- package/src/infrastructure/utils/error-types.ts +23 -0
- package/src/infrastructure/utils/extraction-types.ts +37 -0
- package/src/infrastructure/utils/fal-error-checker.ts +44 -0
- package/src/infrastructure/utils/general-validators.ts +64 -0
- package/src/infrastructure/utils/id-validators.ts +39 -0
- package/src/infrastructure/utils/message-extractor.ts +89 -0
- package/src/infrastructure/utils/primitive-guards.ts +66 -0
- package/src/infrastructure/utils/result-polling.ts +39 -0
- package/src/infrastructure/utils/structure-guards.ts +75 -0
- package/src/infrastructure/utils/type-guards.util.ts +22 -149
- package/src/infrastructure/utils/validation-types.ts +8 -0
- package/src/infrastructure/utils/validation.util.ts +14 -184
- package/src/presentation/hooks/ai-feature-callbacks-auth.hooks.ts +43 -0
- package/src/presentation/hooks/ai-feature-callbacks-cost.hooks.ts +56 -0
- package/src/presentation/hooks/ai-feature-callbacks-execution.hooks.ts +66 -0
- package/src/presentation/hooks/ai-feature-callbacks.types.ts +69 -0
- package/src/presentation/hooks/generation/use-image-generation.types.ts +39 -0
- package/src/presentation/hooks/generation/useImageGeneration.ts +33 -99
- package/src/presentation/hooks/generation-flow-navigation.ts +58 -0
- package/src/presentation/hooks/generation-flow-updates.ts +67 -0
- package/src/presentation/hooks/generation-flow.types.ts +32 -0
- package/src/presentation/hooks/useAIFeatureCallbacks.ts +48 -138
- package/src/presentation/hooks/useGenerationFlow.ts +40 -136
- package/src/presentation/types/flow-config.types.ts +9 -140
- package/src/presentation/types/flow-generation-config.types.ts +25 -0
- package/src/presentation/types/flow-state.types.ts +16 -0
- package/src/presentation/types/flow-step-configs.types.ts +48 -0
- package/src/presentation/types/flow-step-data.types.ts +24 -0
- package/src/presentation/types/result-actions.types.ts +50 -0
- package/src/presentation/types/result-config.types.ts +22 -171
- package/src/presentation/types/result-header.types.ts +44 -0
- package/src/presentation/types/result-image.types.ts +29 -0
- package/src/presentation/types/result-layout.types.ts +26 -0
- package/src/presentation/types/result-story.types.ts +42 -0
- package/src/domains/prompts/domain/entities/BasePromptStructure.ts +0 -168
- package/src/exports/domains.ts +0 -149
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Handling Utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getErrorMessage } from "./error-extractors";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Wraps an async function with error handling
|
|
9
|
+
*/
|
|
10
|
+
export async function withErrorHandling<T>(
|
|
11
|
+
operation: () => Promise<T>,
|
|
12
|
+
onError?: (error: Error) => void
|
|
13
|
+
): Promise<{ data?: T; error?: Error }> {
|
|
14
|
+
try {
|
|
15
|
+
const data = await operation();
|
|
16
|
+
return { data };
|
|
17
|
+
} catch (error) {
|
|
18
|
+
const appError = error instanceof Error ? error : new Error(getErrorMessage(error));
|
|
19
|
+
onError?.(appError);
|
|
20
|
+
return { error: appError };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Safely executes a function and returns null on error
|
|
26
|
+
*/
|
|
27
|
+
export function safeExecute<T>(
|
|
28
|
+
operation: () => T,
|
|
29
|
+
fallback: T = null as T
|
|
30
|
+
): T {
|
|
31
|
+
try {
|
|
32
|
+
return operation();
|
|
33
|
+
} catch {
|
|
34
|
+
return fallback;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Logs error with context
|
|
40
|
+
*/
|
|
41
|
+
export function logError(
|
|
42
|
+
error: unknown,
|
|
43
|
+
context?: string
|
|
44
|
+
): void {
|
|
45
|
+
const message = getErrorMessage(error);
|
|
46
|
+
const contextPrefix = context ? `[${context}]` : "";
|
|
47
|
+
|
|
48
|
+
if (typeof console !== "undefined" && console.error) {
|
|
49
|
+
console.error(`${contextPrefix} Error:`, message, error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -1,190 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Centralized Error Handling Utilities
|
|
2
|
+
* Centralized Error Handling Utilities - Barrel Export
|
|
3
3
|
* Provides consistent error handling patterns across the application
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Safely extracts error message from unknown error type
|
|
14
|
-
*/
|
|
15
|
-
export function getErrorMessage(error: unknown): string {
|
|
16
|
-
if (error instanceof Error) {
|
|
17
|
-
return error.message;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (typeof error === "string") {
|
|
21
|
-
return error;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (error && typeof error === "object" && "message" in error) {
|
|
25
|
-
return String(error.message);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return "An unknown error occurred";
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Creates a standardized application error
|
|
33
|
-
*/
|
|
34
|
-
export function createAppError(
|
|
35
|
-
message: string,
|
|
36
|
-
options: {
|
|
37
|
-
code?: string;
|
|
38
|
-
statusCode?: number;
|
|
39
|
-
originalError?: unknown;
|
|
40
|
-
} = {}
|
|
41
|
-
): AppError {
|
|
42
|
-
const error = new Error(message) as AppError;
|
|
43
|
-
error.code = options.code;
|
|
44
|
-
error.statusCode = options.statusCode;
|
|
45
|
-
error.originalError = options.originalError;
|
|
46
|
-
return error;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Wraps an async function with error handling
|
|
51
|
-
*/
|
|
52
|
-
export async function withErrorHandling<T>(
|
|
53
|
-
operation: () => Promise<T>,
|
|
54
|
-
onError?: (error: Error) => void
|
|
55
|
-
): Promise<{ data?: T; error?: Error }> {
|
|
56
|
-
try {
|
|
57
|
-
const data = await operation();
|
|
58
|
-
return { data };
|
|
59
|
-
} catch (error) {
|
|
60
|
-
const appError = error instanceof Error ? error : new Error(getErrorMessage(error));
|
|
61
|
-
onError?.(appError);
|
|
62
|
-
return { error: appError };
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Type guard to check if value is an Error
|
|
68
|
-
*/
|
|
69
|
-
export function isError(value: unknown): value is Error {
|
|
70
|
-
return value instanceof Error;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Type guard to check if value is an AppError
|
|
75
|
-
*/
|
|
76
|
-
export function isAppError(value: unknown): value is AppError {
|
|
77
|
-
return isError(value) && "code" in value;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Safely executes a function and returns null on error
|
|
82
|
-
*/
|
|
83
|
-
export function safeExecute<T>(
|
|
84
|
-
operation: () => T,
|
|
85
|
-
fallback: T = null as T
|
|
86
|
-
): T {
|
|
87
|
-
try {
|
|
88
|
-
return operation();
|
|
89
|
-
} catch {
|
|
90
|
-
return fallback;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Logs error with context
|
|
96
|
-
*/
|
|
97
|
-
export function logError(
|
|
98
|
-
error: unknown,
|
|
99
|
-
context?: string
|
|
100
|
-
): void {
|
|
101
|
-
const message = getErrorMessage(error);
|
|
102
|
-
const contextPrefix = context ? `[${context}]` : "";
|
|
103
|
-
|
|
104
|
-
if (typeof console !== "undefined" && console.error) {
|
|
105
|
-
console.error(`${contextPrefix} Error:`, message, error);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Checks if error is a network error
|
|
111
|
-
*/
|
|
112
|
-
export function isNetworkError(error: unknown): boolean {
|
|
113
|
-
if (!isError(error)) {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const message = error.message.toLowerCase();
|
|
118
|
-
return (
|
|
119
|
-
message.includes("network") ||
|
|
120
|
-
message.includes("fetch") ||
|
|
121
|
-
message.includes("connection") ||
|
|
122
|
-
message.includes("timeout")
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Checks if error is a validation error
|
|
128
|
-
*/
|
|
129
|
-
export function isValidationError(error: unknown): boolean {
|
|
130
|
-
if (isAppError(error)) {
|
|
131
|
-
return error.code?.toLowerCase().includes("validation") || false;
|
|
132
|
-
}
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Checks if error is an authentication error
|
|
138
|
-
*/
|
|
139
|
-
export function isAuthError(error: unknown): boolean {
|
|
140
|
-
if (!isError(error)) {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const message = error.message.toLowerCase();
|
|
145
|
-
return (
|
|
146
|
-
message.includes("unauthorized") ||
|
|
147
|
-
message.includes("authentication") ||
|
|
148
|
-
message.includes("forbidden") ||
|
|
149
|
-
message.includes("token")
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Retry function with exponential backoff
|
|
155
|
-
*/
|
|
156
|
-
export async function retryWithBackoff<T>(
|
|
157
|
-
operation: () => Promise<T>,
|
|
158
|
-
options: {
|
|
159
|
-
maxRetries?: number;
|
|
160
|
-
delayMs?: number;
|
|
161
|
-
backoffMultiplier?: number;
|
|
162
|
-
shouldRetry?: (error: Error) => boolean;
|
|
163
|
-
} = {}
|
|
164
|
-
): Promise<T> {
|
|
165
|
-
const {
|
|
166
|
-
maxRetries = 3,
|
|
167
|
-
delayMs = 1000,
|
|
168
|
-
backoffMultiplier = 2,
|
|
169
|
-
shouldRetry = () => true,
|
|
170
|
-
} = options;
|
|
171
|
-
|
|
172
|
-
let lastError: Error | undefined;
|
|
173
|
-
|
|
174
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
175
|
-
try {
|
|
176
|
-
return await operation();
|
|
177
|
-
} catch (error) {
|
|
178
|
-
lastError = error instanceof Error ? error : new Error(getErrorMessage(error));
|
|
179
|
-
|
|
180
|
-
if (attempt === maxRetries || !shouldRetry(lastError)) {
|
|
181
|
-
throw lastError;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const delay = delayMs * Math.pow(backoffMultiplier, attempt);
|
|
185
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
throw lastError!;
|
|
190
|
-
}
|
|
6
|
+
export type { AppError } from "./error-types";
|
|
7
|
+
export { isError, isAppError } from "./error-types";
|
|
8
|
+
export { getErrorMessage, createAppError } from "./error-extractors";
|
|
9
|
+
export { withErrorHandling, safeExecute, logError } from "./error-handlers";
|
|
10
|
+
export { isNetworkError, isValidationError, isAuthError } from "./error-classifiers";
|
|
11
|
+
export { retryWithBackoff } from "./error-retry";
|
|
@@ -1,176 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Error Message Extractor
|
|
2
|
+
* Error Message Extractor - Barrel Export
|
|
3
3
|
* Extracts error messages from various API error formats
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
readonly input?: string;
|
|
16
|
-
readonly url?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Error types for user-friendly messages
|
|
21
|
-
*/
|
|
22
|
-
export const GenerationErrorType = {
|
|
23
|
-
CONTENT_POLICY: "content_policy",
|
|
24
|
-
VALIDATION: "validation",
|
|
25
|
-
NETWORK: "network",
|
|
26
|
-
TIMEOUT: "timeout",
|
|
27
|
-
RATE_LIMIT: "rate_limit",
|
|
28
|
-
QUOTA_EXCEEDED: "quota_exceeded",
|
|
29
|
-
UNKNOWN: "unknown",
|
|
30
|
-
} as const;
|
|
31
|
-
|
|
32
|
-
export type GenerationErrorTypeValue = typeof GenerationErrorType[keyof typeof GenerationErrorType];
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Structured generation error
|
|
36
|
-
*/
|
|
37
|
-
export interface GenerationError extends Error {
|
|
38
|
-
readonly errorType: GenerationErrorTypeValue;
|
|
39
|
-
readonly translationKey: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Create a structured generation error
|
|
44
|
-
*/
|
|
45
|
-
function createGenerationError(
|
|
46
|
-
type: GenerationErrorTypeValue,
|
|
47
|
-
message: string,
|
|
48
|
-
): GenerationError {
|
|
49
|
-
const error = new Error(message) as GenerationError;
|
|
50
|
-
(error as { errorType: GenerationErrorTypeValue }).errorType = type;
|
|
51
|
-
(error as { translationKey: string }).translationKey = `error.generation.${type}`;
|
|
52
|
-
return error;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Check if result contains a FAL API error response
|
|
57
|
-
* FAL sometimes returns errors with COMPLETED status
|
|
58
|
-
*/
|
|
59
|
-
export function checkFalApiError(result: unknown): void {
|
|
60
|
-
if (!result || typeof result !== "object") return;
|
|
61
|
-
|
|
62
|
-
const resultObj = result as { detail?: FalErrorDetail[] };
|
|
63
|
-
|
|
64
|
-
// FAL API error format: {detail: [{msg, type, loc}]}
|
|
65
|
-
if (Array.isArray(resultObj.detail) && resultObj.detail.length > 0) {
|
|
66
|
-
const firstError = resultObj.detail[0];
|
|
67
|
-
const errorType = firstError?.type || "unknown";
|
|
68
|
-
const errorMsg = firstError?.msg || "Unknown API error";
|
|
69
|
-
|
|
70
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
71
|
-
console.error("[FalApiError] Detected error in result:", {
|
|
72
|
-
type: errorType,
|
|
73
|
-
message: errorMsg,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Throw specific error based on type
|
|
78
|
-
if (errorType === "content_policy_violation") {
|
|
79
|
-
throw createGenerationError(GenerationErrorType.CONTENT_POLICY, errorMsg);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (errorType === "validation_error" || errorType.includes("validation")) {
|
|
83
|
-
throw createGenerationError(GenerationErrorType.VALIDATION, errorMsg);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
throw createGenerationError(GenerationErrorType.UNKNOWN, errorMsg);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Check if error is a GenerationError with translation key
|
|
92
|
-
*/
|
|
93
|
-
export function isGenerationError(error: unknown): error is GenerationError {
|
|
94
|
-
return error instanceof Error && "errorType" in error && "translationKey" in error;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Get translation key from error (returns key if GenerationError, null otherwise)
|
|
99
|
-
*/
|
|
100
|
-
export function getErrorTranslationKey(error: unknown): string | null {
|
|
101
|
-
if (isGenerationError(error)) {
|
|
102
|
-
return error.translationKey;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Check for content policy in error message
|
|
106
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
107
|
-
const lowerMessage = message.toLowerCase();
|
|
108
|
-
|
|
109
|
-
if (lowerMessage.includes("content_policy") || lowerMessage.includes("policy violation")) {
|
|
110
|
-
return `error.generation.${GenerationErrorType.CONTENT_POLICY}`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (lowerMessage.includes("rate limit") || lowerMessage.includes("429")) {
|
|
114
|
-
return `error.generation.${GenerationErrorType.RATE_LIMIT}`;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (lowerMessage.includes("timeout") || lowerMessage.includes("timed out")) {
|
|
118
|
-
return `error.generation.${GenerationErrorType.TIMEOUT}`;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (lowerMessage.includes("network") || lowerMessage.includes("connection")) {
|
|
122
|
-
return `error.generation.${GenerationErrorType.NETWORK}`;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Extract error message from FAL API and other error formats
|
|
130
|
-
* Supports: Error instances, FAL API errors, generic objects
|
|
131
|
-
* Returns translation key if available, otherwise original message
|
|
132
|
-
*/
|
|
133
|
-
export function extractErrorMessage(
|
|
134
|
-
error: unknown,
|
|
135
|
-
defaultMessage = "Processing failed",
|
|
136
|
-
debugPrefix?: string,
|
|
137
|
-
): string {
|
|
138
|
-
// First check if this is a GenerationError with translation key
|
|
139
|
-
const translationKey = getErrorTranslationKey(error);
|
|
140
|
-
if (translationKey) {
|
|
141
|
-
if (typeof __DEV__ !== "undefined" && __DEV__ && debugPrefix) {
|
|
142
|
-
console.error(`[${debugPrefix}] Error (translation key):`, translationKey);
|
|
143
|
-
}
|
|
144
|
-
return translationKey;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
let message = defaultMessage;
|
|
148
|
-
|
|
149
|
-
if (error instanceof Error) {
|
|
150
|
-
message = error.message;
|
|
151
|
-
} else if (typeof error === "object" && error !== null) {
|
|
152
|
-
const errObj = error as Record<string, unknown>;
|
|
153
|
-
|
|
154
|
-
// FAL API error format: {detail: [{msg, type, loc}]}
|
|
155
|
-
if (Array.isArray(errObj.detail) && errObj.detail[0]?.msg) {
|
|
156
|
-
const detailType = errObj.detail[0]?.type;
|
|
157
|
-
// Check for content policy in FAL API response
|
|
158
|
-
if (detailType === "content_policy_violation") {
|
|
159
|
-
return `error.generation.${GenerationErrorType.CONTENT_POLICY}`;
|
|
160
|
-
}
|
|
161
|
-
message = String(errObj.detail[0].msg);
|
|
162
|
-
} else if (errObj.detail) {
|
|
163
|
-
message = JSON.stringify(errObj.detail);
|
|
164
|
-
} else if (errObj.message) {
|
|
165
|
-
message = String(errObj.message);
|
|
166
|
-
} else if (errObj.msg) {
|
|
167
|
-
message = String(errObj.msg);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (typeof __DEV__ !== "undefined" && __DEV__ && debugPrefix) {
|
|
172
|
-
console.error(`[${debugPrefix}] Error:`, message, error);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return message;
|
|
176
|
-
}
|
|
6
|
+
export type {
|
|
7
|
+
FalErrorDetail,
|
|
8
|
+
GenerationErrorTypeValue,
|
|
9
|
+
GenerationError,
|
|
10
|
+
} from "./extraction-types";
|
|
11
|
+
export { GenerationErrorType } from "./extraction-types";
|
|
12
|
+
export { createGenerationError, isGenerationError } from "./error-factory";
|
|
13
|
+
export { checkFalApiError } from "./fal-error-checker";
|
|
14
|
+
export { extractErrorMessage, getErrorTranslationKey } from "./message-extractor";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Retry Utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getErrorMessage } from "./error-extractors";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Retry function with exponential backoff
|
|
9
|
+
*/
|
|
10
|
+
export async function retryWithBackoff<T>(
|
|
11
|
+
operation: () => Promise<T>,
|
|
12
|
+
options: {
|
|
13
|
+
maxRetries?: number;
|
|
14
|
+
delayMs?: number;
|
|
15
|
+
backoffMultiplier?: number;
|
|
16
|
+
shouldRetry?: (error: Error) => boolean;
|
|
17
|
+
} = {}
|
|
18
|
+
): Promise<T> {
|
|
19
|
+
const {
|
|
20
|
+
maxRetries = 3,
|
|
21
|
+
delayMs = 1000,
|
|
22
|
+
backoffMultiplier = 2,
|
|
23
|
+
shouldRetry = () => true,
|
|
24
|
+
} = options;
|
|
25
|
+
|
|
26
|
+
let lastError: Error | undefined;
|
|
27
|
+
|
|
28
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
29
|
+
try {
|
|
30
|
+
return await operation();
|
|
31
|
+
} catch (error) {
|
|
32
|
+
lastError = error instanceof Error ? error : new Error(getErrorMessage(error));
|
|
33
|
+
|
|
34
|
+
if (attempt === maxRetries || !shouldRetry(lastError)) {
|
|
35
|
+
throw lastError;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const delay = delayMs * Math.pow(backoffMultiplier, attempt);
|
|
39
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
throw lastError!;
|
|
44
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Type Definitions and Guards
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface AppError extends Error {
|
|
6
|
+
code?: string;
|
|
7
|
+
statusCode?: number;
|
|
8
|
+
originalError?: unknown;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Type guard to check if value is an Error
|
|
13
|
+
*/
|
|
14
|
+
export function isError(value: unknown): value is Error {
|
|
15
|
+
return value instanceof Error;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Type guard to check if value is an AppError
|
|
20
|
+
*/
|
|
21
|
+
export function isAppError(value: unknown): value is AppError {
|
|
22
|
+
return isError(value) && "code" in value;
|
|
23
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Extraction Type Definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* FAL API error detail item
|
|
7
|
+
*/
|
|
8
|
+
export interface FalErrorDetail {
|
|
9
|
+
readonly msg?: string;
|
|
10
|
+
readonly type?: string;
|
|
11
|
+
readonly loc?: string[];
|
|
12
|
+
readonly input?: string;
|
|
13
|
+
readonly url?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Error types for user-friendly messages
|
|
18
|
+
*/
|
|
19
|
+
export const GenerationErrorType = {
|
|
20
|
+
CONTENT_POLICY: "content_policy",
|
|
21
|
+
VALIDATION: "validation",
|
|
22
|
+
NETWORK: "network",
|
|
23
|
+
TIMEOUT: "timeout",
|
|
24
|
+
RATE_LIMIT: "rate_limit",
|
|
25
|
+
QUOTA_EXCEEDED: "quota_exceeded",
|
|
26
|
+
UNKNOWN: "unknown",
|
|
27
|
+
} as const;
|
|
28
|
+
|
|
29
|
+
export type GenerationErrorTypeValue = typeof GenerationErrorType[keyof typeof GenerationErrorType];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Structured generation error
|
|
33
|
+
*/
|
|
34
|
+
export interface GenerationError extends Error {
|
|
35
|
+
readonly errorType: GenerationErrorTypeValue;
|
|
36
|
+
readonly translationKey: string;
|
|
37
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FAL API Error Checker
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { FalErrorDetail } from "./extraction-types";
|
|
6
|
+
import { GenerationErrorType } from "./extraction-types";
|
|
7
|
+
import { createGenerationError } from "./error-factory";
|
|
8
|
+
|
|
9
|
+
declare const __DEV__: boolean;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Check if result contains a FAL API error response
|
|
13
|
+
* FAL sometimes returns errors with COMPLETED status
|
|
14
|
+
*/
|
|
15
|
+
export function checkFalApiError(result: unknown): void {
|
|
16
|
+
if (!result || typeof result !== "object") return;
|
|
17
|
+
|
|
18
|
+
const resultObj = result as { detail?: FalErrorDetail[] };
|
|
19
|
+
|
|
20
|
+
// FAL API error format: {detail: [{msg, type, loc}]}
|
|
21
|
+
if (Array.isArray(resultObj.detail) && resultObj.detail.length > 0) {
|
|
22
|
+
const firstError = resultObj.detail[0];
|
|
23
|
+
const errorType = firstError?.type || "unknown";
|
|
24
|
+
const errorMsg = firstError?.msg || "Unknown API error";
|
|
25
|
+
|
|
26
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
27
|
+
console.error("[FalApiError] Detected error in result:", {
|
|
28
|
+
type: errorType,
|
|
29
|
+
message: errorMsg,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Throw specific error based on type
|
|
34
|
+
if (errorType === "content_policy_violation") {
|
|
35
|
+
throw createGenerationError(GenerationErrorType.CONTENT_POLICY, errorMsg);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (errorType === "validation_error" || errorType.includes("validation")) {
|
|
39
|
+
throw createGenerationError(GenerationErrorType.VALIDATION, errorMsg);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
throw createGenerationError(GenerationErrorType.UNKNOWN, errorMsg);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* General Validation Utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ValidationResult } from "./validation-types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Validates that a value is not empty
|
|
9
|
+
*/
|
|
10
|
+
export function validateNotEmpty(value: unknown, fieldName = "Value"): ValidationResult {
|
|
11
|
+
if (value === null || value === undefined) {
|
|
12
|
+
return { isValid: false, error: `${fieldName} is required` };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (typeof value === "string" && value.trim().length === 0) {
|
|
16
|
+
return { isValid: false, error: `${fieldName} cannot be empty` };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
20
|
+
return { isValid: false, error: `${fieldName} cannot be empty` };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return { isValid: true };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Validates numeric range
|
|
28
|
+
*/
|
|
29
|
+
export function validateNumericRange(
|
|
30
|
+
value: number,
|
|
31
|
+
options: {
|
|
32
|
+
min?: number;
|
|
33
|
+
max?: number;
|
|
34
|
+
fieldName?: string;
|
|
35
|
+
}
|
|
36
|
+
): ValidationResult {
|
|
37
|
+
const { min, max, fieldName = "Value" } = options;
|
|
38
|
+
|
|
39
|
+
if (typeof value !== "number" || isNaN(value)) {
|
|
40
|
+
return { isValid: false, error: `${fieldName} must be a number` };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (min !== undefined && value < min) {
|
|
44
|
+
return { isValid: false, error: `${fieldName} must be at least ${min}` };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (max !== undefined && value > max) {
|
|
48
|
+
return { isValid: false, error: `${fieldName} must not exceed ${max}` };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { isValid: true };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Combines multiple validation results
|
|
56
|
+
*/
|
|
57
|
+
export function combineValidations(...results: ValidationResult[]): ValidationResult {
|
|
58
|
+
for (const result of results) {
|
|
59
|
+
if (!result.isValid) {
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { isValid: true };
|
|
64
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ID Validation Utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
MAX_USER_ID_LENGTH,
|
|
7
|
+
MAX_CREATION_ID_LENGTH,
|
|
8
|
+
} from "../constants/validation.constants";
|
|
9
|
+
import type { ValidationResult } from "./validation-types";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Validates user ID
|
|
13
|
+
*/
|
|
14
|
+
export function validateUserId(userId: string): ValidationResult {
|
|
15
|
+
if (!userId || typeof userId !== "string") {
|
|
16
|
+
return { isValid: false, error: "User ID is required" };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (userId.length > MAX_USER_ID_LENGTH) {
|
|
20
|
+
return { isValid: false, error: "User ID is too long" };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return { isValid: true };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Validates creation ID
|
|
28
|
+
*/
|
|
29
|
+
export function validateCreationId(creationId: string): ValidationResult {
|
|
30
|
+
if (!creationId || typeof creationId !== "string") {
|
|
31
|
+
return { isValid: false, error: "Creation ID is required" };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (creationId.length > MAX_CREATION_ID_LENGTH) {
|
|
35
|
+
return { isValid: false, error: "Creation ID is too long" };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return { isValid: true };
|
|
39
|
+
}
|