@apicity/fal 0.1.0-alpha.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.
@@ -0,0 +1,1223 @@
1
+ import { FalError, } from "./types.js";
2
+ import { FalPricingEstimateRequestSchema, FalDeletePayloadsRequestSchema, FalQueueSubmitRequestSchema, FalLogsStreamRequestSchema, FalFilesUploadUrlRequestSchema, FalFilesUploadLocalRequestSchema, FalSeedance2p0ImageToVideoRequestSchema, FalSeedance2p0TextToVideoRequestSchema, FalSeedance2p0FastImageToVideoRequestSchema, FalSeedance2p0FastTextToVideoRequestSchema, FalSeedance2p0ReferenceToVideoRequestSchema, FalSeedance2p0FastReferenceToVideoRequestSchema, FalNanoBananaProTextToImageRequestSchema, FalNanoBananaProEditRequestSchema, FalNanoBanana2TextToImageRequestSchema, FalNanoBanana2EditRequestSchema, FalSeedreamV5LiteEditRequestSchema, FalSeedreamV5LiteTextToImageRequestSchema, FalElevenlabsSpeechToTextScribeV2RequestSchema, FalWanV2p7TextToImageRequestSchema, FalWanV2p7EditRequestSchema, FalWanV2p7TextToVideoRequestSchema, FalWanV2p7ImageToVideoRequestSchema, FalWanV2p7ReferenceToVideoRequestSchema, FalWanV2p7EditVideoRequestSchema, FalXaiGrokImagineImageRequestSchema, FalXaiGrokImagineImageEditRequestSchema, FalQwenImageRequestSchema, FalQwenImageEditRequestSchema, FalGptImage1p5RequestSchema, FalGptImage1p5EditRequestSchema, FalNanoBananaTextToImageRequestSchema, FalNanoBananaEditRequestSchema, FalXaiGrokImagineVideoImageToVideoRequestSchema, FalXaiGrokImagineVideoReferenceToVideoRequestSchema, FalXaiGrokImagineVideoExtendVideoRequestSchema, FalXaiGrokImagineVideoEditVideoRequestSchema, FalVeo3p1TextToVideoRequestSchema, FalVeo3p1ImageToVideoRequestSchema, FalStorageUploadInitiateRequestSchema, FalStorageUploadInitiateMultipartRequestSchema, FalStorageUploadCompleteMultipartRequestSchema, FalKlingVideoV3ProImageToVideoRequestSchema, FalKlingVideoV3ProTextToVideoRequestSchema, FalKlingVideoV3StandardImageToVideoRequestSchema, FalKlingVideoV3StandardTextToVideoRequestSchema, FalKlingVideoO3p4kImageToVideoRequestSchema, FalKlingVideoO3p4kReferenceToVideoRequestSchema, FalKlingVideoO3p4kTextToVideoRequestSchema, FalSora2TextToVideoRequestSchema, FalSora2ImageToVideoRequestSchema, FalHunyuanImageV3InstructEditRequestSchema, } from "./zod.js";
3
+ import { attachExamples } from "./example.js";
4
+ // Helper function to safely handle AbortSignal across different environments
5
+ function attachAbortHandler(signal, controller) {
6
+ if (!signal)
7
+ return;
8
+ // Handle both standard AbortSignal and node-fetch's AbortSignal
9
+ if (typeof signal.addEventListener === "function") {
10
+ signal.addEventListener("abort", () => controller.abort(), { once: true });
11
+ }
12
+ else if (signal.aborted) {
13
+ // Already aborted, abort our controller too
14
+ controller.abort();
15
+ }
16
+ }
17
+ // Build query string from parameters (no case conversion)
18
+ export function buildQueryString(params) {
19
+ const searchParams = new URLSearchParams();
20
+ for (const [key, value] of Object.entries(params)) {
21
+ if (value === undefined)
22
+ continue;
23
+ if (Array.isArray(value)) {
24
+ for (const item of value) {
25
+ searchParams.append(key, String(item));
26
+ }
27
+ }
28
+ else {
29
+ searchParams.append(key, String(value));
30
+ }
31
+ }
32
+ const queryString = searchParams.toString();
33
+ return queryString ? `?${queryString}` : "";
34
+ }
35
+ function isFalApiErrorResponse(data) {
36
+ return (typeof data === "object" &&
37
+ data !== null &&
38
+ "error" in data &&
39
+ typeof data.error === "object" &&
40
+ data.error !== null);
41
+ }
42
+ // SSE stream parser: yields parsed data payloads from an SSE Response
43
+ async function* sseToIterable(res) {
44
+ if (!res.body)
45
+ return;
46
+ const reader = res.body.getReader();
47
+ const decoder = new TextDecoder();
48
+ let buffer = "";
49
+ while (true) {
50
+ const { value, done } = await reader.read();
51
+ if (done)
52
+ break;
53
+ buffer += decoder.decode(value, { stream: true });
54
+ const parts = buffer.split(/\r?\n\r?\n/);
55
+ for (let i = 0; i < parts.length - 1; i++) {
56
+ const chunk = parts[i];
57
+ const lines = chunk.split(/\r?\n/);
58
+ for (const line of lines) {
59
+ const trimmed = line.trimStart();
60
+ if (trimmed.startsWith("data:")) {
61
+ const payload = trimmed.slice(5).trim();
62
+ if (payload) {
63
+ yield JSON.parse(payload);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ buffer = parts[parts.length - 1];
69
+ }
70
+ const trailing = buffer.trim();
71
+ if (trailing.length) {
72
+ const lines = trailing.split(/\r?\n/);
73
+ for (const line of lines) {
74
+ const trimmed = line.trimStart();
75
+ if (trimmed.startsWith("data:")) {
76
+ const payload = trimmed.slice(5).trim();
77
+ if (payload) {
78
+ yield JSON.parse(payload);
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ export function fal(opts) {
85
+ const baseURL = opts.baseURL ?? "https://api.fal.ai/v1";
86
+ const doFetch = opts.fetch ?? fetch;
87
+ const timeout = opts.timeout ?? 30000;
88
+ async function makeRequest(method, path, paramsOrBody, signal, headers, customBaseURL) {
89
+ const controller = new AbortController();
90
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
91
+ if (signal) {
92
+ attachAbortHandler(signal, controller);
93
+ }
94
+ const base = customBaseURL ?? baseURL;
95
+ const url = method === "GET" && paramsOrBody
96
+ ? `${base}${path}${buildQueryString(paramsOrBody)}`
97
+ : `${base}${path}`;
98
+ const requestInit = {
99
+ method,
100
+ headers: {
101
+ Authorization: `Key ${opts.apiKey}`,
102
+ "Content-Type": "application/json",
103
+ ...headers,
104
+ },
105
+ signal: controller.signal,
106
+ };
107
+ if (method !== "GET" && paramsOrBody) {
108
+ requestInit.body = JSON.stringify(paramsOrBody);
109
+ }
110
+ try {
111
+ const res = await doFetch(url, requestInit);
112
+ clearTimeout(timeoutId);
113
+ if (!res.ok) {
114
+ let errorData;
115
+ try {
116
+ errorData = await res.json();
117
+ }
118
+ catch {
119
+ errorData = null;
120
+ }
121
+ if (isFalApiErrorResponse(errorData)) {
122
+ throw new FalError(errorData.error.message, res.status, errorData.error.type, errorData.error.request_id, errorData.error.docs_url, errorData);
123
+ }
124
+ throw new FalError(`Fal API error: ${res.status}`, res.status, "server_error", undefined, undefined, errorData);
125
+ }
126
+ if (res.status === 204) {
127
+ return undefined;
128
+ }
129
+ return (await res.json());
130
+ }
131
+ catch (error) {
132
+ clearTimeout(timeoutId);
133
+ if (error instanceof FalError)
134
+ throw error;
135
+ throw new FalError(`Fal request failed: ${error}`, 500, "server_error");
136
+ }
137
+ }
138
+ async function makeStreamPostWithQuery(path, queryParams, body, signal) {
139
+ const qs = buildQueryString(queryParams);
140
+ const url = `${baseURL}${path}${qs}`;
141
+ const controller = new AbortController();
142
+ // No timeout for stream — connections are long-lived
143
+ if (signal) {
144
+ attachAbortHandler(signal, controller);
145
+ }
146
+ const requestInit = {
147
+ method: "POST",
148
+ headers: {
149
+ Authorization: `Key ${opts.apiKey}`,
150
+ "Content-Type": "application/json",
151
+ Accept: "text/event-stream",
152
+ },
153
+ signal: controller.signal,
154
+ };
155
+ if (body !== undefined) {
156
+ requestInit.body = JSON.stringify(body);
157
+ }
158
+ const res = await doFetch(url, requestInit);
159
+ if (!res.ok) {
160
+ let errorData;
161
+ try {
162
+ errorData = await res.json();
163
+ }
164
+ catch {
165
+ errorData = null;
166
+ }
167
+ if (isFalApiErrorResponse(errorData)) {
168
+ throw new FalError(errorData.error.message, res.status, errorData.error.type, errorData.error.request_id, errorData.error.docs_url, errorData);
169
+ }
170
+ throw new FalError(`Fal API error: ${res.status}`, res.status, "server_error", undefined, undefined, errorData);
171
+ }
172
+ return res;
173
+ }
174
+ async function makeRawRequest(method, path, body, signal, queryParams) {
175
+ const controller = new AbortController();
176
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
177
+ if (signal) {
178
+ attachAbortHandler(signal, controller);
179
+ }
180
+ let url = `${baseURL}${path}`;
181
+ if (queryParams) {
182
+ url += buildQueryString(queryParams);
183
+ }
184
+ const requestInit = {
185
+ method,
186
+ headers: {
187
+ Authorization: `Key ${opts.apiKey}`,
188
+ },
189
+ signal: controller.signal,
190
+ };
191
+ if (body) {
192
+ requestInit.body = body;
193
+ }
194
+ try {
195
+ const res = await doFetch(url, requestInit);
196
+ clearTimeout(timeoutId);
197
+ if (!res.ok) {
198
+ let errorData;
199
+ try {
200
+ errorData = await res.json();
201
+ }
202
+ catch {
203
+ errorData = null;
204
+ }
205
+ if (isFalApiErrorResponse(errorData)) {
206
+ throw new FalError(errorData.error.message, res.status, errorData.error.type, errorData.error.request_id, errorData.error.docs_url, errorData);
207
+ }
208
+ throw new FalError(`Fal API error: ${res.status}`, res.status, "server_error", undefined, undefined, errorData);
209
+ }
210
+ return res;
211
+ }
212
+ catch (error) {
213
+ clearTimeout(timeoutId);
214
+ if (error instanceof FalError)
215
+ throw error;
216
+ throw new FalError(`Fal request failed: ${error}`, 500, "server_error");
217
+ }
218
+ }
219
+ // GET https://api.fal.ai/v1/models/pricing
220
+ // Docs: https://docs.fal.ai
221
+ const pricing = Object.assign(async function pricing(params, signal) {
222
+ return makeRequest("GET", "/models/pricing", params, signal);
223
+ }, {
224
+ // POST https://api.fal.ai/v1/models/pricing/estimate
225
+ // Docs: https://docs.fal.ai
226
+ estimate: Object.assign(async function estimate(req, signal) {
227
+ return makeRequest("POST", "/models/pricing/estimate", req, signal);
228
+ }, {
229
+ schema: FalPricingEstimateRequestSchema,
230
+ }),
231
+ });
232
+ const requests = {
233
+ async byEndpoint(params, signal) {
234
+ return makeRequest("GET", "/models/requests/by-endpoint", params, signal);
235
+ },
236
+ // DELETE https://api.fal.ai/v1/models/requests/{param}/payloads
237
+ // Docs: https://docs.fal.ai
238
+ payloads: Object.assign(async function payloads(params, signal) {
239
+ const headers = {};
240
+ if (params.idempotency_key) {
241
+ headers["Idempotency-Key"] = params.idempotency_key;
242
+ }
243
+ return makeRequest("DELETE", `/models/requests/${params.request_id}/payloads`, undefined, signal, headers);
244
+ }, {
245
+ schema: FalDeletePayloadsRequestSchema,
246
+ }),
247
+ };
248
+ // GET https://api.fal.ai/v1/models
249
+ // Docs: https://docs.fal.ai
250
+ const models = Object.assign(async function models(params, signal) {
251
+ return makeRequest("GET", "/models", params, signal);
252
+ }, {
253
+ pricing,
254
+ async usage(params, signal) {
255
+ return makeRequest("GET", "/models/usage", params, signal);
256
+ },
257
+ async analytics(params, signal) {
258
+ return makeRequest("GET", "/models/analytics", params, signal);
259
+ },
260
+ requests,
261
+ });
262
+ const queueBaseURL = opts.queueBaseURL ?? "https://queue.fal.run";
263
+ const runBaseURL = opts.runBaseURL ?? "https://fal.run";
264
+ const restBaseURL = opts.restBaseURL ?? "https://rest.fal.ai";
265
+ // sig-ok: stylistic dotPath divergence from URL
266
+ // POST https://api.fal.ai/v1/bytedance/seedance-2.0/image-to-video
267
+ // Docs: https://docs.fal.ai
268
+ const bytedanceSeedance2p0ImageToVideo = Object.assign(async function imageToVideo(params, signal) {
269
+ return makeRequest("POST", "/bytedance/seedance-2.0/image-to-video", params, signal, undefined, runBaseURL);
270
+ }, {
271
+ schema: FalSeedance2p0ImageToVideoRequestSchema,
272
+ });
273
+ // sig-ok: stylistic dotPath divergence from URL
274
+ // POST https://api.fal.ai/v1/bytedance/seedance-2.0/text-to-video
275
+ // Docs: https://docs.fal.ai
276
+ const bytedanceSeedance2p0TextToVideo = Object.assign(async function textToVideo(params, signal) {
277
+ return makeRequest("POST", "/bytedance/seedance-2.0/text-to-video", params, signal, undefined, runBaseURL);
278
+ }, {
279
+ schema: FalSeedance2p0TextToVideoRequestSchema,
280
+ });
281
+ // sig-ok: stylistic dotPath divergence from URL
282
+ // POST https://api.fal.ai/v1/bytedance/seedance-2.0/fast/image-to-video
283
+ // Docs: https://docs.fal.ai
284
+ const bytedanceSeedance2p0FastImageToVideo = Object.assign(async function imageToVideo(params, signal) {
285
+ return makeRequest("POST", "/bytedance/seedance-2.0/fast/image-to-video", params, signal, undefined, runBaseURL);
286
+ }, {
287
+ schema: FalSeedance2p0FastImageToVideoRequestSchema,
288
+ });
289
+ // sig-ok: stylistic dotPath divergence from URL
290
+ // POST https://api.fal.ai/v1/bytedance/seedance-2.0/fast/text-to-video
291
+ // Docs: https://docs.fal.ai
292
+ const bytedanceSeedance2p0FastTextToVideo = Object.assign(async function textToVideo(params, signal) {
293
+ return makeRequest("POST", "/bytedance/seedance-2.0/fast/text-to-video", params, signal, undefined, runBaseURL);
294
+ }, {
295
+ schema: FalSeedance2p0FastTextToVideoRequestSchema,
296
+ });
297
+ // sig-ok: stylistic dotPath divergence from URL
298
+ // POST https://api.fal.ai/v1/bytedance/seedance-2.0/reference-to-video
299
+ // Docs: https://docs.fal.ai
300
+ const bytedanceSeedance2p0ReferenceToVideo = Object.assign(async function referenceToVideo(params, signal) {
301
+ return makeRequest("POST", "/bytedance/seedance-2.0/reference-to-video", params, signal, undefined, runBaseURL);
302
+ }, {
303
+ schema: FalSeedance2p0ReferenceToVideoRequestSchema,
304
+ });
305
+ // sig-ok: stylistic dotPath divergence from URL
306
+ // POST https://api.fal.ai/v1/bytedance/seedance-2.0/fast/reference-to-video
307
+ // Docs: https://docs.fal.ai
308
+ const bytedanceSeedance2p0FastReferenceToVideo = Object.assign(async function referenceToVideo(params, signal) {
309
+ return makeRequest("POST", "/bytedance/seedance-2.0/fast/reference-to-video", params, signal, undefined, runBaseURL);
310
+ }, {
311
+ schema: FalSeedance2p0FastReferenceToVideoRequestSchema,
312
+ });
313
+ // sig-ok: stylistic dotPath divergence from URL
314
+ // POST https://api.fal.ai/v1/fal-ai/nano-banana-pro/edit
315
+ // Docs: https://docs.fal.ai
316
+ const nanoBananaProEdit = Object.assign(async function edit(params, signal) {
317
+ return makeRequest("POST", "/fal-ai/nano-banana-pro/edit", { safety_tolerance: "6", ...params }, signal, undefined, runBaseURL);
318
+ }, {
319
+ schema: FalNanoBananaProEditRequestSchema,
320
+ });
321
+ // sig-ok: stylistic dotPath divergence from URL
322
+ // POST https://api.fal.ai/v1/fal-ai/nano-banana-pro
323
+ // Docs: https://docs.fal.ai
324
+ const nanoBananaProTextToImage = Object.assign(async function textToImage(params, signal) {
325
+ return makeRequest("POST", "/fal-ai/nano-banana-pro", { safety_tolerance: "6", ...params }, signal, undefined, runBaseURL);
326
+ }, {
327
+ schema: FalNanoBananaProTextToImageRequestSchema,
328
+ });
329
+ // sig-ok: stylistic dotPath divergence from URL
330
+ // POST https://api.fal.ai/v1/fal-ai/nano-banana
331
+ // Docs: https://docs.fal.ai
332
+ const nanoBananaTextToImage = Object.assign(async function textToImage(params, signal) {
333
+ return makeRequest("POST", "/fal-ai/nano-banana", params, signal, undefined, runBaseURL);
334
+ }, {
335
+ schema: FalNanoBananaTextToImageRequestSchema,
336
+ });
337
+ // sig-ok: stylistic dotPath divergence from URL
338
+ // POST https://api.fal.ai/v1/fal-ai/nano-banana/edit
339
+ // Docs: https://docs.fal.ai
340
+ const nanoBananaEdit = Object.assign(async function edit(params, signal) {
341
+ return makeRequest("POST", "/fal-ai/nano-banana/edit", params, signal, undefined, runBaseURL);
342
+ }, {
343
+ schema: FalNanoBananaEditRequestSchema,
344
+ });
345
+ // sig-ok: stylistic dotPath divergence from URL
346
+ // POST https://api.fal.ai/v1/fal-ai/nano-banana-2
347
+ // Docs: https://docs.fal.ai
348
+ const nanoBanana2TextToImage = Object.assign(async function textToImage(params, signal) {
349
+ return makeRequest("POST", "/fal-ai/nano-banana-2", params, signal, undefined, runBaseURL);
350
+ }, {
351
+ schema: FalNanoBanana2TextToImageRequestSchema,
352
+ });
353
+ // sig-ok: stylistic dotPath divergence from URL
354
+ // POST https://api.fal.ai/v1/fal-ai/nano-banana-2/edit
355
+ // Docs: https://docs.fal.ai
356
+ const nanoBanana2Edit = Object.assign(async function edit(params, signal) {
357
+ return makeRequest("POST", "/fal-ai/nano-banana-2/edit", params, signal, undefined, runBaseURL);
358
+ }, {
359
+ schema: FalNanoBanana2EditRequestSchema,
360
+ });
361
+ // sig-ok: stylistic dotPath divergence from URL
362
+ // POST https://api.fal.ai/v1/fal-ai/bytedance/seedream/v5/lite/edit
363
+ // Docs: https://docs.fal.ai
364
+ const seedreamV5LiteEdit = Object.assign(async function edit(params, signal) {
365
+ return makeRequest("POST", "/fal-ai/bytedance/seedream/v5/lite/edit", { enable_safety_checker: false, ...params }, signal, undefined, runBaseURL);
366
+ }, {
367
+ schema: FalSeedreamV5LiteEditRequestSchema,
368
+ });
369
+ // sig-ok: stylistic dotPath divergence from URL
370
+ // POST https://api.fal.ai/v1/fal-ai/bytedance/seedream/v5/lite/text-to-image
371
+ // Docs: https://docs.fal.ai
372
+ const seedreamV5LiteTextToImage = Object.assign(async function textToImage(params, signal) {
373
+ return makeRequest("POST", "/fal-ai/bytedance/seedream/v5/lite/text-to-image", { enable_safety_checker: false, ...params }, signal, undefined, runBaseURL);
374
+ }, {
375
+ schema: FalSeedreamV5LiteTextToImageRequestSchema,
376
+ });
377
+ // sig-ok: stylistic dotPath divergence from URL
378
+ // POST https://api.fal.ai/v1/fal-ai/elevenlabs/speech-to-text/scribe-v2
379
+ // Docs: https://docs.fal.ai
380
+ const elevenlabsSpeechToTextScribeV2 = Object.assign(async function scribeV2(params, signal) {
381
+ return makeRequest("POST", "/fal-ai/elevenlabs/speech-to-text/scribe-v2", params, signal, undefined, runBaseURL);
382
+ }, {
383
+ schema: FalElevenlabsSpeechToTextScribeV2RequestSchema,
384
+ });
385
+ // sig-ok: stylistic dotPath divergence from URL
386
+ // POST https://api.fal.ai/v1/fal-ai/wan/v2.7/text-to-image
387
+ // Docs: https://docs.fal.ai
388
+ const wanV2p7TextToImage = Object.assign(async function textToImage(params, signal) {
389
+ return makeRequest("POST", "/fal-ai/wan/v2.7/text-to-image", params, signal, undefined, runBaseURL);
390
+ }, {
391
+ schema: FalWanV2p7TextToImageRequestSchema,
392
+ });
393
+ // sig-ok: stylistic dotPath divergence from URL
394
+ // POST https://api.fal.ai/v1/fal-ai/wan/v2.7/edit
395
+ // Docs: https://docs.fal.ai
396
+ const wanV2p7Edit = Object.assign(async function edit(params, signal) {
397
+ return makeRequest("POST", "/fal-ai/wan/v2.7/edit", params, signal, undefined, runBaseURL);
398
+ }, {
399
+ schema: FalWanV2p7EditRequestSchema,
400
+ });
401
+ // sig-ok: stylistic dotPath divergence from URL
402
+ // POST https://api.fal.ai/v1/fal-ai/wan/v2.7/pro/text-to-image
403
+ // Docs: https://docs.fal.ai
404
+ const wanV2p7ProTextToImage = Object.assign(async function textToImage(params, signal) {
405
+ return makeRequest("POST", "/fal-ai/wan/v2.7/pro/text-to-image", params, signal, undefined, runBaseURL);
406
+ }, {
407
+ schema: FalWanV2p7TextToImageRequestSchema,
408
+ });
409
+ // sig-ok: stylistic dotPath divergence from URL
410
+ // POST https://api.fal.ai/v1/fal-ai/wan/v2.7/pro/edit
411
+ // Docs: https://docs.fal.ai
412
+ const wanV2p7ProEdit = Object.assign(async function edit(params, signal) {
413
+ return makeRequest("POST", "/fal-ai/wan/v2.7/pro/edit", params, signal, undefined, runBaseURL);
414
+ }, {
415
+ schema: FalWanV2p7EditRequestSchema,
416
+ });
417
+ // sig-ok: stylistic dotPath divergence from URL
418
+ // POST https://api.fal.ai/v1/fal-ai/wan/v2.7/text-to-video
419
+ // Docs: https://docs.fal.ai
420
+ const wanV2p7TextToVideo = Object.assign(async function textToVideo(params, signal) {
421
+ return makeRequest("POST", "/fal-ai/wan/v2.7/text-to-video", params, signal, undefined, runBaseURL);
422
+ }, {
423
+ schema: FalWanV2p7TextToVideoRequestSchema,
424
+ });
425
+ // sig-ok: stylistic dotPath divergence from URL
426
+ // POST https://api.fal.ai/v1/fal-ai/wan/v2.7/image-to-video
427
+ // Docs: https://docs.fal.ai
428
+ const wanV2p7ImageToVideo = Object.assign(async function imageToVideo(params, signal) {
429
+ return makeRequest("POST", "/fal-ai/wan/v2.7/image-to-video", params, signal, undefined, runBaseURL);
430
+ }, {
431
+ schema: FalWanV2p7ImageToVideoRequestSchema,
432
+ });
433
+ // sig-ok: stylistic dotPath divergence from URL
434
+ // POST https://api.fal.ai/v1/fal-ai/wan/v2.7/reference-to-video
435
+ // Docs: https://docs.fal.ai
436
+ const wanV2p7ReferenceToVideo = Object.assign(async function referenceToVideo(params, signal) {
437
+ return makeRequest("POST", "/fal-ai/wan/v2.7/reference-to-video", params, signal, undefined, runBaseURL);
438
+ }, {
439
+ schema: FalWanV2p7ReferenceToVideoRequestSchema,
440
+ });
441
+ // sig-ok: stylistic dotPath divergence from URL
442
+ // POST https://api.fal.ai/v1/fal-ai/wan/v2.7/edit-video
443
+ // Docs: https://docs.fal.ai
444
+ const wanV2p7EditVideo = Object.assign(async function editVideo(params, signal) {
445
+ return makeRequest("POST", "/fal-ai/wan/v2.7/edit-video", params, signal, undefined, runBaseURL);
446
+ }, {
447
+ schema: FalWanV2p7EditVideoRequestSchema,
448
+ });
449
+ // sig-ok: stylistic dotPath divergence from URL
450
+ // POST https://api.fal.ai/v1/xai/grok-imagine-image/edit
451
+ // Docs: https://docs.fal.ai
452
+ const xaiGrokImagineImageEdit = Object.assign(async function edit(params, signal) {
453
+ return makeRequest("POST", "/xai/grok-imagine-image/edit", params, signal, undefined, runBaseURL);
454
+ }, {
455
+ schema: FalXaiGrokImagineImageEditRequestSchema,
456
+ });
457
+ // sig-ok: stylistic dotPath divergence from URL
458
+ // POST https://api.fal.ai/v1/fal-ai/sora-2/text-to-video
459
+ // Docs: https://docs.fal.ai
460
+ const sora2TextToVideo = Object.assign(async function textToVideo(params, signal) {
461
+ return makeRequest("POST", "/fal-ai/sora-2/text-to-video", params, signal, undefined, runBaseURL);
462
+ }, {
463
+ schema: FalSora2TextToVideoRequestSchema,
464
+ });
465
+ // sig-ok: stylistic dotPath divergence from URL
466
+ // POST https://api.fal.ai/v1/fal-ai/sora-2/image-to-video
467
+ // Docs: https://docs.fal.ai
468
+ const sora2ImageToVideo = Object.assign(async function imageToVideo(params, signal) {
469
+ return makeRequest("POST", "/fal-ai/sora-2/image-to-video", params, signal, undefined, runBaseURL);
470
+ }, {
471
+ schema: FalSora2ImageToVideoRequestSchema,
472
+ });
473
+ // sig-ok: stylistic dotPath divergence from URL
474
+ // POST https://api.fal.ai/v1/fal-ai/hunyuan-image/v3/instruct/edit
475
+ // Docs: https://docs.fal.ai
476
+ const hunyuanImageV3InstructEdit = Object.assign(async function v3InstructEdit(params, signal) {
477
+ return makeRequest("POST", "/fal-ai/hunyuan-image/v3/instruct/edit", params, signal, undefined, runBaseURL);
478
+ }, {
479
+ schema: FalHunyuanImageV3InstructEditRequestSchema,
480
+ });
481
+ // sig-ok: stylistic dotPath divergence from URL
482
+ // POST https://api.fal.ai/v1/fal-ai/kling-video/v3/pro/image-to-video
483
+ // Docs: https://docs.fal.ai
484
+ const klingVideoV3ProImageToVideo = Object.assign(async function imageToVideo(params, signal) {
485
+ return makeRequest("POST", "/fal-ai/kling-video/v3/pro/image-to-video", params, signal, undefined, runBaseURL);
486
+ }, {
487
+ schema: FalKlingVideoV3ProImageToVideoRequestSchema,
488
+ });
489
+ // sig-ok: stylistic dotPath divergence from URL
490
+ // POST https://api.fal.ai/v1/fal-ai/kling-video/v3/pro/text-to-video
491
+ // Docs: https://docs.fal.ai
492
+ const klingVideoV3ProTextToVideo = Object.assign(async function textToVideo(params, signal) {
493
+ return makeRequest("POST", "/fal-ai/kling-video/v3/pro/text-to-video", params, signal, undefined, runBaseURL);
494
+ }, {
495
+ schema: FalKlingVideoV3ProTextToVideoRequestSchema,
496
+ });
497
+ // sig-ok: stylistic dotPath divergence from URL
498
+ // POST https://api.fal.ai/v1/fal-ai/kling-video/v3/standard/image-to-video
499
+ // Docs: https://docs.fal.ai
500
+ const klingVideoV3StandardImageToVideo = Object.assign(async function imageToVideo(params, signal) {
501
+ return makeRequest("POST", "/fal-ai/kling-video/v3/standard/image-to-video", params, signal, undefined, runBaseURL);
502
+ }, {
503
+ schema: FalKlingVideoV3StandardImageToVideoRequestSchema,
504
+ });
505
+ // sig-ok: stylistic dotPath divergence from URL
506
+ // POST https://api.fal.ai/v1/fal-ai/kling-video/v3/standard/text-to-video
507
+ // Docs: https://docs.fal.ai
508
+ const klingVideoV3StandardTextToVideo = Object.assign(async function textToVideo(params, signal) {
509
+ return makeRequest("POST", "/fal-ai/kling-video/v3/standard/text-to-video", params, signal, undefined, runBaseURL);
510
+ }, {
511
+ schema: FalKlingVideoV3StandardTextToVideoRequestSchema,
512
+ });
513
+ // sig-ok: stylistic dotPath divergence from URL
514
+ // POST https://api.fal.ai/v1/fal-ai/kling-video/o3/4k/image-to-video
515
+ // Docs: https://docs.fal.ai
516
+ const klingVideoO3p4kImageToVideo = Object.assign(async function imageToVideo(params, signal) {
517
+ return makeRequest("POST", "/fal-ai/kling-video/o3/4k/image-to-video", params, signal, undefined, runBaseURL);
518
+ }, {
519
+ schema: FalKlingVideoO3p4kImageToVideoRequestSchema,
520
+ });
521
+ // sig-ok: stylistic dotPath divergence from URL
522
+ // POST https://api.fal.ai/v1/fal-ai/kling-video/o3/4k/reference-to-video
523
+ // Docs: https://docs.fal.ai
524
+ const klingVideoO3p4kReferenceToVideo = Object.assign(async function referenceToVideo(params, signal) {
525
+ return makeRequest("POST", "/fal-ai/kling-video/o3/4k/reference-to-video", params, signal, undefined, runBaseURL);
526
+ }, {
527
+ schema: FalKlingVideoO3p4kReferenceToVideoRequestSchema,
528
+ });
529
+ // sig-ok: stylistic dotPath divergence from URL
530
+ // POST https://api.fal.ai/v1/fal-ai/kling-video/o3/4k/text-to-video
531
+ // Docs: https://docs.fal.ai
532
+ const klingVideoO3p4kTextToVideo = Object.assign(async function textToVideo(params, signal) {
533
+ return makeRequest("POST", "/fal-ai/kling-video/o3/4k/text-to-video", params, signal, undefined, runBaseURL);
534
+ }, {
535
+ schema: FalKlingVideoO3p4kTextToVideoRequestSchema,
536
+ });
537
+ // sig-ok: stylistic dotPath divergence from URL
538
+ // POST https://api.fal.ai/v1/fal-ai/veo3.1
539
+ // Docs: https://docs.fal.ai
540
+ const veo3p1TextToVideo = Object.assign(async function textToVideo(params, signal) {
541
+ return makeRequest("POST", "/fal-ai/veo3.1", params, signal, undefined, runBaseURL);
542
+ }, {
543
+ schema: FalVeo3p1TextToVideoRequestSchema,
544
+ });
545
+ // sig-ok: stylistic dotPath divergence from URL
546
+ // POST https://api.fal.ai/v1/fal-ai/veo3.1/image-to-video
547
+ // Docs: https://docs.fal.ai
548
+ const veo3p1ImageToVideo = Object.assign(async function imageToVideo(params, signal) {
549
+ return makeRequest("POST", "/fal-ai/veo3.1/image-to-video", params, signal, undefined, runBaseURL);
550
+ }, {
551
+ schema: FalVeo3p1ImageToVideoRequestSchema,
552
+ });
553
+ // sig-ok: stylistic dotPath divergence from URL
554
+ // POST https://api.fal.ai/v1/xai/grok-imagine-video/image-to-video
555
+ // Docs: https://docs.fal.ai
556
+ const xaiGrokImagineVideoImageToVideo = Object.assign(async function imageToVideo(params, signal) {
557
+ return makeRequest("POST", "/xai/grok-imagine-video/image-to-video", params, signal, undefined, runBaseURL);
558
+ }, {
559
+ schema: FalXaiGrokImagineVideoImageToVideoRequestSchema,
560
+ });
561
+ // sig-ok: stylistic dotPath divergence from URL
562
+ // POST https://api.fal.ai/v1/xai/grok-imagine-video/reference-to-video
563
+ // Docs: https://docs.fal.ai
564
+ const xaiGrokImagineVideoReferenceToVideo = Object.assign(async function referenceToVideo(params, signal) {
565
+ return makeRequest("POST", "/xai/grok-imagine-video/reference-to-video", params, signal, undefined, runBaseURL);
566
+ }, {
567
+ schema: FalXaiGrokImagineVideoReferenceToVideoRequestSchema,
568
+ });
569
+ // sig-ok: stylistic dotPath divergence from URL
570
+ // POST https://api.fal.ai/v1/xai/grok-imagine-video/extend-video
571
+ // Docs: https://docs.fal.ai
572
+ const xaiGrokImagineVideoExtendVideo = Object.assign(async function extendVideo(params, signal) {
573
+ return makeRequest("POST", "/xai/grok-imagine-video/extend-video", params, signal, undefined, runBaseURL);
574
+ }, {
575
+ schema: FalXaiGrokImagineVideoExtendVideoRequestSchema,
576
+ });
577
+ // sig-ok: stylistic dotPath divergence from URL
578
+ // POST https://api.fal.ai/v1/xai/grok-imagine-video/edit-video
579
+ // Docs: https://docs.fal.ai
580
+ const xaiGrokImagineVideoEditVideo = Object.assign(async function editVideo(params, signal) {
581
+ return makeRequest("POST", "/xai/grok-imagine-video/edit-video", params, signal, undefined, runBaseURL);
582
+ }, {
583
+ schema: FalXaiGrokImagineVideoEditVideoRequestSchema,
584
+ });
585
+ // sig-ok: stylistic dotPath divergence from URL
586
+ // POST https://api.fal.ai/v1/xai/grok-imagine-image
587
+ // Docs: https://docs.fal.ai
588
+ const xaiGrokImagineImage = Object.assign(async function grokImagineImage(params, signal) {
589
+ return makeRequest("POST", "/xai/grok-imagine-image", params, signal, undefined, runBaseURL);
590
+ }, {
591
+ schema: FalXaiGrokImagineImageRequestSchema,
592
+ edit: xaiGrokImagineImageEdit,
593
+ });
594
+ // sig-ok: stylistic dotPath divergence from URL
595
+ // POST https://api.fal.ai/v1/fal-ai/qwen-image-edit
596
+ // Docs: https://docs.fal.ai
597
+ const qwenImageEdit = Object.assign(async function edit(params, signal) {
598
+ return makeRequest("POST", "/fal-ai/qwen-image-edit", params, signal, undefined, runBaseURL);
599
+ }, {
600
+ schema: FalQwenImageEditRequestSchema,
601
+ });
602
+ // sig-ok: stylistic dotPath divergence from URL
603
+ // POST https://api.fal.ai/v1/fal-ai/gpt-image-1.5/edit
604
+ // Docs: https://docs.fal.ai
605
+ const gptImage1p5Edit = Object.assign(async function edit(params, signal) {
606
+ return makeRequest("POST", "/fal-ai/gpt-image-1.5/edit", params, signal, undefined, runBaseURL);
607
+ }, {
608
+ schema: FalGptImage1p5EditRequestSchema,
609
+ });
610
+ // sig-ok: stylistic dotPath divergence from URL
611
+ // POST https://api.fal.ai/v1/fal-ai/gpt-image-1.5
612
+ // Docs: https://docs.fal.ai
613
+ const gptImage1p5 = Object.assign(async function gptImage1p5(params, signal) {
614
+ return makeRequest("POST", "/fal-ai/gpt-image-1.5", params, signal, undefined, runBaseURL);
615
+ }, {
616
+ schema: FalGptImage1p5RequestSchema,
617
+ edit: gptImage1p5Edit,
618
+ });
619
+ // sig-ok: stylistic dotPath divergence from URL
620
+ // POST https://api.fal.ai/v1/fal-ai/qwen-image
621
+ // Docs: https://docs.fal.ai
622
+ const qwenImage = Object.assign(async function qwenImage(params, signal) {
623
+ return makeRequest("POST", "/fal-ai/qwen-image", params, signal, undefined, runBaseURL);
624
+ }, {
625
+ schema: FalQwenImageRequestSchema,
626
+ edit: qwenImageEdit,
627
+ });
628
+ async function storageInitiateCall(path, params, signal) {
629
+ const { file_name, content_type, storage_type = "fal-cdn-v3", lifecycle, } = params;
630
+ const url = `${restBaseURL}${path}?storage_type=${encodeURIComponent(storage_type)}`;
631
+ const headers = {
632
+ Authorization: `Key ${opts.apiKey}`,
633
+ "Content-Type": "application/json",
634
+ };
635
+ if (lifecycle) {
636
+ headers["X-Fal-Object-Lifecycle"] = JSON.stringify(lifecycle);
637
+ }
638
+ const res = await doFetch(url, {
639
+ method: "POST",
640
+ headers,
641
+ body: JSON.stringify({ file_name, content_type }),
642
+ signal,
643
+ });
644
+ if (!res.ok) {
645
+ throw new FalError(`Fal storage error: ${res.status}`, res.status, "server_error");
646
+ }
647
+ return (await res.json());
648
+ }
649
+ // sig-ok: stylistic dotPath divergence from URL
650
+ // POST https://rest.fal.ai/storage/upload/initiate
651
+ // Docs: https://docs.fal.ai
652
+ const storageUploadInitiate = Object.assign(async function initiate(params, signal) {
653
+ return storageInitiateCall("/storage/upload/initiate", params, signal);
654
+ }, {
655
+ schema: FalStorageUploadInitiateRequestSchema,
656
+ });
657
+ // sig-ok: stylistic dotPath divergence from URL
658
+ // POST https://rest.fal.ai/storage/upload/initiate-multipart
659
+ // Docs: https://docs.fal.ai
660
+ const storageUploadInitiateMultipart = Object.assign(async function initiateMultipart(params, signal) {
661
+ return storageInitiateCall("/storage/upload/initiate-multipart", params, signal);
662
+ }, {
663
+ schema: FalStorageUploadInitiateMultipartRequestSchema,
664
+ });
665
+ // sig-ok: stylistic dotPath divergence from URL
666
+ // POST https://rest.fal.ai/storage/upload/complete-multipart
667
+ // Docs: https://docs.fal.ai
668
+ const storageUploadCompleteMultipart = Object.assign(async function completeMultipart(params, signal) {
669
+ const upload = new URL(params.upload_url);
670
+ const completeUrl = `${upload.origin}${upload.pathname}/complete${upload.search}`;
671
+ return doFetch(completeUrl, {
672
+ method: "POST",
673
+ headers: { "Content-Type": "application/json" },
674
+ body: JSON.stringify({ parts: params.parts }),
675
+ signal,
676
+ });
677
+ }, {
678
+ schema: FalStorageUploadCompleteMultipartRequestSchema,
679
+ });
680
+ const storage = {
681
+ upload: {
682
+ initiate: storageUploadInitiate,
683
+ initiateMultipart: storageUploadInitiateMultipart,
684
+ completeMultipart: storageUploadCompleteMultipart,
685
+ },
686
+ };
687
+ const run = {
688
+ bytedance: {
689
+ seedance2p0: {
690
+ imageToVideo: bytedanceSeedance2p0ImageToVideo,
691
+ textToVideo: bytedanceSeedance2p0TextToVideo,
692
+ referenceToVideo: bytedanceSeedance2p0ReferenceToVideo,
693
+ fast: {
694
+ imageToVideo: bytedanceSeedance2p0FastImageToVideo,
695
+ textToVideo: bytedanceSeedance2p0FastTextToVideo,
696
+ referenceToVideo: bytedanceSeedance2p0FastReferenceToVideo,
697
+ },
698
+ },
699
+ seedream: {
700
+ v5: {
701
+ lite: {
702
+ edit: seedreamV5LiteEdit,
703
+ textToImage: seedreamV5LiteTextToImage,
704
+ },
705
+ },
706
+ },
707
+ },
708
+ nanoBananaPro: {
709
+ textToImage: nanoBananaProTextToImage,
710
+ edit: nanoBananaProEdit,
711
+ },
712
+ nanoBanana: {
713
+ textToImage: nanoBananaTextToImage,
714
+ edit: nanoBananaEdit,
715
+ },
716
+ nanoBanana2: {
717
+ textToImage: nanoBanana2TextToImage,
718
+ edit: nanoBanana2Edit,
719
+ },
720
+ qwenImage,
721
+ klingVideo: {
722
+ v3: {
723
+ pro: {
724
+ imageToVideo: klingVideoV3ProImageToVideo,
725
+ textToVideo: klingVideoV3ProTextToVideo,
726
+ },
727
+ standard: {
728
+ imageToVideo: klingVideoV3StandardImageToVideo,
729
+ textToVideo: klingVideoV3StandardTextToVideo,
730
+ },
731
+ },
732
+ o3p4k: {
733
+ imageToVideo: klingVideoO3p4kImageToVideo,
734
+ referenceToVideo: klingVideoO3p4kReferenceToVideo,
735
+ textToVideo: klingVideoO3p4kTextToVideo,
736
+ },
737
+ },
738
+ gptImage1p5,
739
+ sora2: {
740
+ textToVideo: sora2TextToVideo,
741
+ imageToVideo: sora2ImageToVideo,
742
+ },
743
+ hunyuan: {
744
+ v3: {
745
+ instructEdit: hunyuanImageV3InstructEdit,
746
+ },
747
+ },
748
+ veo3p1: {
749
+ textToVideo: veo3p1TextToVideo,
750
+ imageToVideo: veo3p1ImageToVideo,
751
+ },
752
+ falAi: {
753
+ elevenlabs: {
754
+ speechToText: {
755
+ scribeV2: elevenlabsSpeechToTextScribeV2,
756
+ },
757
+ },
758
+ },
759
+ wan: {
760
+ v2p7: {
761
+ textToImage: wanV2p7TextToImage,
762
+ edit: wanV2p7Edit,
763
+ textToVideo: wanV2p7TextToVideo,
764
+ imageToVideo: wanV2p7ImageToVideo,
765
+ referenceToVideo: wanV2p7ReferenceToVideo,
766
+ editVideo: wanV2p7EditVideo,
767
+ pro: {
768
+ textToImage: wanV2p7ProTextToImage,
769
+ edit: wanV2p7ProEdit,
770
+ },
771
+ },
772
+ },
773
+ xai: {
774
+ grokImagineImage: xaiGrokImagineImage,
775
+ grokImagineVideo: {
776
+ imageToVideo: xaiGrokImagineVideoImageToVideo,
777
+ referenceToVideo: xaiGrokImagineVideoReferenceToVideo,
778
+ extendVideo: xaiGrokImagineVideoExtendVideo,
779
+ editVideo: xaiGrokImagineVideoEditVideo,
780
+ },
781
+ },
782
+ };
783
+ const queue = {
784
+ // sig-ok: stylistic dotPath divergence from URL
785
+ // POST https://api.fal.ai/v1/POST
786
+ // Docs: https://docs.fal.ai
787
+ submit: Object.assign(async function submit(params, signal) {
788
+ const headers = {};
789
+ if (params.priority) {
790
+ headers["X-Fal-Queue-Priority"] = params.priority;
791
+ }
792
+ if (params.timeout !== undefined) {
793
+ headers["X-Fal-Request-Timeout"] = String(params.timeout);
794
+ }
795
+ if (params.no_retry) {
796
+ headers["X-Fal-No-Retry"] = "1";
797
+ }
798
+ if (params.runner_hint) {
799
+ headers["X-Fal-Runner-Hint"] = params.runner_hint;
800
+ }
801
+ if (params.store_io) {
802
+ headers["X-Fal-Store-IO"] = params.store_io;
803
+ }
804
+ if (params.object_lifecycle_preference) {
805
+ headers["X-Fal-Object-Lifecycle-Preference"] =
806
+ params.object_lifecycle_preference;
807
+ }
808
+ const path = params.webhook
809
+ ? `/${params.endpoint_id}?fal_webhook=${encodeURIComponent(params.webhook)}`
810
+ : `/${params.endpoint_id}`;
811
+ return makeRequest("POST", path, params.input, signal, headers, queueBaseURL);
812
+ }, {
813
+ schema: FalQueueSubmitRequestSchema,
814
+ }),
815
+ async status(params, signal) {
816
+ const queryParams = {};
817
+ if (params.logs) {
818
+ queryParams.logs = "1";
819
+ }
820
+ return makeRequest("GET", `/${params.endpoint_id}/requests/${params.request_id}/status`, Object.keys(queryParams).length > 0 ? queryParams : undefined, signal, undefined, queueBaseURL);
821
+ },
822
+ async result(params, signal) {
823
+ return makeRequest("GET", `/${params.endpoint_id}/requests/${params.request_id}`, undefined, signal, undefined, queueBaseURL);
824
+ },
825
+ };
826
+ function buildLogsQueryParams(params) {
827
+ if (!params)
828
+ return {};
829
+ const query = {};
830
+ for (const [key, value] of Object.entries(params)) {
831
+ if (value !== undefined) {
832
+ query[key] = value;
833
+ }
834
+ }
835
+ return query;
836
+ }
837
+ const serverless = {
838
+ logs: {
839
+ // sig-ok: stylistic dotPath divergence from URL
840
+ // POST https://api.fal.ai/v1/serverless/logs/stream
841
+ // Docs: https://docs.fal.ai
842
+ stream: Object.assign(async function stream(params, body, signal) {
843
+ const res = await makeStreamPostWithQuery("/serverless/logs/stream", buildLogsQueryParams(params), body, signal);
844
+ return sseToIterable(res);
845
+ }, {
846
+ schema: FalLogsStreamRequestSchema,
847
+ }),
848
+ },
849
+ files: {
850
+ async list(params, signal) {
851
+ const path = params?.dir
852
+ ? `/serverless/files/list/${params.dir}`
853
+ : "/serverless/files/list";
854
+ return makeRequest("GET", path, undefined, signal);
855
+ },
856
+ // sig-ok: stylistic dotPath divergence from URL
857
+ // POST https://api.fal.ai/v1/serverless/files/file/url/{param}
858
+ // Docs: https://docs.fal.ai
859
+ uploadUrl: Object.assign(async function uploadUrl(params, signal) {
860
+ return makeRequest("POST", `/serverless/files/file/url/${params.file}`, { url: params.url }, signal);
861
+ }, {
862
+ schema: FalFilesUploadUrlRequestSchema,
863
+ }),
864
+ // sig-ok: stylistic dotPath divergence from URL
865
+ // POST https://api.fal.ai/v1/serverless/files/file/local/{param}
866
+ // Docs: https://docs.fal.ai
867
+ uploadLocal: Object.assign(async function uploadLocal(params, signal) {
868
+ const formData = new FormData();
869
+ formData.append("file_upload", params.file, params.filename ?? "upload");
870
+ const queryParams = {};
871
+ if (params.unzip) {
872
+ queryParams.unzip = "true";
873
+ }
874
+ const res = await makeRawRequest("POST", `/serverless/files/file/local/${params.target_path}`, formData, signal, Object.keys(queryParams).length > 0 ? queryParams : undefined);
875
+ return (await res.json());
876
+ }, {
877
+ schema: FalFilesUploadLocalRequestSchema,
878
+ }),
879
+ },
880
+ apps: {
881
+ async queue(params, signal) {
882
+ return makeRequest("GET", `/serverless/apps/${encodeURIComponent(params.owner)}/${encodeURIComponent(params.name)}/queue`, undefined, signal);
883
+ },
884
+ },
885
+ async metrics(signal) {
886
+ const controller = new AbortController();
887
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
888
+ if (signal) {
889
+ attachAbortHandler(signal, controller);
890
+ }
891
+ const url = `${baseURL}/serverless/metrics`;
892
+ try {
893
+ const res = await doFetch(url, {
894
+ method: "GET",
895
+ headers: {
896
+ Authorization: `Key ${opts.apiKey}`,
897
+ },
898
+ signal: controller.signal,
899
+ });
900
+ clearTimeout(timeoutId);
901
+ if (!res.ok) {
902
+ let errorData;
903
+ try {
904
+ errorData = await res.json();
905
+ }
906
+ catch {
907
+ errorData = null;
908
+ }
909
+ if (isFalApiErrorResponse(errorData)) {
910
+ throw new FalError(errorData.error.message, res.status, errorData.error.type, errorData.error.request_id, errorData.error.docs_url, errorData);
911
+ }
912
+ throw new FalError(`Fal API error: ${res.status}`, res.status, "server_error", undefined, undefined, errorData);
913
+ }
914
+ return await res.text();
915
+ }
916
+ catch (error) {
917
+ clearTimeout(timeoutId);
918
+ if (error instanceof FalError)
919
+ throw error;
920
+ throw new FalError(`Fal request failed: ${error}`, 500, "server_error");
921
+ }
922
+ },
923
+ };
924
+ // GET https://api.fal.ai/v1/workflows
925
+ // Docs: https://docs.fal.ai
926
+ const workflows = Object.assign(async function workflows(params, signal) {
927
+ return makeRequest("GET", "/workflows", params, signal);
928
+ }, {
929
+ async get(params, signal) {
930
+ return makeRequest("GET", `/workflows/${encodeURIComponent(params.username)}/${encodeURIComponent(params.workflow_name)}`, undefined, signal);
931
+ },
932
+ });
933
+ // ==================== Verb-Prefixed API Surface ====================
934
+ // GET https://api.fal.ai/v1/models/pricing
935
+ // Docs: https://docs.fal.ai
936
+ const getV1ModelsPricing = Object.assign(async function pricing(params, signal) {
937
+ return makeRequest("GET", "/models/pricing", params, signal);
938
+ }, {
939
+ // GET https://api.fal.ai/v1/models/pricing/estimate
940
+ // Docs: https://docs.fal.ai
941
+ estimate: Object.assign(async function estimate(req, signal) {
942
+ return makeRequest("POST", "/models/pricing/estimate", req, signal);
943
+ }, {
944
+ schema: FalPricingEstimateRequestSchema,
945
+ }),
946
+ });
947
+ const getV1ModelsRequests = {
948
+ async byEndpoint(params, signal) {
949
+ return makeRequest("GET", "/models/requests/by-endpoint", params, signal);
950
+ },
951
+ // GET https://api.fal.ai/v1/models/requests/{param}/payloads
952
+ // Docs: https://docs.fal.ai
953
+ payloads: Object.assign(async function payloads(params, signal) {
954
+ const headers = {};
955
+ if (params.idempotency_key) {
956
+ headers["Idempotency-Key"] = params.idempotency_key;
957
+ }
958
+ return makeRequest("DELETE", `/models/requests/${params.request_id}/payloads`, undefined, signal, headers);
959
+ }, {
960
+ schema: FalDeletePayloadsRequestSchema,
961
+ }),
962
+ };
963
+ // GET https://api.fal.ai/v1/models
964
+ // Docs: https://docs.fal.ai
965
+ const getV1Models = Object.assign(async function models(params, signal) {
966
+ return makeRequest("GET", "/models", params, signal);
967
+ }, {
968
+ pricing: getV1ModelsPricing,
969
+ async usage(params, signal) {
970
+ return makeRequest("GET", "/models/usage", params, signal);
971
+ },
972
+ async analytics(params, signal) {
973
+ return makeRequest("GET", "/models/analytics", params, signal);
974
+ },
975
+ requests: getV1ModelsRequests,
976
+ });
977
+ const getV1Queue = {
978
+ async status(params, signal) {
979
+ const queryParams = {};
980
+ if (params.logs) {
981
+ queryParams.logs = "1";
982
+ }
983
+ return makeRequest("GET", `/${params.endpoint_id}/requests/${params.request_id}/status`, Object.keys(queryParams).length > 0 ? queryParams : undefined, signal, undefined, queueBaseURL);
984
+ },
985
+ async result(params, signal) {
986
+ return makeRequest("GET", `/${params.endpoint_id}/requests/${params.request_id}`, undefined, signal, undefined, queueBaseURL);
987
+ },
988
+ };
989
+ const getV1ServerlessFiles = {
990
+ async list(params, signal) {
991
+ const path = params?.dir
992
+ ? `/serverless/files/list/${params.dir}`
993
+ : "/serverless/files/list";
994
+ return makeRequest("GET", path, undefined, signal);
995
+ },
996
+ };
997
+ const getV1ServerlessApps = {
998
+ async queue(params, signal) {
999
+ return makeRequest("GET", `/serverless/apps/${encodeURIComponent(params.owner)}/${encodeURIComponent(params.name)}/queue`, undefined, signal);
1000
+ },
1001
+ };
1002
+ const getV1Serverless = {
1003
+ files: getV1ServerlessFiles,
1004
+ apps: getV1ServerlessApps,
1005
+ async metrics(signal) {
1006
+ const controller = new AbortController();
1007
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
1008
+ if (signal) {
1009
+ attachAbortHandler(signal, controller);
1010
+ }
1011
+ const url = `${baseURL}/serverless/metrics`;
1012
+ try {
1013
+ const res = await doFetch(url, {
1014
+ method: "GET",
1015
+ headers: {
1016
+ Authorization: `Key ${opts.apiKey}`,
1017
+ },
1018
+ signal: controller.signal,
1019
+ });
1020
+ clearTimeout(timeoutId);
1021
+ if (!res.ok) {
1022
+ let errorData;
1023
+ try {
1024
+ errorData = await res.json();
1025
+ }
1026
+ catch {
1027
+ errorData = null;
1028
+ }
1029
+ if (isFalApiErrorResponse(errorData)) {
1030
+ throw new FalError(errorData.error.message, res.status, errorData.error.type, errorData.error.request_id, errorData.error.docs_url, errorData);
1031
+ }
1032
+ throw new FalError(`Fal API error: ${res.status}`, res.status, "server_error", undefined, undefined, errorData);
1033
+ }
1034
+ return await res.text();
1035
+ }
1036
+ catch (error) {
1037
+ clearTimeout(timeoutId);
1038
+ if (error instanceof FalError)
1039
+ throw error;
1040
+ throw new FalError(`Fal request failed: ${error}`, 500, "server_error");
1041
+ }
1042
+ },
1043
+ };
1044
+ // GET https://api.fal.ai/v1/workflows
1045
+ // Docs: https://docs.fal.ai
1046
+ const getV1Workflows = Object.assign(async function workflows(params, signal) {
1047
+ return makeRequest("GET", "/workflows", params, signal);
1048
+ }, {
1049
+ async get(params, signal) {
1050
+ return makeRequest("GET", `/workflows/${encodeURIComponent(params.username)}/${encodeURIComponent(params.workflow_name)}`, undefined, signal);
1051
+ },
1052
+ });
1053
+ const getV1 = {
1054
+ models: getV1Models,
1055
+ queue: getV1Queue,
1056
+ serverless: getV1Serverless,
1057
+ workflows: getV1Workflows,
1058
+ };
1059
+ // POST v1 namespace
1060
+ const postV1ModelsPricing = {
1061
+ // POST https://api.fal.ai/v1/models/pricing/estimate
1062
+ // Docs: https://docs.fal.ai
1063
+ estimate: Object.assign(async function estimate(req, signal) {
1064
+ return makeRequest("POST", "/models/pricing/estimate", req, signal);
1065
+ }, {
1066
+ schema: FalPricingEstimateRequestSchema,
1067
+ }),
1068
+ };
1069
+ const postV1Models = {
1070
+ pricing: postV1ModelsPricing,
1071
+ };
1072
+ const postV1Queue = {
1073
+ // sig-ok: stylistic dotPath divergence from URL
1074
+ // POST https://api.fal.ai/v1/POST
1075
+ // Docs: https://docs.fal.ai
1076
+ submit: Object.assign(async function submit(params, signal) {
1077
+ const headers = {};
1078
+ if (params.priority) {
1079
+ headers["X-Fal-Queue-Priority"] = params.priority;
1080
+ }
1081
+ if (params.timeout !== undefined) {
1082
+ headers["X-Fal-Request-Timeout"] = String(params.timeout);
1083
+ }
1084
+ if (params.no_retry) {
1085
+ headers["X-Fal-No-Retry"] = "1";
1086
+ }
1087
+ if (params.runner_hint) {
1088
+ headers["X-Fal-Runner-Hint"] = params.runner_hint;
1089
+ }
1090
+ if (params.store_io) {
1091
+ headers["X-Fal-Store-IO"] = params.store_io;
1092
+ }
1093
+ if (params.object_lifecycle_preference) {
1094
+ headers["X-Fal-Object-Lifecycle-Preference"] =
1095
+ params.object_lifecycle_preference;
1096
+ }
1097
+ const path = params.webhook
1098
+ ? `/${params.endpoint_id}?fal_webhook=${encodeURIComponent(params.webhook)}`
1099
+ : `/${params.endpoint_id}`;
1100
+ return makeRequest("POST", path, params.input, signal, headers, queueBaseURL);
1101
+ }, {
1102
+ schema: FalQueueSubmitRequestSchema,
1103
+ }),
1104
+ };
1105
+ const postV1ServerlessFiles = {
1106
+ // sig-ok: stylistic dotPath divergence from URL
1107
+ // POST https://api.fal.ai/v1/serverless/files/file/url/{param}
1108
+ // Docs: https://docs.fal.ai
1109
+ uploadUrl: Object.assign(async function uploadUrl(params, signal) {
1110
+ return makeRequest("POST", `/serverless/files/file/url/${params.file}`, { url: params.url }, signal);
1111
+ }, {
1112
+ schema: FalFilesUploadUrlRequestSchema,
1113
+ }),
1114
+ // sig-ok: stylistic dotPath divergence from URL
1115
+ // POST https://api.fal.ai/v1/serverless/files/file/local/{param}
1116
+ // Docs: https://docs.fal.ai
1117
+ uploadLocal: Object.assign(async function uploadLocal(params, signal) {
1118
+ const formData = new FormData();
1119
+ formData.append("file_upload", params.file, params.filename ?? "upload");
1120
+ const queryParams = {};
1121
+ if (params.unzip) {
1122
+ queryParams.unzip = "true";
1123
+ }
1124
+ const res = await makeRawRequest("POST", `/serverless/files/file/local/${params.target_path}`, formData, signal, Object.keys(queryParams).length > 0 ? queryParams : undefined);
1125
+ return (await res.json());
1126
+ }, {
1127
+ schema: FalFilesUploadLocalRequestSchema,
1128
+ }),
1129
+ };
1130
+ const postV1Serverless = {
1131
+ files: postV1ServerlessFiles,
1132
+ };
1133
+ const postV1 = {
1134
+ models: postV1Models,
1135
+ queue: postV1Queue,
1136
+ serverless: postV1Serverless,
1137
+ };
1138
+ // POST stream v1 namespace
1139
+ const postStreamV1ServerlessLogs = {
1140
+ // sig-ok: stylistic dotPath divergence from URL
1141
+ // POST https://api.fal.ai/v1/serverless/logs/stream
1142
+ // Docs: https://docs.fal.ai
1143
+ stream: Object.assign(async function stream(params, body, signal) {
1144
+ const res = await makeStreamPostWithQuery("/serverless/logs/stream", buildLogsQueryParams(params), body, signal);
1145
+ return sseToIterable(res);
1146
+ }, {
1147
+ schema: FalLogsStreamRequestSchema,
1148
+ }),
1149
+ };
1150
+ const postStreamV1Serverless = {
1151
+ logs: postStreamV1ServerlessLogs,
1152
+ };
1153
+ const postStreamV1 = {
1154
+ serverless: postStreamV1Serverless,
1155
+ };
1156
+ const postStream = {
1157
+ v1: postStreamV1,
1158
+ };
1159
+ // DELETE v1 namespace
1160
+ const deleteV1ModelsRequests = {
1161
+ // DELETE https://api.fal.ai/v1/models/requests/{param}/payloads
1162
+ // Docs: https://docs.fal.ai
1163
+ payloads: Object.assign(async function payloads(params, signal) {
1164
+ const headers = {};
1165
+ if (params.idempotency_key) {
1166
+ headers["Idempotency-Key"] = params.idempotency_key;
1167
+ }
1168
+ return makeRequest("DELETE", `/models/requests/${params.request_id}/payloads`, undefined, signal, headers);
1169
+ }, {
1170
+ schema: FalDeletePayloadsRequestSchema,
1171
+ }),
1172
+ };
1173
+ const deleteV1Models = {
1174
+ requests: deleteV1ModelsRequests,
1175
+ };
1176
+ const deleteV1 = {
1177
+ models: deleteV1Models,
1178
+ };
1179
+ const aiV1 = {
1180
+ models,
1181
+ queue,
1182
+ serverless,
1183
+ workflows,
1184
+ };
1185
+ return attachExamples({
1186
+ // api.fal.ai/v1/* — management API
1187
+ v1: aiV1,
1188
+ // fal.run/* — synchronous inference
1189
+ run,
1190
+ // rest.fal.ai/* — CDN storage uploads
1191
+ storage,
1192
+ // Verb-prefixed API surface
1193
+ get: { v1: getV1 },
1194
+ post: { v1: postV1, run, stream: postStream },
1195
+ delete: { v1: deleteV1 },
1196
+ });
1197
+ }
1198
+ // Upload bytes to fal's CDN via the `storage.upload.initiate` + signed PUT
1199
+ // flow. Returns a stable `https://v3.fal.media/...` URL that fal model
1200
+ // endpoints can fetch directly — no third-party host dependency.
1201
+ export async function uploadFile(provider, args, signal) {
1202
+ const initiateParams = {
1203
+ file_name: args.filename,
1204
+ content_type: args.contentType,
1205
+ ...(args.storage_type ? { storage_type: args.storage_type } : {}),
1206
+ ...(args.lifecycle ? { lifecycle: args.lifecycle } : {}),
1207
+ };
1208
+ const { file_url, upload_url } = await provider.storage.upload.initiate(initiateParams, signal);
1209
+ const body = args.data instanceof Blob
1210
+ ? args.data
1211
+ : new Blob([new Uint8Array(args.data)], { type: args.contentType });
1212
+ const res = await fetch(upload_url, {
1213
+ method: "PUT",
1214
+ headers: { "Content-Type": args.contentType },
1215
+ body,
1216
+ signal,
1217
+ });
1218
+ if (!res.ok) {
1219
+ throw new FalError(`Fal storage PUT failed: ${res.status} ${res.statusText}`, res.status, "server_error");
1220
+ }
1221
+ return file_url;
1222
+ }
1223
+ //# sourceMappingURL=fal.js.map