import { getConfig } from './config';
import { getUserAgent, isBrowser } from './runtime';
import { EnqueueResult, QueueStatus } from './types';
import { isUUIDv4, isValidUrl } 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 `/`.
*/
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;
};
/**
* 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 = {}
): string {
const { host } = getConfig();
const method = (options.method ?? 'post').toLowerCase();
const path = (options.path ?? '').replace(/^\//, '').replace(/\/{2,}/, '/');
const params =
method === 'get' ? new URLSearchParams(options.input ?? {}) : undefined;
// TODO: change to params.size once it's officially supported
const queryParams = params && params['size'] ? `?${params.toString()}` : '';
const parts = id.split('/');
// if a fal.ai url is passed, just use it
if (isValidUrl(id)) {
const url = id.endsWith('/') ? id : `${id}/`;
return `${url}${path}${queryParams}`;
}
if (parts.length === 2 && isUUIDv4(parts[1])) {
return `https://${host}/trigger/${id}/${path}${queryParams}`;
}
return `https://${id}.${host}/${path}${queryParams}`;
}
/**
* Runs a fal serverless function identified by its `id`.
* TODO: expand documentation and provide examples
*
* @param id the registered function revision id or alias.
* @returns the remote function output
*/
export async function run(
id: string,
options: RunOptions = {}
): Promise