@umituz/react-native-ai-fal-provider 1.0.3 → 1.0.4
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
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-fal-provider",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "FAL AI provider
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "FAL AI provider for React Native - implements IAIProvider interface for unified AI generation",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"typecheck": "
|
|
9
|
-
"lint": "
|
|
10
|
-
"
|
|
11
|
-
"version:minor": "npm version minor -m 'chore: release v%s'",
|
|
12
|
-
"version:major": "npm version major -m 'chore: release v%s'"
|
|
8
|
+
"typecheck": "tsc --noEmit",
|
|
9
|
+
"lint": "eslint src --ext .ts,.tsx --max-warnings 0",
|
|
10
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix"
|
|
13
11
|
},
|
|
14
12
|
"keywords": [
|
|
15
13
|
"react-native",
|
|
16
14
|
"fal-ai",
|
|
17
15
|
"ai",
|
|
16
|
+
"ai-provider",
|
|
18
17
|
"text-to-image",
|
|
19
18
|
"text-to-video",
|
|
20
19
|
"image-to-video",
|
|
21
|
-
"ai-generation"
|
|
20
|
+
"ai-generation",
|
|
21
|
+
"provider-agnostic"
|
|
22
22
|
],
|
|
23
23
|
"author": "Umit UZ <umit@umituz.com>",
|
|
24
24
|
"license": "MIT",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"@fal-ai/client": ">=0.6.0",
|
|
31
|
+
"@umituz/react-native-ai-generation-content": ">=1.16.0",
|
|
31
32
|
"react": ">=18.2.0",
|
|
32
33
|
"react-native": ">=0.74.0"
|
|
33
34
|
},
|
|
@@ -36,9 +37,13 @@
|
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@types/react": "~19.1.10",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
41
|
+
"@typescript-eslint/parser": "^7.0.0",
|
|
42
|
+
"@umituz/react-native-ai-generation-content": "^1.16.0",
|
|
43
|
+
"eslint": "^8.57.0",
|
|
39
44
|
"react": "19.1.0",
|
|
40
45
|
"react-native": "0.81.5",
|
|
41
|
-
"typescript": "
|
|
46
|
+
"typescript": "^5.3.0"
|
|
42
47
|
},
|
|
43
48
|
"publishConfig": {
|
|
44
49
|
"access": "public"
|
|
@@ -48,4 +53,4 @@
|
|
|
48
53
|
"README.md",
|
|
49
54
|
"LICENSE"
|
|
50
55
|
]
|
|
51
|
-
}
|
|
56
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @umituz/react-native-ai-fal-provider
|
|
3
|
-
* FAL AI provider
|
|
3
|
+
* FAL AI provider for React Native - implements IAIProvider interface
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
6
|
* import {
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* FalProvider,
|
|
8
|
+
* falProvider,
|
|
9
|
+
* providerRegistry,
|
|
10
10
|
* } from '@umituz/react-native-ai-fal-provider';
|
|
11
|
+
* import { providerRegistry } from '@umituz/react-native-ai-generation-content';
|
|
12
|
+
*
|
|
13
|
+
* // Register provider at app startup
|
|
14
|
+
* falProvider.initialize({ apiKey: 'your-api-key' });
|
|
15
|
+
* providerRegistry.register(falProvider);
|
|
16
|
+
* providerRegistry.setActiveProvider('fal');
|
|
11
17
|
*/
|
|
12
18
|
|
|
13
19
|
// =============================================================================
|
|
@@ -37,7 +43,13 @@ export type {
|
|
|
37
43
|
} from "./domain/entities/error.types";
|
|
38
44
|
|
|
39
45
|
// =============================================================================
|
|
40
|
-
// INFRASTRUCTURE LAYER -
|
|
46
|
+
// INFRASTRUCTURE LAYER - Provider (IAIProvider Implementation)
|
|
47
|
+
// =============================================================================
|
|
48
|
+
|
|
49
|
+
export { FalProvider, falProvider } from "./infrastructure/services";
|
|
50
|
+
|
|
51
|
+
// =============================================================================
|
|
52
|
+
// INFRASTRUCTURE LAYER - Services (Low-level client)
|
|
41
53
|
// =============================================================================
|
|
42
54
|
|
|
43
55
|
export { falClientService } from "./infrastructure/services";
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FAL Provider
|
|
3
|
+
* Implements IAIProvider interface for unified AI generation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { fal } from "@fal-ai/client";
|
|
7
|
+
import type {
|
|
8
|
+
IAIProvider,
|
|
9
|
+
AIProviderConfig,
|
|
10
|
+
JobSubmission,
|
|
11
|
+
JobStatus,
|
|
12
|
+
AIJobStatusType,
|
|
13
|
+
SubscribeOptions,
|
|
14
|
+
} from "@umituz/react-native-ai-generation-content";
|
|
15
|
+
import type { FalQueueStatus, FalLogEntry } from "../../domain/entities/fal.types";
|
|
16
|
+
|
|
17
|
+
declare const __DEV__: boolean;
|
|
18
|
+
|
|
19
|
+
const DEFAULT_CONFIG = {
|
|
20
|
+
maxRetries: 3,
|
|
21
|
+
baseDelay: 1000,
|
|
22
|
+
maxDelay: 10000,
|
|
23
|
+
defaultTimeoutMs: 300000,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function mapFalStatusToJobStatus(status: FalQueueStatus): JobStatus {
|
|
27
|
+
const statusMap: Record<string, AIJobStatusType> = {
|
|
28
|
+
IN_QUEUE: "IN_QUEUE",
|
|
29
|
+
IN_PROGRESS: "IN_PROGRESS",
|
|
30
|
+
COMPLETED: "COMPLETED",
|
|
31
|
+
FAILED: "FAILED",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
status: statusMap[status.status] ?? "IN_PROGRESS",
|
|
36
|
+
logs: status.logs?.map((log: FalLogEntry) => ({
|
|
37
|
+
message: log.message,
|
|
38
|
+
level: log.level ?? "info",
|
|
39
|
+
timestamp: log.timestamp,
|
|
40
|
+
})),
|
|
41
|
+
queuePosition: status.queuePosition,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class FalProvider implements IAIProvider {
|
|
46
|
+
readonly providerId = "fal";
|
|
47
|
+
readonly providerName = "FAL AI";
|
|
48
|
+
|
|
49
|
+
private apiKey: string | null = null;
|
|
50
|
+
private config: AIProviderConfig | null = null;
|
|
51
|
+
private initialized = false;
|
|
52
|
+
|
|
53
|
+
initialize(config: AIProviderConfig): void {
|
|
54
|
+
this.apiKey = config.apiKey;
|
|
55
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
56
|
+
|
|
57
|
+
fal.config({
|
|
58
|
+
credentials: config.apiKey,
|
|
59
|
+
retry: {
|
|
60
|
+
maxRetries: config.maxRetries ?? DEFAULT_CONFIG.maxRetries,
|
|
61
|
+
baseDelay: config.baseDelay ?? DEFAULT_CONFIG.baseDelay,
|
|
62
|
+
maxDelay: config.maxDelay ?? DEFAULT_CONFIG.maxDelay,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this.initialized = true;
|
|
67
|
+
|
|
68
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
69
|
+
// eslint-disable-next-line no-console
|
|
70
|
+
console.log("[FalProvider] Initialized");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
isInitialized(): boolean {
|
|
75
|
+
return this.initialized;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private validateInitialization(): void {
|
|
79
|
+
if (!this.apiKey || !this.initialized) {
|
|
80
|
+
throw new Error("FAL provider not initialized. Call initialize() first.");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async submitJob(
|
|
85
|
+
model: string,
|
|
86
|
+
input: Record<string, unknown>,
|
|
87
|
+
): Promise<JobSubmission> {
|
|
88
|
+
this.validateInitialization();
|
|
89
|
+
|
|
90
|
+
const result = await fal.queue.submit(model, { input });
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
requestId: result.request_id,
|
|
94
|
+
statusUrl: result.status_url,
|
|
95
|
+
responseUrl: result.response_url,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async getJobStatus(model: string, requestId: string): Promise<JobStatus> {
|
|
100
|
+
this.validateInitialization();
|
|
101
|
+
|
|
102
|
+
const status = await fal.queue.status(model, { requestId, logs: true });
|
|
103
|
+
|
|
104
|
+
return mapFalStatusToJobStatus(status as unknown as FalQueueStatus);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async getJobResult<T = unknown>(model: string, requestId: string): Promise<T> {
|
|
108
|
+
this.validateInitialization();
|
|
109
|
+
|
|
110
|
+
const result = await fal.queue.result(model, { requestId });
|
|
111
|
+
|
|
112
|
+
return result.data as T;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async subscribe<T = unknown>(
|
|
116
|
+
model: string,
|
|
117
|
+
input: Record<string, unknown>,
|
|
118
|
+
options?: SubscribeOptions<T>,
|
|
119
|
+
): Promise<T> {
|
|
120
|
+
this.validateInitialization();
|
|
121
|
+
|
|
122
|
+
const timeoutMs = options?.timeoutMs ?? this.config?.defaultTimeoutMs ?? DEFAULT_CONFIG.defaultTimeoutMs;
|
|
123
|
+
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
124
|
+
|
|
125
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
126
|
+
// eslint-disable-next-line no-console
|
|
127
|
+
console.log("[FalProvider] Subscribe started:", { model, timeoutMs });
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const result = await Promise.race([
|
|
132
|
+
fal.subscribe(model, {
|
|
133
|
+
input,
|
|
134
|
+
onQueueUpdate: (update) => {
|
|
135
|
+
const jobStatus = mapFalStatusToJobStatus(update as unknown as FalQueueStatus);
|
|
136
|
+
options?.onQueueUpdate?.(jobStatus);
|
|
137
|
+
},
|
|
138
|
+
}),
|
|
139
|
+
new Promise<never>((_, reject) => {
|
|
140
|
+
timeoutId = setTimeout(
|
|
141
|
+
() => reject(new Error("FAL subscription timeout")),
|
|
142
|
+
timeoutMs,
|
|
143
|
+
);
|
|
144
|
+
}),
|
|
145
|
+
]);
|
|
146
|
+
|
|
147
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
148
|
+
// eslint-disable-next-line no-console
|
|
149
|
+
console.log("[FalProvider] Subscribe completed:", { model });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
options?.onResult?.(result as T);
|
|
153
|
+
|
|
154
|
+
return result as T;
|
|
155
|
+
} finally {
|
|
156
|
+
if (timeoutId) {
|
|
157
|
+
clearTimeout(timeoutId);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async run<T = unknown>(model: string, input: Record<string, unknown>): Promise<T> {
|
|
163
|
+
this.validateInitialization();
|
|
164
|
+
|
|
165
|
+
const result = await fal.run(model, { input });
|
|
166
|
+
|
|
167
|
+
return result as T;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
reset(): void {
|
|
171
|
+
this.apiKey = null;
|
|
172
|
+
this.config = null;
|
|
173
|
+
this.initialized = false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export const falProvider = new FalProvider();
|