@umituz/react-native-ai-fal-provider 3.1.7 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/package.json +1 -1
  2. package/src/exports/infrastructure.ts +0 -45
  3. package/src/exports/presentation.ts +2 -11
  4. package/src/index.ts +2 -3
  5. package/src/infrastructure/services/fal-queue-operations.ts +1 -1
  6. package/src/infrastructure/services/index.ts +0 -2
  7. package/src/infrastructure/utils/index.ts +7 -53
  8. package/src/infrastructure/utils/input-validator.util.ts +1 -1
  9. package/src/infrastructure/utils/parsers/index.ts +1 -4
  10. package/src/init/createAiProviderInitModule.ts +0 -56
  11. package/src/init/initializeFalProvider.ts +34 -0
  12. package/src/presentation/hooks/index.ts +0 -3
  13. package/src/infrastructure/services/fal-models.service.ts +0 -40
  14. package/src/infrastructure/utils/base-builders.util.ts +0 -28
  15. package/src/infrastructure/utils/collections/array-filters.util.ts +0 -63
  16. package/src/infrastructure/utils/collections/array-sorters.util.ts +0 -94
  17. package/src/infrastructure/utils/collections/index.ts +0 -7
  18. package/src/infrastructure/utils/date-format.util.ts +0 -30
  19. package/src/infrastructure/utils/error-categorizer.ts +0 -9
  20. package/src/infrastructure/utils/job-metadata/index.ts +0 -26
  21. package/src/infrastructure/utils/job-metadata/job-metadata-format.util.ts +0 -78
  22. package/src/infrastructure/utils/job-metadata/job-metadata-lifecycle.util.ts +0 -66
  23. package/src/infrastructure/utils/job-metadata/job-metadata-queries.util.ts +0 -57
  24. package/src/infrastructure/utils/job-metadata/job-metadata.types.ts +0 -19
  25. package/src/infrastructure/utils/job-storage/index.ts +0 -19
  26. package/src/infrastructure/utils/job-storage/job-storage-crud.util.ts +0 -64
  27. package/src/infrastructure/utils/job-storage/job-storage-interface.ts +0 -44
  28. package/src/infrastructure/utils/job-storage/job-storage-queries.util.ts +0 -81
  29. package/src/infrastructure/utils/number-format.util.ts +0 -86
  30. package/src/infrastructure/utils/parsers/object-validators.util.ts +0 -38
  31. package/src/infrastructure/utils/parsers/value-parsers.util.ts +0 -45
  32. package/src/infrastructure/utils/string-format.util.ts +0 -72
  33. package/src/infrastructure/validators/README.md +0 -290
  34. package/src/init/registerWithWizard.ts +0 -28
  35. package/src/presentation/hooks/README.md +0 -626
  36. package/src/presentation/hooks/use-models.ts +0 -56
