@vladbasin/strong-api-client
v1.1.1
Published
Strongly typed API client
Downloads
185
Readme
Strong API client
Share request/response models with your API consumers, so they don't need to repeat the same mapping & validation logic.
This is CLIENT library. See SERVER library: @vladbasin/strong-api-middleware
Installation
npm
npm install @vladbasin/strong-api-client @vladbasin/strong-api-middleware @vladbasin/strong-api-mapping @vladbasin/ts-result reflect-metadata joi
yarn
yarn add @vladbasin/strong-api-client @vladbasin/strong-api-middleware @vladbasin/strong-api-mapping @vladbasin/ts-result reflect-metadata joi
Usage
- Import
reflect-metadata
ONCE in your index file:
import 'reflect-metadata';
- Define Request model
import { body, header, path, query } from '@vladbasin/strong-api-mapping';
export class RequestPayload {
@path()
public userId!: number;
@path({ key: 'userId' })
public id!: number;
@query()
public name!: string;
@query()
public isAdmin!: boolean;
@query({ key: 'lastname' })
public surname!: string;
@query({ parser: String })
public cars!: string[];
@query({ parser: Number })
public cash!: number[];
@body()
public details!: DetailsType;
@header({ key: 'Content-Type' })
public contentType!: string;
@header({ key: 'X-Info', parser: String })
public info!: string[];
}
- Define Response model
import { body } from '@vladbasin/strong-api-mapping';
export class ResponsePayload {
@body()
public user!: UserType;
}
- Define validation rules with
Joi
export const RequestPayloadSchema = Joi.object<RequestPayload>({
surname: Joi.string().min(10),
cars: Joi.array().max(3),
// other rules for field content...
});
- Call
fetchPayloadRequestWithBodyAsync()
to execute a request:
fetchWithBodyAsync({
request: {
url: 'http://your-backend/api/users/{userId}',
method: HttpRequestMethods.Post,
payload: assign(new RequestPayload(), { id: 12 }),
},
response: {
// process success response (automapped to model instance by the library)
data: {
Model: ResponsePayload,
schema: ResponsePayloadSchema,
},
// OPTIONAL: process error response with custom format (automapped to model instance by the library)
error: {
element: {
Model: ErrorPayload,
schema: ErrorPayloadSchema,
},
handler: (statusCode, errorPayload) => {
//return Error object based on arguments
},
},
},
})
.onSuccess(({ user }: response) => {
// process response data model
})
.onFailureWithError(error => {
// process error (see FetchError below)
})
.run();
By default this library creates FetchError
when reponse fails. You can use it to process the data:
class FetchError extends CodedError {
constructor(
public httpStatusCode: number,
public code: string,
public message: string,
public errors: InnerErrorType[] = [],
public stack = '',
public details: Record<string, unknown> = {}
)
}
type InnerErrorType = {
code: string;
message: string;
};