fix: validation error body format (#17)
* fix: validation error body format * chore: bump proxy version * chore: bump client version
This commit is contained in:
parent
e02118f43f
commit
0e3cb85939
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@fal-ai/serverless-client",
|
||||
"description": "The fal serverless JS/TS client",
|
||||
"version": "0.3.1",
|
||||
"version": "0.3.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@ -4,4 +4,4 @@ export { withMiddleware, withProxy } from './middleware';
|
||||
export type { RequestMiddleware } from './middleware';
|
||||
export { ApiError, ValidationError } from './response';
|
||||
export type { ResponseHandler } from './response';
|
||||
export type { QueueStatus } from './types';
|
||||
export type { QueueStatus, ValidationErrorInfo } from './types';
|
||||
|
||||
@ -20,20 +20,45 @@ export class ApiError<Body> extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export class ValidationError extends ApiError<ValidationErrorInfo[]> {
|
||||
type ValidationErrorBody = {
|
||||
detail: ValidationErrorInfo[];
|
||||
};
|
||||
|
||||
export class ValidationError extends ApiError<ValidationErrorBody> {
|
||||
constructor(args: ApiErrorArgs) {
|
||||
super(args);
|
||||
this.name = 'ValidationError';
|
||||
}
|
||||
|
||||
get fieldErrors(): ValidationErrorInfo[] {
|
||||
// NOTE: this is a hack to support both FastAPI/Pydantic errors
|
||||
// and some custom 422 errors that might not be in the Pydantic format.
|
||||
if (typeof this.body.detail === 'string') {
|
||||
return [
|
||||
{
|
||||
loc: ['body'],
|
||||
msg: this.body.detail,
|
||||
type: 'value_error',
|
||||
},
|
||||
];
|
||||
}
|
||||
return this.body.detail || [];
|
||||
}
|
||||
|
||||
getFieldErrors(field: string): ValidationErrorInfo[] {
|
||||
return this.fieldErrors.filter(
|
||||
(error) => error.loc[error.loc.length - 1] === field
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function defaultResponseHandler<Output>(
|
||||
response: Response
|
||||
): Promise<Output> {
|
||||
const { status, statusText } = response;
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
const contentType = response.headers.get('Content-Type') ?? "";
|
||||
if (!response.ok) {
|
||||
if (contentType?.includes('application/json')) {
|
||||
if (contentType.includes('application/json')) {
|
||||
const body = await response.json();
|
||||
const ErrorType = status === 422 ? ValidationError : ApiError;
|
||||
throw new ErrorType({
|
||||
@ -44,13 +69,13 @@ export async function defaultResponseHandler<Output>(
|
||||
}
|
||||
throw new ApiError({ message: `HTTP ${status}: ${statusText}`, status });
|
||||
}
|
||||
if (contentType?.includes('application/json')) {
|
||||
if (contentType.includes('application/json')) {
|
||||
return response.json() as Promise<Output>;
|
||||
}
|
||||
if (contentType?.includes('text/html')) {
|
||||
if (contentType.includes('text/html')) {
|
||||
return response.text() as Promise<Output>;
|
||||
}
|
||||
if (contentType?.includes('application/octet-stream')) {
|
||||
if (contentType.includes('application/octet-stream')) {
|
||||
return response.arrayBuffer() as Promise<Output>;
|
||||
}
|
||||
// TODO convert to either number or bool automatically
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fal-ai/serverless-proxy",
|
||||
"version": "0.3.4",
|
||||
"version": "0.3.5",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@ -19,7 +19,7 @@ export const handler: RequestHandler = async (request, response, next) => {
|
||||
method: request.method,
|
||||
respondWith: (status, data) =>
|
||||
typeof data === 'string'
|
||||
? response.status(status).json({ details: data })
|
||||
? response.status(status).json({ detail: data })
|
||||
: response.status(status).json(data),
|
||||
getHeaders: () => request.headers,
|
||||
getHeader: (name) => request.headers[name],
|
||||
|
||||
@ -19,7 +19,7 @@ export const handler: NextApiHandler = async (request, response) => {
|
||||
method: request.method,
|
||||
respondWith: (status, data) =>
|
||||
typeof data === 'string'
|
||||
? response.status(status).json({ details: data })
|
||||
? response.status(status).json({ detail: data })
|
||||
: response.status(status).json(data),
|
||||
getHeaders: () => request.headers,
|
||||
getHeader: (name) => request.headers[name],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user