@@ -1,78 +0,0 @@
1
- /**
2
- * Job Metadata Formatting
3
- * Duration, progress calculation, and formatting utilities
4
- */
5
-
6
- import type { FalJobMetadata } from "./job-metadata.types";
7
-
8
- /**
9
- * Get job duration in milliseconds
10
- * Returns null if job not completed or if dates are invalid
11
- */
12
- export function getJobDuration(metadata: FalJobMetadata): number | null {
13
- if (!metadata.completedAt) {
14
- return null;
15
- }
16
-
17
- const completedTime = new Date(metadata.completedAt).getTime();
18
- const createdTime = new Date(metadata.createdAt).getTime();
19
-
20
- // Validate both dates parsed correctly
21
- if (isNaN(completedTime) || isNaN(createdTime)) {
22
- console.warn(
23
- '[job-metadata] Invalid date(s) in metadata:',
24
- { completedAt: metadata.completedAt, createdAt: metadata.createdAt }
25
- );
26
- return null;
27
- }
28
-
29
- const duration = completedTime - createdTime;
30
-
31
- // Sanity check: duration should be positive
32
- if (duration < 0) {
33
- console.warn(
34
- '[job-metadata] Negative duration detected (completedAt < createdAt):',
35
- { duration, completedAt: metadata.completedAt, createdAt: metadata.createdAt }
36
- );
37
- return null;
38
- }
39
-
40
- return duration;
41
- }
42
-
43
- /**
44
- * Format job duration for display
45
- */
46
- export function formatJobDuration(metadata: FalJobMetadata): string {
47
- const duration = getJobDuration(metadata);
48
- if (!duration) {
49
- return "In progress";
50
- }
51
-
52
- const seconds = Math.floor(duration / 1000);
53
- if (seconds < 60) {
54
- return `${seconds}s`;
55
- }
56
-
57
- const minutes = Math.floor(seconds / 60);
58
- const remainingSeconds = seconds % 60;
59
- return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
60
- }
61
-
62
- /**
63
- * Calculate job progress percentage
64
- */
65
- export function calculateJobProgress(metadata: FalJobMetadata): number {
66
- switch (metadata.status) {
67
- case "IN_QUEUE":
68
- return 10;
69
- case "IN_PROGRESS":
70
- return 50;
71
- case "COMPLETED":
72
- return 100;
73
- case "FAILED":
74
- return 0;
75
- default:
76
- return 0;
77
- }
78
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * Job Metadata Lifecycle
3
- * Create, update, and status check operations
4
- */
5
-
6
- import type { JobStatus } from "../../../domain/types";
7
- import type { FalJobMetadata } from "./job-metadata.types";
8
-
9
- /**
10
- * Create job metadata
11
- */
12
- export function createJobMetadata(
13
- requestId: string,
14
- model: string,
15
- timeout?: number
16
- ): FalJobMetadata {
17
- const now = new Date().toISOString();
18
- return {
19
- requestId,
20
- model,
21
- status: "IN_QUEUE",
22
- createdAt: now,
23
- updatedAt: now,
24
- timeout,
25
- };
26
- }
27
-
28
- /**
29
- * Update job metadata status
30
- */
31
- export function updateJobMetadata(
32
- metadata: FalJobMetadata,
33
- status: JobStatus["status"],
34
- error?: string
35
- ): FalJobMetadata {
36
- return {
37
- ...metadata,
38
- status,
39
- updatedAt: new Date().toISOString(),
40
- ...(status === "COMPLETED" || status === "FAILED" ? { completedAt: new Date().toISOString() } : {}),
41
- ...(error ? { error } : {}),
42
- };
43
- }
44
-
45
- /**
46
- * Check if job is completed (success or failure)
47
- */
48
- export function isJobCompleted(metadata: FalJobMetadata): boolean {
49
- return metadata.status === "COMPLETED" || metadata.status === "FAILED";
50
- }
51
-
52
- /**
53
- * Check if job is running
54
- */
55
- export function isJobRunning(metadata: FalJobMetadata): boolean {
56
- return metadata.status === "IN_QUEUE" || metadata.status === "IN_PROGRESS";
57
- }
58
-
59
- /**
60
- * Check if job is stale (older than specified minutes)
61
- */
62
- export function isJobStale(metadata: FalJobMetadata, maxAgeMinutes: number = 60): boolean {
63
- const age = Date.now() - new Date(metadata.createdAt).getTime();
64
- const maxAgeMs = maxAgeMinutes * 60 * 1000;
65
- return age > maxAgeMs;
66
- }
@@ -1,57 +0,0 @@
1
- /**
2
- * Job Metadata Queries
3
- * Serialization and array operations
4
- */
5
-
6
- import type { FalJobMetadata } from "./job-metadata.types";
7
- import { isJobStale, isJobRunning, isJobCompleted } from "./job-metadata-lifecycle.util";
8
- import { sortByDateDescending, filterByPredicate } from "../collections";
9
- import { safeJsonParseOrNull, validateObjectStructure } from "../parsers";
10
-
11
- /**
12
- * Serialize job metadata for storage
13
- */
14
- export function serializeJobMetadata(metadata: FalJobMetadata): string {
15
- return JSON.stringify(metadata);
16
- }
17
-
18
- /**
19
- * Deserialize job metadata from storage
20
- */
21
- export function deserializeJobMetadata(data: string): FalJobMetadata | null {
22
- const parsed = safeJsonParseOrNull<Record<string, unknown>>(data);
23
-
24
- if (!parsed || !validateObjectStructure<Partial<FalJobMetadata>>(parsed, ["requestId", "model", "status"] as const)) {
25
- return null;
26
- }
27
-
28
- return parsed as FalJobMetadata;
29
- }
30
-
31
- /**
32
- * Filter valid job metadata from array
33
- */
34
- export function filterValidJobs(jobs: FalJobMetadata[]): FalJobMetadata[] {
35
- return filterByPredicate(jobs, (job) => !isJobStale(job));
36
- }
37
-
38
- /**
39
- * Sort jobs by creation time (newest first)
40
- */
41
- export function sortJobsByCreation(jobs: FalJobMetadata[]): FalJobMetadata[] {
42
- return sortByDateDescending(jobs, "createdAt");
43
- }
44
-
45
- /**
46
- * Get active jobs (not completed and not stale)
47
- */
48
- export function getActiveJobs(jobs: FalJobMetadata[]): FalJobMetadata[] {
49
- return filterByPredicate(jobs, (job) => isJobRunning(job) && !isJobStale(job));
50
- }
51
-
52
- /**
53
- * Get completed jobs
54
- */
55
- export function getCompletedJobs(jobs: FalJobMetadata[]): FalJobMetadata[] {
56
- return filterByPredicate(jobs, isJobCompleted);
57
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * Job Metadata Types
3
- */
4
-
5
- import type { JobStatus } from "../../../domain/types";
6
-
7
- /**
8
- * Job metadata for tracking and persistence
9
- */
10
- export interface FalJobMetadata {
11
- readonly requestId: string;
12
- readonly model: string;
13
- readonly status: JobStatus["status"];
14
- readonly createdAt: string;
15
- readonly updatedAt: string;
16
- readonly completedAt?: string;
17
- readonly timeout?: number;
18
- readonly error?: string;
19
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * Job Storage Utilities
3
- * Exports all job storage functionality
4
- */
5
-
6
- export type { IJobStorage } from "./job-storage-interface";
7
- export { InMemoryJobStorage } from "./job-storage-interface";
8
- export {
9
- saveJobMetadata,
10
- loadJobMetadata,
11
- deleteJobMetadata,
12
- updateJobStatus,
13
- } from "./job-storage-crud.util";
14
- export {
15
- loadAllJobs,
16
- cleanupOldJobs,
17
- getJobsByModel,
18
- getJobsByStatus,
19
- } from "./job-storage-queries.util";
@@ -1,64 +0,0 @@
1
- /**
2
- * Job Storage CRUD Operations
3
- * Basic create, read, update, delete operations for job metadata
4
- */
5
-
6
- import type { FalJobMetadata } from "../job-metadata";
7
- import { updateJobMetadata } from "../job-metadata";
8
- import type { IJobStorage } from "./job-storage-interface";
9
- import { safeJsonParseOrNull, safeJsonStringify } from "../parsers";
10
-
11
- /**
12
- * Save job metadata to storage
13
- */
14
- export async function saveJobMetadata(
15
- storage: IJobStorage,
16
- metadata: FalJobMetadata
17
- ): Promise<void> {
18
- const key = `fal_job:${metadata.requestId}`;
19
- const value = safeJsonStringify(metadata, "{}");
20
- await storage.setItem(key, value);
21
- }
22
-
23
- /**
24
- * Load job metadata from storage
25
- */
26
- export async function loadJobMetadata(
27
- storage: IJobStorage,
28
- requestId: string
29
- ): Promise<FalJobMetadata | null> {
30
- const key = `fal_job:${requestId}`;
31
- const value = await storage.getItem(key);
32
- if (!value) return null;
33
-
34
- return safeJsonParseOrNull<FalJobMetadata>(value);
35
- }
36
-
37
- /**
38
- * Delete job metadata from storage
39
- */
40
- export async function deleteJobMetadata(
41
- storage: IJobStorage,
42
- requestId: string
43
- ): Promise<void> {
44
- const key = `fal_job:${requestId}`;
45
- await storage.removeItem(key);
46
- }
47
-
48
- /**
49
- * Update job status in storage
50
- */
51
- export async function updateJobStatus(
52
- storage: IJobStorage,
53
- requestId: string,
54
- status: FalJobMetadata["status"],
55
- error?: string
56
- ): Promise<void> {
57
- const metadata = await loadJobMetadata(storage, requestId);
58
- if (!metadata) {
59
- throw new Error(`Job not found: ${requestId}`);
60
- }
61
-
62
- const updated = updateJobMetadata(metadata, status, error);
63
- await saveJobMetadata(storage, updated);
64
- }
@@ -1,44 +0,0 @@
1
- /**
2
- * Job Storage Interface
3
- * Generic storage interface for job persistence
4
- */
5
-
6
- /**
7
- * Generic storage interface for job persistence
8
- * Implement this interface with your preferred storage backend
9
- */
10
- export interface IJobStorage {
11
- setItem(key: string, value: string): Promise<void>;
12
- getItem(key: string): Promise<string | null>;
13
- removeItem(key: string): Promise<void>;
14
- getAllKeys?(): Promise<readonly string[]>;
15
- }
16
-
17
- /**
18
- * Simple in-memory storage for testing
19
- */
20
- export class InMemoryJobStorage implements IJobStorage {
21
- private store = new Map<string, string>();
22
-
23
- setItem(key: string, value: string): Promise<void> {
24
- this.store.set(key, value);
25
- return Promise.resolve();
26
- }
27
-
28
- getItem(key: string): Promise<string | null> {
29
- return Promise.resolve(this.store.get(key) ?? null);
30
- }
31
-
32
- removeItem(key: string): Promise<void> {
33
- this.store.delete(key);
34
- return Promise.resolve();
35
- }
36
-
37
- getAllKeys(): Promise<readonly string[]> {
38
- return Promise.resolve(Array.from(this.store.keys()));
39
- }
40
-
41
- clear(): void {
42
- this.store.clear();
43
- }
44
- }
@@ -1,81 +0,0 @@
1
- /**
2
- * Job Storage Query Operations
3
- * Query and batch operations for job metadata
4
- */
5
-
6
- import type { FalJobMetadata } from "../job-metadata";
7
- import type { IJobStorage } from "./job-storage-interface";
8
- import { deleteJobMetadata } from "./job-storage-crud.util";
9
- import { safeJsonParseOrNull } from "../parsers";
10
-
11
- /**
12
- * Load all jobs from storage
13
- */
14
- export async function loadAllJobs(
15
- storage: IJobStorage
16
- ): Promise<FalJobMetadata[]> {
17
- if (!storage.getAllKeys) {
18
- return [];
19
- }
20
-
21
- const keys = await storage.getAllKeys();
22
- const jobKeys = keys.filter((key) => key.startsWith("fal_job:"));
23
-
24
- const jobs: FalJobMetadata[] = [];
25
- for (const key of jobKeys) {
26
- const value = await storage.getItem(key);
27
- if (value) {
28
- const metadata = safeJsonParseOrNull<FalJobMetadata>(value);
29
- if (metadata) {
30
- jobs.push(metadata);
31
- }
32
- }
33
- }
34
-
35
- return jobs;
36
- }
37
-
38
- /**
39
- * Clean up old jobs from storage
40
- */
41
- export async function cleanupOldJobs(
42
- storage: IJobStorage,
43
- maxAgeMinutes: number = 60
44
- ): Promise<number> {
45
- const jobs = await loadAllJobs(storage);
46
- const now = Date.now();
47
- const maxAgeMs = maxAgeMinutes * 60 * 1000;
48
- let cleanedCount = 0;
49
-
50
- for (const job of jobs) {
51
- const jobAge = now - new Date(job.createdAt).getTime();
52
- if (jobAge > maxAgeMs) {
53
- await deleteJobMetadata(storage, job.requestId);
54
- cleanedCount++;
55
- }
56
- }
57
-
58
- return cleanedCount;
59
- }
60
-
61
- /**
62
- * Get jobs by model
63
- */
64
- export async function getJobsByModel(
65
- storage: IJobStorage,
66
- model: string
67
- ): Promise<FalJobMetadata[]> {
68
- const jobs = await loadAllJobs(storage);
69
- return jobs.filter((job) => job.model === model);
70
- }
71
-
72
- /**
73
- * Get jobs by status
74
- */
75
- export async function getJobsByStatus(
76
- storage: IJobStorage,
77
- status: FalJobMetadata["status"]
78
- ): Promise<FalJobMetadata[]> {
79
- const jobs = await loadAllJobs(storage);
80
- return jobs.filter((job) => job.status === status);
81
- }
@@ -1,86 +0,0 @@
1
- /**
2
- * Number Formatting Utilities
3
- * Functions for formatting numbers and quantities
4
- */
5
-
6
- /**
7
- * Format number with decimal places
8
- */
9
- export function formatNumber(value: number, decimals: number = 2): string {
10
- if (Number.isNaN(value) || !Number.isFinite(value)) {
11
- return "0";
12
- }
13
-
14
- // Return integer if no decimal part
15
- if (value % 1 === 0) {
16
- return value.toString();
17
- }
18
-
19
- return value.toFixed(decimals);
20
- }
21
-
22
- /**
23
- * Format bytes to human-readable size
24
- * Handles edge cases: negative bytes, NaN, Infinity, extremely large values
25
- */
26
- export function formatBytes(bytes: number, decimals: number = 2): string {
27
- // Handle invalid inputs
28
- if (!Number.isFinite(bytes) || Number.isNaN(bytes)) {
29
- return "0 Bytes";
30
- }
31
-
32
- // Handle negative bytes
33
- if (bytes < 0) {
34
- return `-${formatBytes(-bytes, decimals)}`;
35
- }
36
-
37
- // Handle zero
38
- if (bytes === 0) {
39
- return "0 Bytes";
40
- }
41
-
42
- const k = 1024;
43
- const dm = decimals < 0 ? 0 : decimals;
44
- const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
45
- const i = Math.floor(Math.log(bytes) / Math.log(k));
46
-
47
- // Clamp index to valid range
48
- const index = Math.min(i, sizes.length - 1);
49
-
50
- // For extremely large values beyond our size array
51
- if (index >= sizes.length - 1 && i > sizes.length - 1) {
52
- const exponent = i - (sizes.length - 1);
53
- const value = bytes / Math.pow(k, sizes.length - 1);
54
- return `${parseFloat(value.toFixed(dm))} ${sizes[sizes.length - 1]} × ${k}^${exponent}`;
55
- }
56
-
57
- return `${parseFloat((bytes / Math.pow(k, index)).toFixed(dm))} ${sizes[index]}`;
58
- }
59
-
60
- /**
61
- * Format duration in milliseconds to human-readable string
62
- */
63
- export function formatDuration(milliseconds: number): string {
64
- if (milliseconds < 1000) {
65
- return `${milliseconds}ms`;
66
- }
67
-
68
- const seconds = Math.floor(milliseconds / 1000);
69
- if (seconds < 60) {
70
- return `${seconds}s`;
71
- }
72
-
73
- const minutes = Math.floor(seconds / 60);
74
- const remainingSeconds = seconds % 60;
75
- if (minutes < 60) {
76
- return remainingSeconds > 0
77
- ? `${minutes}m ${remainingSeconds}s`
78
- : `${minutes}m`;
79
- }
80
-
81
- const hours = Math.floor(minutes / 60);
82
- const remainingMinutes = minutes % 60;
83
- return remainingMinutes > 0
84
- ? `${hours}h ${remainingMinutes}m`
85
- : `${hours}h`;
86
- }
@@ -1,38 +0,0 @@
1
- /**
2
- * Object Validator Utilities
3
- * Runtime object structure validation
4
- */
5
-
6
- /**
7
- * Validate object structure
8
- */
9
- export function validateObjectStructure<T extends Record<string, unknown>>(
10
- data: unknown,
11
- requiredKeys: readonly (keyof T)[]
12
- ): data is T {
13
- if (!data || typeof data !== "object") {
14
- return false;
15
- }
16
-
17
- for (const key of requiredKeys) {
18
- if (!(key in data)) {
19
- return false;
20
- }
21
- }
22
-
23
- return true;
24
- }
25
-
26
- /**
27
- * Validate array of objects
28
- */
29
- export function validateObjectArray<T>(
30
- data: unknown,
31
- validator: (item: unknown) => item is T
32
- ): data is T[] {
33
- if (!Array.isArray(data)) {
34
- return false;
35
- }
36
-
37
- return data.every(validator);
38
- }
@@ -1,45 +0,0 @@
1
- /**
2
- * Value Parser Utilities
3
- * Parse primitive values with fallbacks
4
- */
5
-
6
- /**
7
- * Parse number with fallback
8
- */
9
- export function parseNumber(value: unknown, fallback: number): number {
10
- if (typeof value === "number") {
11
- return value;
12
- }
13
-
14
- if (typeof value === "string") {
15
- const parsed = Number.parseFloat(value);
16
- return Number.isNaN(parsed) ? fallback : parsed;
17
- }
18
-
19
- return fallback;
20
- }
21
-
22
- /**
23
- * Parse boolean with fallback
24
- */
25
- export function parseBoolean(value: unknown, fallback: boolean): boolean {
26
- if (typeof value === "boolean") {
27
- return value;
28
- }
29
-
30
- if (typeof value === "string") {
31
- const lower = value.toLowerCase().trim();
32
- if (lower === "true" || lower === "yes" || lower === "1") {
33
- return true;
34
- }
35
- if (lower === "false" || lower === "no" || lower === "0") {
36
- return false;
37
- }
38
- }
39
-
40
- if (typeof value === "number") {
41
- return value !== 0;
42
- }
43
-
44
- return fallback;
45
- }
@@ -1,72 +0,0 @@
1
- /**
2
- * String Formatting Utilities
3
- * Functions for formatting and manipulating strings
4
- *
5
- * Consolidates text truncation and prompt sanitization utilities.
6
- * Previously duplicated across string-format.util.ts and prompt-helpers.util.ts.
7
- */
8
-
9
- /**
10
- * Truncate text with customizable ellipsis
11
- *
12
- * @param text - The text to truncate
13
- * @param maxLength - Maximum length including ellipsis
14
- * @param ellipsis - String to append when truncating (default: "...")
15
- * @returns Truncated text with ellipsis or original if under max length
16
- *
17
- * @example
18
- * ```typescript
19
- * truncateText("Hello World", 8); // "Hello..."
20
- * truncateText("Hello World", 8, "…"); // "Hello W…"
21
- * ```
22
- */
23
- export function truncateText(
24
- text: string,
25
- maxLength: number,
26
- ellipsis: string = "..."
27
- ): string {
28
- if (text.length <= maxLength) {
29
- return text;
30
- }
31
- return text.slice(0, maxLength - ellipsis.length) + ellipsis;
32
- }
33
-
34
- /**
35
- * Truncate prompt to maximum length
36
- * Specialized wrapper for prompt truncation with 5000 char default
37
- *
38
- * @param prompt - The prompt text to truncate
39
- * @param maxLength - Maximum length (default: 5000)
40
- * @returns Truncated prompt
41
- *
42
- * @example
43
- * ```typescript
44
- * truncatePrompt(longPrompt); // Truncates to 5000 chars
45
- * truncatePrompt(longPrompt, 1000); // Truncates to 1000 chars
46
- * ```
47
- */
48
- export function truncatePrompt(prompt: string, maxLength: number = 5000): string {
49
- return truncateText(prompt, maxLength);
50
- }
51
-
52
- /**
53
- * Sanitize prompt by removing excessive whitespace and control characters
54
- * Also enforces maximum length of 5000 characters
55
- *
56
- * @param prompt - The prompt text to sanitize
57
- * @returns Sanitized prompt
58
- *
59
- * @example
60
- * ```typescript
61
- * sanitizePrompt("Hello \n\n World\x00"); // "Hello World"
62
- * ```
63
- */
64
- export function sanitizePrompt(prompt: string): string {
65
- return prompt
66
- .trim()
67
- .replace(/\s+/g, " ")
68
- // Remove control characters except tab, newline, carriage return
69
- // eslint-disable-next-line no-control-regex
70
- .replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, '')
71
- .slice(0, 5000);
72
- }