@umituz/react-native-ai-generation-content 1.90.2 → 1.90.3
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/interfaces/app-services-auth.interface.ts +27 -0
- package/src/domain/interfaces/app-services-composite.interface.ts +29 -0
- package/src/domain/interfaces/app-services-optional.interface.ts +42 -0
- package/src/domain/interfaces/app-services.interface.ts +0 -79
- package/src/domains/background/infrastructure/services/job-poller-index.ts +7 -0
- package/src/domains/background/infrastructure/services/job-poller-utils.ts +130 -0
- package/src/domains/background/infrastructure/utils/polling-interval.util.ts +1 -1
- package/src/domains/background/presentation/hooks/use-background-generation.ts +1 -1
- package/src/domains/content-moderation/infrastructure/services/content-moderation.service.ts +1 -1
- package/src/domains/content-moderation/infrastructure/services/moderators/image.moderator.ts +34 -8
- package/src/domains/content-moderation/infrastructure/services/moderators/text.moderator.ts +15 -4
- package/src/domains/content-moderation/infrastructure/services/moderators/video.moderator.ts +34 -8
- package/src/domains/content-moderation/infrastructure/services/moderators/voice.moderator.ts +19 -8
- package/src/domains/creations/domain/types/creation-categories.constants.ts +57 -0
- package/src/domains/creations/domain/types/creation-categories.helpers.ts +67 -0
- package/src/domains/creations/domain/types/creation-categories.ts +5 -111
- package/src/domains/creations/presentation/hooks/creation-validators.ts +31 -29
- package/src/domains/creations/presentation/hooks/job-poller-index.ts +10 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.filters.ts +34 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.logger.ts +76 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.stale-handlers.ts +52 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.ts +8 -0
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +1 -1
- package/src/domains/creations/presentation-exports.ts +2 -2
- package/src/domains/face-detection/domain/entities/FaceDetection.ts +4 -3
- package/src/domains/face-detection/presentation/hooks/useFaceDetection.ts +24 -21
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-preparation.ts +58 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-prompt.ts +69 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-resolution.ts +77 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple.ts +54 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-index.ts +8 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-scenario.ts +113 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder.ts +7 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/index.ts +20 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/types.ts +44 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-end-logger.ts +18 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-start-logger.ts +57 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-step-logger.ts +106 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/index.ts +8 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/types.ts +49 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils.ts +8 -0
- package/src/domains/generation/infrastructure/flow/flow-store-actions.ts +105 -0
- package/src/domains/generation/infrastructure/flow/flow-store-initial-state.ts +26 -0
- package/src/domains/generation/infrastructure/flow/useFlowStore.ts +4 -116
- package/src/domains/generation/presentation/useAIGeneration.hook.ts +1 -1
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation-strategy-index.ts +7 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.ts +2 -12
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.types.ts +11 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.utils.ts +12 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts +1 -220
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-builder.ts +66 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-extraction.ts +88 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-prompt-builder.ts +75 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-style-enhancements.ts +35 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-strategy-factory.ts +42 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor-index.ts +11 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor.ts +76 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-input-builder.ts +46 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-result-types.ts +17 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-submission.ts +62 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.audio-extractor.ts +27 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.executor.ts +2 -175
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.input-builder.ts +90 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +3 -108
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.types.ts +0 -129
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.validation.ts +136 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/index.ts +39 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/types.ts +37 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/usePhotoUploadStateLogic.ts +142 -0
- package/src/domains/generation/wizard/presentation/hooks/use-video-queue-utils.ts +103 -0
- package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.handlers.ts +97 -0
- package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.saver.ts +54 -0
- package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.ts +22 -87
- package/src/domains/generation/wizard/presentation/hooks/usePhotoUploadState.ts +8 -177
- package/src/domains/generation/wizard/presentation/hooks/useVideoQueueGeneration.ts +1 -295
- package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +1 -1
- package/src/domains/generation/wizard/presentation/hooks/video-queue/index.ts +82 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationCallbacks.ts +120 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationPolling.ts +76 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationRefs.ts +65 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationStart.ts +123 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue-index.ts +9 -0
- package/src/domains/image-to-video/domain/types/image-to-video-state.types.ts +11 -4
- package/src/domains/text-to-image/domain/types/text-to-image.types.ts +44 -22
- package/src/domains/text-to-video/domain/types/request.types.ts +33 -9
- package/src/domains/text-to-video/domain/types/state.types.ts +29 -9
- package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.handlers.ts +44 -0
- package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.ts +5 -51
- package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.types.ts +33 -0
- package/src/infrastructure/services/generation-orchestrator.service.ts +2 -2
- package/src/infrastructure/utils/couple-input-context.ts +13 -0
- package/src/infrastructure/utils/couple-input-index.ts +8 -0
- package/src/infrastructure/utils/couple-input-refiner.ts +101 -0
- package/src/infrastructure/utils/couple-input-resolver.ts +71 -0
- package/src/infrastructure/utils/couple-input-types.ts +14 -0
- package/src/infrastructure/utils/couple-input.util.ts +3 -176
- package/src/infrastructure/utils/photo-generation/photo-preparation.util.ts +1 -1
- package/src/infrastructure/validation/base-validator.ts +1 -27
- package/src/infrastructure/validation/base-validator.types.ts +32 -0
- package/src/presentation/hooks/generation/index.ts +1 -1
- package/src/presentation/hooks/generation/orchestrator-abort-logs.ts +48 -0
- package/src/presentation/hooks/generation/orchestrator-execution-logs.ts +67 -0
- package/src/presentation/hooks/generation/orchestrator-index.ts +14 -0
- package/src/presentation/hooks/generation/orchestrator-start-logs.ts +65 -0
- package/src/presentation/hooks/generation/orchestrator-state-utils.ts +17 -0
- package/src/presentation/hooks/generation/orchestrator-types.ts +55 -0
- package/src/presentation/hooks/generation/orchestrator-utils-index.ts +29 -0
- package/src/presentation/hooks/generation/orchestrator-utils.ts +25 -0
- package/src/presentation/hooks/generation/useDualImageGeneration.ts +1 -1
- package/src/presentation/hooks/generation/useImageGeneration.ts +1 -1
- package/src/presentation/hooks/generation/useVideoGeneration.ts +1 -1
- package/src/shared/hooks/factories/generation-hook-index.ts +12 -0
- package/src/shared/hooks/factories/generation-hook-types.ts +47 -0
- package/src/shared/hooks/factories/generation-hook-utils.ts +94 -0
- package/src/shared/hooks/factories/index.ts +1 -1
- package/src/shared/index.ts +1 -1
- package/src/shared/utils/calculations/aspect-ratio-calculations.ts +30 -0
- package/src/shared/utils/calculations/base64-calculations.ts +26 -0
- package/src/shared/utils/calculations/confidence-calculations.ts +21 -0
- package/src/shared/utils/calculations/cost-calculations-index.ts +43 -0
- package/src/shared/utils/calculations/cost-calculations.ts +25 -0
- package/src/shared/utils/calculations/credit-calculations.ts +37 -0
- package/src/shared/utils/calculations/index.ts +46 -0
- package/src/shared/utils/calculations/math-utilities.ts +32 -0
- package/src/shared/utils/calculations/memory-calculations.ts +33 -0
- package/src/shared/utils/calculations/pagination-calculations.ts +38 -0
- package/src/shared/utils/calculations/percentage-calculations.ts +33 -0
- package/src/shared/utils/calculations/time-calculations.ts +99 -0
- package/src/shared/utils/credit.ts +1 -1
- package/src/shared-kernel/application/hooks/index.ts +8 -0
- package/src/shared-kernel/application/hooks/use-feature-state.ts +107 -0
- package/src/shared-kernel/application/hooks/use-generation-handler.ts +110 -0
- package/src/shared-kernel/base-types/base-callbacks.types.ts +73 -0
- package/src/shared-kernel/base-types/base-feature-state.types.ts +77 -0
- package/src/shared-kernel/base-types/base-generation.types.ts +69 -0
- package/src/shared-kernel/base-types/index.ts +30 -0
- package/src/shared-kernel/domain/base-generation-strategy.ts +146 -0
- package/src/shared-kernel/domain/index.ts +7 -0
- package/src/shared-kernel/index.ts +17 -0
- package/src/shared-kernel/infrastructure/validation/common-validators.ts +126 -0
- package/src/shared-kernel/infrastructure/validation/common-validators.types.ts +33 -0
- package/src/shared-kernel/infrastructure/validation/error-handler.ts +52 -0
- package/src/shared-kernel/infrastructure/validation/error-handler.types.ts +38 -0
- package/src/shared-kernel/infrastructure/validation/error-handler.utils.ts +79 -0
- package/src/shared-kernel/infrastructure/validation/index.ts +28 -0
- package/src/domains/background/infrastructure/services/job-poller.service.ts +0 -234
- package/src/domains/creations/presentation/hooks/useProcessingJobsPoller.ts +0 -256
- package/src/domains/generation/infrastructure/couple-generation-builder.ts +0 -374
- package/src/presentation/hooks/generation/orchestrator.ts +0 -276
- package/src/shared/hooks/factories/createGenerationHook.ts +0 -253
- package/src/shared/utils/calculations.util.ts +0 -366
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base strategy pattern for generation operations
|
|
3
|
+
* Eliminates duplicate strategy implementations across domains
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
BaseGenerationCallbacks,
|
|
8
|
+
BaseGenerationResult,
|
|
9
|
+
BaseRequestMeta,
|
|
10
|
+
GenerationProgress,
|
|
11
|
+
} from '../base-types';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Base strategy interface for all generation operations
|
|
15
|
+
*/
|
|
16
|
+
export interface IGenerationStrategy<TInput, TOutput> {
|
|
17
|
+
/** Execute the generation operation */
|
|
18
|
+
execute(input: TInput, meta: BaseRequestMeta): Promise<BaseGenerationResult<TOutput>>;
|
|
19
|
+
/** Validate input before execution */
|
|
20
|
+
validate(input: TInput): boolean | Promise<boolean>;
|
|
21
|
+
/** Get estimated cost in credits */
|
|
22
|
+
getCreditCost(input: TInput): number;
|
|
23
|
+
/** Cancel ongoing generation */
|
|
24
|
+
cancel?(): void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Abstract base class for generation strategies
|
|
29
|
+
* Provides common implementation for all strategies
|
|
30
|
+
*/
|
|
31
|
+
export abstract class BaseGenerationStrategy<TInput, TOutput>
|
|
32
|
+
implements IGenerationStrategy<TInput, TOutput>
|
|
33
|
+
{
|
|
34
|
+
protected callbacks?: BaseGenerationCallbacks<TOutput>;
|
|
35
|
+
protected isCancelled = false;
|
|
36
|
+
|
|
37
|
+
constructor(callbacks?: BaseGenerationCallbacks<TOutput>) {
|
|
38
|
+
this.callbacks = callbacks;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Execute generation with consistent error handling and callbacks
|
|
43
|
+
*/
|
|
44
|
+
async execute(
|
|
45
|
+
input: TInput,
|
|
46
|
+
meta: BaseRequestMeta
|
|
47
|
+
): Promise<BaseGenerationResult<TOutput>> {
|
|
48
|
+
const startTime = Date.now();
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
this.isCancelled = false;
|
|
52
|
+
this.callbacks?.onStart?.();
|
|
53
|
+
|
|
54
|
+
// Validate input
|
|
55
|
+
const isValid = await this.validate(input);
|
|
56
|
+
if (!isValid) {
|
|
57
|
+
throw new Error('Invalid input');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check credits
|
|
61
|
+
const creditCost = this.getCreditCost(input);
|
|
62
|
+
if (this.callbacks?.onCreditCheck) {
|
|
63
|
+
const hasCredits = await this.callbacks.onCreditCheck();
|
|
64
|
+
if (!hasCredits) {
|
|
65
|
+
this.callbacks?.onShowPaywall?.();
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
error: 'Insufficient credits',
|
|
69
|
+
requestId: meta.requestId,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Execute generation
|
|
75
|
+
const result = await this.doExecute(input, meta);
|
|
76
|
+
|
|
77
|
+
if (this.isCancelled) {
|
|
78
|
+
this.callbacks?.onCancel?.();
|
|
79
|
+
return {
|
|
80
|
+
success: false,
|
|
81
|
+
error: 'Generation cancelled',
|
|
82
|
+
requestId: meta.requestId,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (result.success) {
|
|
87
|
+
this.callbacks?.onSuccess?.(result);
|
|
88
|
+
this.callbacks?.onCreditsConsumed?.(creditCost);
|
|
89
|
+
} else {
|
|
90
|
+
const error = new Error(result.error || 'Generation failed');
|
|
91
|
+
this.callbacks?.onError?.(error);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.callbacks?.onComplete?.();
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
...result,
|
|
98
|
+
duration: Date.now() - startTime,
|
|
99
|
+
};
|
|
100
|
+
} catch (error) {
|
|
101
|
+
const err = error instanceof Error ? error : new Error('Unknown error');
|
|
102
|
+
this.callbacks?.onError?.(err);
|
|
103
|
+
this.callbacks?.onComplete?.();
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
error: err.message,
|
|
108
|
+
requestId: meta.requestId,
|
|
109
|
+
duration: Date.now() - startTime,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Abstract method to be implemented by concrete strategies
|
|
116
|
+
*/
|
|
117
|
+
protected abstract doExecute(
|
|
118
|
+
input: TInput,
|
|
119
|
+
meta: BaseRequestMeta
|
|
120
|
+
): Promise<BaseGenerationResult<TOutput>>;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Abstract validation method to be implemented by concrete strategies
|
|
124
|
+
*/
|
|
125
|
+
abstract validate(input: TInput): boolean | Promise<boolean>;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Abstract credit cost method to be implemented by concrete strategies
|
|
129
|
+
*/
|
|
130
|
+
abstract getCreditCost(input: TInput): number;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Cancel ongoing generation
|
|
134
|
+
*/
|
|
135
|
+
cancel(): void {
|
|
136
|
+
this.isCancelled = true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Report progress during generation
|
|
141
|
+
*/
|
|
142
|
+
protected reportProgress(progress: number, status?: string): void {
|
|
143
|
+
const progressInfo: GenerationProgress = { progress, status };
|
|
144
|
+
this.callbacks?.onProgress?.(progressInfo);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Kernel Module
|
|
3
|
+
* Provides base types, utilities, and patterns for all domains
|
|
4
|
+
* Following DDD principles with clean architecture
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Base types
|
|
8
|
+
export * from './base-types';
|
|
9
|
+
|
|
10
|
+
// Application services
|
|
11
|
+
export * from './application/hooks';
|
|
12
|
+
|
|
13
|
+
// Domain layer
|
|
14
|
+
export * from './domain';
|
|
15
|
+
|
|
16
|
+
// Infrastructure utilities
|
|
17
|
+
export * from './infrastructure/validation';
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common validation utilities
|
|
3
|
+
* Shared validation logic across all domains
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ValidationResult, StringValidationOptions, NumberValidationOptions } from "./common-validators.types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Validate a string value
|
|
10
|
+
*/
|
|
11
|
+
export function validateString(
|
|
12
|
+
value: string,
|
|
13
|
+
options: StringValidationOptions = {}
|
|
14
|
+
): ValidationResult {
|
|
15
|
+
const errors: Record<string, string> = {};
|
|
16
|
+
let processedValue = value;
|
|
17
|
+
|
|
18
|
+
if (options.trim) {
|
|
19
|
+
processedValue = value.trim();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (options.required && !processedValue) {
|
|
23
|
+
errors.required = 'This field is required';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (options.minLength && processedValue.length < options.minLength) {
|
|
27
|
+
errors.minLength = `Minimum length is ${options.minLength}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (options.maxLength && processedValue.length > options.maxLength) {
|
|
31
|
+
errors.maxLength = `Maximum length is ${options.maxLength}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (options.pattern && !options.pattern.test(processedValue)) {
|
|
35
|
+
errors.pattern = 'Invalid format';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
isValid: Object.keys(errors).length === 0,
|
|
40
|
+
errors,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Validate a number value
|
|
46
|
+
*/
|
|
47
|
+
export function validateNumber(
|
|
48
|
+
value: number,
|
|
49
|
+
options: NumberValidationOptions = {}
|
|
50
|
+
): ValidationResult {
|
|
51
|
+
const errors: Record<string, string> = {};
|
|
52
|
+
|
|
53
|
+
if (options.required && (value === null || value === undefined)) {
|
|
54
|
+
errors.required = 'This field is required';
|
|
55
|
+
return { isValid: false, errors };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (value === null || value === undefined) {
|
|
59
|
+
return { isValid: true, errors: {} };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (options.integer && !Number.isInteger(value)) {
|
|
63
|
+
errors.integer = 'Must be an integer';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (options.min !== undefined && value < options.min) {
|
|
67
|
+
errors.min = `Minimum value is ${options.min}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (options.max !== undefined && value > options.max) {
|
|
71
|
+
errors.max = `Maximum value is ${options.max}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
isValid: Object.keys(errors).length === 0,
|
|
76
|
+
errors,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Validate a URL
|
|
82
|
+
*/
|
|
83
|
+
export function validateUrl(url: string): ValidationResult {
|
|
84
|
+
const urlPattern = /^https?:\/\/.+/i;
|
|
85
|
+
return validateString(url, {
|
|
86
|
+
required: true,
|
|
87
|
+
pattern: urlPattern,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Validate an object has required fields
|
|
93
|
+
*/
|
|
94
|
+
export function validateRequiredFields<T extends Record<string, unknown>>(
|
|
95
|
+
obj: T,
|
|
96
|
+
requiredFields: (keyof T)[]
|
|
97
|
+
): ValidationResult {
|
|
98
|
+
const errors: Record<string, string> = {};
|
|
99
|
+
|
|
100
|
+
for (const field of requiredFields) {
|
|
101
|
+
if (obj[field] === null || obj[field] === undefined) {
|
|
102
|
+
errors[field as string] = `${String(field)} is required`;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
isValid: Object.keys(errors).length === 0,
|
|
108
|
+
errors,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Combine multiple validation results
|
|
114
|
+
*/
|
|
115
|
+
export function combineValidationResults(
|
|
116
|
+
...results: ValidationResult[]
|
|
117
|
+
): ValidationResult {
|
|
118
|
+
const allErrors = results.reduce((acc, result) => {
|
|
119
|
+
return { ...acc, ...result.errors };
|
|
120
|
+
}, {} as Record<string, string>);
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
isValid: Object.keys(allErrors).length === 0,
|
|
124
|
+
errors: allErrors,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common validation utilities - Types
|
|
3
|
+
* Type definitions for validation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Validation result structure
|
|
8
|
+
*/
|
|
9
|
+
export interface ValidationResult {
|
|
10
|
+
isValid: boolean;
|
|
11
|
+
errors: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* String validation options
|
|
16
|
+
*/
|
|
17
|
+
export interface StringValidationOptions {
|
|
18
|
+
minLength?: number;
|
|
19
|
+
maxLength?: number;
|
|
20
|
+
pattern?: RegExp;
|
|
21
|
+
required?: boolean;
|
|
22
|
+
trim?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Number validation options
|
|
27
|
+
*/
|
|
28
|
+
export interface NumberValidationOptions {
|
|
29
|
+
min?: number;
|
|
30
|
+
max?: number;
|
|
31
|
+
integer?: boolean;
|
|
32
|
+
required?: boolean;
|
|
33
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized error handling utilities
|
|
3
|
+
* Standardizes error handling across all domains
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { AppError, ErrorHandlerOptions } from "./error-handler.types";
|
|
7
|
+
import { toAppError, getUserFriendlyMessage } from "./error-handler.utils";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Handle error with consistent behavior
|
|
11
|
+
*/
|
|
12
|
+
export function handleError(
|
|
13
|
+
error: unknown,
|
|
14
|
+
options: ErrorHandlerOptions = {}
|
|
15
|
+
): AppError {
|
|
16
|
+
const {
|
|
17
|
+
logErrors = true,
|
|
18
|
+
showUserMessage = true,
|
|
19
|
+
transformError,
|
|
20
|
+
} = options;
|
|
21
|
+
|
|
22
|
+
const appError = toAppError(error);
|
|
23
|
+
const finalError = transformError ? transformError(appError) : appError;
|
|
24
|
+
|
|
25
|
+
if (logErrors) {
|
|
26
|
+
console.error('[Error Handler]', finalError);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (showUserMessage) {
|
|
30
|
+
const userMessage = getUserFriendlyMessage(finalError);
|
|
31
|
+
// Could integrate with notification system here
|
|
32
|
+
console.warn('[User Message]', userMessage);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return finalError;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Wrap async function with error handling
|
|
40
|
+
*/
|
|
41
|
+
export function withErrorHandling<T extends (...args: unknown[]) => Promise<unknown>>(
|
|
42
|
+
fn: T,
|
|
43
|
+
options: ErrorHandlerOptions = {}
|
|
44
|
+
): T {
|
|
45
|
+
return (async (...args: Parameters<T>) => {
|
|
46
|
+
try {
|
|
47
|
+
return await fn(...args);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
throw handleError(error, options);
|
|
50
|
+
}
|
|
51
|
+
}) as T;
|
|
52
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Handler - Types
|
|
3
|
+
* Type definitions for error handling
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Error types for categorization
|
|
8
|
+
*/
|
|
9
|
+
export enum ErrorType {
|
|
10
|
+
VALIDATION = 'VALIDATION',
|
|
11
|
+
NETWORK = 'NETWORK',
|
|
12
|
+
CREDIT = 'CREDIT',
|
|
13
|
+
PROVIDER = 'PROVIDER',
|
|
14
|
+
UNKNOWN = 'UNKNOWN',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Application error structure
|
|
19
|
+
*/
|
|
20
|
+
export interface AppError {
|
|
21
|
+
type: ErrorType;
|
|
22
|
+
message: string;
|
|
23
|
+
code?: string;
|
|
24
|
+
details?: Record<string, unknown>;
|
|
25
|
+
originalError?: unknown;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Error handler options
|
|
30
|
+
*/
|
|
31
|
+
export interface ErrorHandlerOptions {
|
|
32
|
+
/** Log errors to console */
|
|
33
|
+
logErrors?: boolean;
|
|
34
|
+
/** Show user-friendly messages */
|
|
35
|
+
showUserMessage?: boolean;
|
|
36
|
+
/** Custom error transformer */
|
|
37
|
+
transformError?: (error: AppError) => AppError;
|
|
38
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Handler - Utilities
|
|
3
|
+
* Utility functions for error handling
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { AppError, ErrorHandlerOptions } from "./error-handler.types";
|
|
7
|
+
import { ErrorType } from "./error-handler.types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Create a standardized application error
|
|
11
|
+
*/
|
|
12
|
+
export function createError(
|
|
13
|
+
type: ErrorType,
|
|
14
|
+
message: string,
|
|
15
|
+
code?: string,
|
|
16
|
+
details?: Record<string, unknown>,
|
|
17
|
+
originalError?: unknown
|
|
18
|
+
): AppError {
|
|
19
|
+
return {
|
|
20
|
+
type,
|
|
21
|
+
message,
|
|
22
|
+
code,
|
|
23
|
+
details,
|
|
24
|
+
originalError,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Convert unknown error to AppError
|
|
30
|
+
*/
|
|
31
|
+
export function toAppError(error: unknown): AppError {
|
|
32
|
+
if (isAppError(error)) {
|
|
33
|
+
return error;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (error instanceof Error) {
|
|
37
|
+
return {
|
|
38
|
+
type: ErrorType.UNKNOWN,
|
|
39
|
+
message: error.message,
|
|
40
|
+
originalError: error,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
type: ErrorType.UNKNOWN,
|
|
46
|
+
message: String(error),
|
|
47
|
+
originalError: error,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Check if error is AppError
|
|
53
|
+
*/
|
|
54
|
+
export function isAppError(error: unknown): error is AppError {
|
|
55
|
+
return (
|
|
56
|
+
typeof error === 'object' &&
|
|
57
|
+
error !== null &&
|
|
58
|
+
'type' in error &&
|
|
59
|
+
'message' in error
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get user-friendly error message
|
|
65
|
+
*/
|
|
66
|
+
export function getUserFriendlyMessage(error: AppError): string {
|
|
67
|
+
switch (error.type) {
|
|
68
|
+
case ErrorType.VALIDATION:
|
|
69
|
+
return 'Please check your input and try again.';
|
|
70
|
+
case ErrorType.NETWORK:
|
|
71
|
+
return 'Network error. Please check your connection and try again.';
|
|
72
|
+
case ErrorType.CREDIT:
|
|
73
|
+
return 'Insufficient credits. Please upgrade to continue.';
|
|
74
|
+
case ErrorType.PROVIDER:
|
|
75
|
+
return 'Service temporarily unavailable. Please try again later.';
|
|
76
|
+
default:
|
|
77
|
+
return error.message || 'An unexpected error occurred.';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared infrastructure validation utilities
|
|
3
|
+
* Exports all validation and error handling utilities
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type {
|
|
7
|
+
ValidationResult,
|
|
8
|
+
StringValidationOptions,
|
|
9
|
+
NumberValidationOptions,
|
|
10
|
+
} from './common-validators';
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
validateString,
|
|
14
|
+
validateNumber,
|
|
15
|
+
validateUrl,
|
|
16
|
+
validateRequiredFields,
|
|
17
|
+
combineValidationResults,
|
|
18
|
+
} from './common-validators';
|
|
19
|
+
|
|
20
|
+
export { ErrorType, type AppError, type ErrorHandlerOptions } from './error-handler';
|
|
21
|
+
export {
|
|
22
|
+
createError,
|
|
23
|
+
toAppError,
|
|
24
|
+
isAppError,
|
|
25
|
+
getUserFriendlyMessage,
|
|
26
|
+
handleError,
|
|
27
|
+
withErrorHandling,
|
|
28
|
+
} from './error-handler';
|