feat: validation error type (#13)
* feat: add validation error type * feat: move subscribe to top-level * fix: wrong import
This commit is contained in:
parent
25a763602f
commit
f240e622d3
@ -112,6 +112,50 @@ export async function run<Input, Output>(
|
||||
return await responseHandler(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to updates for a specific request in the queue.
|
||||
*
|
||||
* @param id - The ID or URL of the function web endpoint.
|
||||
* @param options - Options to configure how the request is run and how updates are received.
|
||||
* @returns A promise that resolves to the result of the request once it's completed.
|
||||
*/
|
||||
export async function subscribe<Input, Output>(
|
||||
id: string,
|
||||
options: RunOptions<Input> & QueueSubscribeOptions = {}
|
||||
): Promise<Output> {
|
||||
const { request_id: requestId } = await queue.submit(id, options);
|
||||
if (options.onEnqueue) {
|
||||
options.onEnqueue(requestId);
|
||||
}
|
||||
return new Promise<Output>((resolve, reject) => {
|
||||
let timeoutId: ReturnType<typeof setTimeout>;
|
||||
const pollInterval = options.pollInterval ?? 1000;
|
||||
const poll = async () => {
|
||||
try {
|
||||
const requestStatus = await queue.status(id, requestId);
|
||||
if (options.onQueueUpdate) {
|
||||
options.onQueueUpdate(requestStatus);
|
||||
}
|
||||
if (requestStatus.status === 'COMPLETED') {
|
||||
clearTimeout(timeoutId);
|
||||
try {
|
||||
const result = await queue.result<Output>(id, requestId);
|
||||
resolve(result);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
timeoutId = setTimeout(poll, pollInterval);
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId);
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
poll().catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for subscribing to the request queue.
|
||||
*/
|
||||
@ -168,11 +212,7 @@ interface Queue {
|
||||
result<Output>(id: string, requestId: string): Promise<Output>;
|
||||
|
||||
/**
|
||||
* Subscribes to updates for a specific request in the queue.
|
||||
*
|
||||
* @param id - The ID or URL of the function web endpoint.
|
||||
* @param options - Options to configure how the request is run and how updates are received.
|
||||
* @returns A promise that resolves to the result of the request once it's completed.
|
||||
* @deprecated Use `fal.subscribe` instead.
|
||||
*/
|
||||
subscribe<Input, Output>(
|
||||
id: string,
|
||||
@ -204,40 +244,5 @@ export const queue: Queue = {
|
||||
path: `/fal/queue/requests/${requestId}/response`,
|
||||
});
|
||||
},
|
||||
async subscribe<Input, Output>(
|
||||
id: string,
|
||||
options: RunOptions<Input> & QueueSubscribeOptions = {}
|
||||
): Promise<Output> {
|
||||
const { request_id: requestId } = await queue.submit(id, options);
|
||||
if (options.onEnqueue) {
|
||||
options.onEnqueue(requestId);
|
||||
}
|
||||
return new Promise<Output>((resolve, reject) => {
|
||||
let timeoutId: ReturnType<typeof setTimeout>;
|
||||
const pollInterval = options.pollInterval ?? 1000;
|
||||
const poll = async () => {
|
||||
try {
|
||||
const requestStatus = await queue.status(id, requestId);
|
||||
if (options.onQueueUpdate) {
|
||||
options.onQueueUpdate(requestStatus);
|
||||
}
|
||||
if (requestStatus.status === 'COMPLETED') {
|
||||
clearTimeout(timeoutId);
|
||||
try {
|
||||
const result = await queue.result<Output>(id, requestId);
|
||||
resolve(result);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
timeoutId = setTimeout(poll, pollInterval);
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId);
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
poll().catch(reject);
|
||||
});
|
||||
},
|
||||
subscribe,
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
export { config, getConfig } from './config';
|
||||
export { queue, run } from './function';
|
||||
export { queue, run, subscribe } from './function';
|
||||
export { withMiddleware } from './middleware';
|
||||
export { ApiError, ValidationError } from './response';
|
||||
export type { RequestMiddleware } from './middleware';
|
||||
export type { ResponseHandler } from './response';
|
||||
export type { QueueStatus } from './types';
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
import { ValidationErrorInfo } from './types';
|
||||
|
||||
export type ResponseHandler<Output> = (response: Response) => Promise<Output>;
|
||||
|
||||
type ApiErrorArgs = {
|
||||
message: string;
|
||||
status: number;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
body?: any;
|
||||
};
|
||||
|
||||
export class ApiError extends Error {
|
||||
export class ApiError<Body> extends Error {
|
||||
public readonly status: number;
|
||||
public readonly body?: any;
|
||||
public readonly body: Body;
|
||||
constructor({ message, status, body }: ApiErrorArgs) {
|
||||
super(message);
|
||||
this.name = 'ApiError';
|
||||
@ -17,6 +20,13 @@ export class ApiError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export class ValidationError extends ApiError<ValidationErrorInfo[]> {
|
||||
constructor(args: ApiErrorArgs) {
|
||||
super(args);
|
||||
this.name = 'ValidationError';
|
||||
}
|
||||
}
|
||||
|
||||
export async function defaultResponseHandler<Output>(
|
||||
response: Response
|
||||
): Promise<Output> {
|
||||
@ -25,13 +35,14 @@ export async function defaultResponseHandler<Output>(
|
||||
if (!response.ok) {
|
||||
if (contentType?.includes('application/json')) {
|
||||
const body = await response.json();
|
||||
throw new ApiError({
|
||||
const ErrorType = status === 422 ? ValidationError : ApiError;
|
||||
throw new ErrorType({
|
||||
message: body.message || statusText,
|
||||
status,
|
||||
body,
|
||||
});
|
||||
}
|
||||
throw new Error(`HTTP ${status}: ${statusText}`);
|
||||
throw new ApiError({ message: `HTTP ${status}: ${statusText}`, status });
|
||||
}
|
||||
if (contentType?.includes('application/json')) {
|
||||
return response.json() as Promise<Output>;
|
||||
|
||||
@ -33,3 +33,9 @@ export type QueueStatus =
|
||||
export function isQueueStatus(obj: any): obj is QueueStatus {
|
||||
return obj && obj.status && obj.response_url;
|
||||
}
|
||||
|
||||
export type ValidationErrorInfo = {
|
||||
msg: string;
|
||||
loc: Array<string | number>;
|
||||
type: string;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user