@vladbasin/strong-api-mapping
TypeScript icon, indicating that this package has built-in type declarations

1.1.9 • Public • Published

Strong API mapping

Strongly typed API models. Mapping & validation. Use meaningful decorators. Don't repeat yourself.

Installation

npm

npm install reflect-metadata @vladbasin/strong-api-mapping

yarn

yarn add reflect-metadata @vladbasin/strong-api-mapping

Usage

This is a generic mapping library. You can integrate it with any HTTP stack. Currently the following packages use this library:

Step-by-step guide

  1. Import reflect-metadata ONCE in your index file:
import 'reflect-metadata';
  1. Define your 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[];
}
  1. 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...
});
  1. Prepare RawApiRequest for mapping. For example, @vladbasin/strong-api-middleware-aws-lambda already does it for you for AWS Lambda. But you can create your own middleware for your stack and use this library to do mapping & validation for you.
// represents Query, Header, Route and Body values for HTTP request
export type RawApiRequestType = {
    queryParams?: MaybeNullable<Record<string, Maybe<string>>>;
    multiValueQueryParams?: MaybeNullable<Record<string, Maybe<string[]>>>;
    pathParams?: MaybeNullable<Record<string, Maybe<string>>>;
    headers?: MaybeNullable<Record<string, Maybe<string>>>;
    multiValueHeaders?: MaybeNullable<Record<string, Maybe<string[]>>>;
    body?: MaybeNullable<string>;
};
  1. Call the following methods to map HTTP request to your model and vice versa with DRY principle
// maps RawApiRequest to Model (RequestPayload) and validates it (throws `CodedError` with information if model is not valid)
mapRawApiRequestToPayload<RequestPayload>({
    rawApiRequest,
    PayloadConstructor: RequestPayload,
    schema: RequestPayloadSchema,
});

// maps Model (RequestPayload) to RawApiRequest
mapPayloadToRawApiRequest(requestPayload);

Also applicable to response models (mapRawApiResponseToPayload(), mapPayloadToRawApiResponse()).

In case validation fails, the library throws CodedError instance with information which properties are not valid:

{
    message: 'ValidationError: "surname" is required'
    code: 'ValidationFailed',
    errors: [ { code: 'surname', message: 'any.required' } ],
}

Thus, you can share request/response models with your API consumers, so they don't need to repeat the same mapping & validation logic. See: @vladbasin/strong-api-client

Custom decorator/mapping

You can also specify custom mappings for custom decorator:

  1. Define custom decorator
import { defineDecorator, ParserType } from '@vladbasin/strong-api-mapping';

export const context = (options: { key?: string; parser?: ParserType }): PropertyDecorator =>
    defineDecorator({
        source: 'context',
        useKey: true,
        isKeyCaseSensitive: false,
        key: options.key,
        parser: options.parser,
        isCustom: true,
    });
  1. Specify data for custom context
mapRawApiRequestToPayload<RequestPayload>({
    rawApiRequest,
    PayloadConstructor: RequestPayload,
    schema: RequestPayloadSchema,
    customApiRequestData: {
        context: {
            customKey: 'customValue',
            //...
        },
    },
});

Readme

Keywords

Package Sidebar

Install

npm i @vladbasin/strong-api-mapping

Weekly Downloads

65

Version

1.1.9

License

GPL-3.0-only

Unpacked Size

92.2 kB

Total Files

118

Last publish

Collaborators

  • vladbasin