import { dispatchRequest } from './request';
import { storageImpl } from './storage';
import { EnqueueResult, QueueStatus } from './types';
import { ensureAppIdFormat, isUUIDv4, isValidUrl, parseAppId } from './utils';
/**
* The function input and other configuration when running
* the function, such as the HTTP method to use.
*/
type RunOptions = {
/**
* The path to the function, if any. Defaults to ``.
* @deprecated Pass the path as part of the app id itself, e.g. `fal-ai/sdxl/image-to-image`
*/
readonly path?: string;
/**
* The function input. It will be submitted either as query params
* or the body payload, depending on the `method`.
*/
readonly input?: Input;
/**
* The HTTP method, defaults to `post`;
*/
readonly method?: 'get' | 'post' | 'put' | 'delete' | string;
/**
* If `true`, the function will automatically upload any files
* (i.e. instances of `Blob`) or data:uri in the input.
*
* You can disable this behavior by setting it to `false`, which
* is useful in cases where you want to upload the files yourself
* or use small data:uri in the input.
*/
readonly autoUpload?: boolean;
};
type ExtraOptions = {
/**
* If `true`, the function will use the queue to run the function
* asynchronously and return the result in a separate call. This
* influences how the URL is built.
*/
readonly subdomain?: string;
};
/**
* Builds the final url to run the function based on its `id` or alias and
* a the options from `RunOptions`.
*
* @private
* @param id the function id or alias
* @param options the run options
* @returns the final url to run the function
*/
export function buildUrl(
id: string,
options: RunOptions & ExtraOptions = {}
): string {
const method = (options.method ?? 'post').toLowerCase();
const path = (options.path ?? '').replace(/^\//, '').replace(/\/{2,}/, '/');
const input = options.input;
const params =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
method === 'get' && input ? new URLSearchParams(input as any) : undefined;
const queryParams = params ? `?${params.toString()}` : '';
const parts = id.split('/');
// if a fal url is passed, just use it
if (isValidUrl(id)) {
const url = id.endsWith('/') ? id : `${id}/`;
return `${url}${path}${queryParams}`;
}
// TODO remove this after some time, fal.run should be preferred
if (parts.length === 2 && isUUIDv4(parts[1])) {
const host = 'gateway.shark.fal.ai';
return `https://${host}/trigger/${id}/${path}${queryParams}`;
}
const appId = ensureAppIdFormat(id);
const subdomain = options.subdomain ? `${options.subdomain}.` : '';
const url = `https://${subdomain}fal.run/${appId}/${path}`;
return `${url.replace(/\/$/, '')}${queryParams}`;
}
export async function send(
id: string,
options: RunOptions & ExtraOptions = {}
): Promise