0.0.0-0 • Published 4 years ago

restea v0.0.0-0

Weekly downloads
4
License
ISC
Repository
github
Last release
4 years ago

restea

restea is a collection of several middleware functions that can be composed in order to validate incoming (and outgoing) data in a declarative and documenting way. restea is built to be used with TypeScript and koa with @koa/router.

These middleware, not only do the validation but they also provide types inside the handler function. See example below:

router.get(
  '/users',
  compose(
    description('Fetch a paginated list of users.'),
    paginated(),
    sortable({ fields: ['id', 'name'], default: '+id' }),
    query('role', string('none', 'admin'), {
      description: 'If provided will filter users based on this role',
    }),
    returns(Ok(ArrayOfSchema(UserSchema)))
  ),
  (ctx, next) => {
    const {
      offset, // `number`
      limit,  // `number`
      sort,   // `Sorting<'id' | 'name'>`
      role,   // `'none' | 'admin'`
    } = ctx.state.params;
    ...
  }
);

If the wrong value is passed for any of the parameters the endpoint will return an error explaining what went wrong:

curl http://localhost:3000/users?role=nonne
{
  "error": {
    "status": 422,
    "code": "InvalidParameter",
    "message": "Invalid query parameter 'role'. Expected 'none' | 'admin' but received: 'nonne'"
  }
}

An additional benefit of using restea is that these middleware are holding the necessary metadata that allows the generation of an Open API schema. See below an example of the generated docs for the previous example. Generated documentation

Run the example

Running the example is the best way to see restea in action

git clone https://github.com/santialbo/restea
cd restea
yarn
cd example
yarn
yarn dev

Now head to https://editor.swagger.io/ and load the spec from http://localhost:3000/schema.

How to use

Installation

npm install restea

or

yarn add restea

List of middleware

  • query: Use it to validate/parse query parameters. See example:

    import { query, regex } from 'restea';
    ...
    router.get('/post', query('slug', regex(/^[a-z0-9-]+$/), async (ctx, next) => {
      return await controller.loadPost(ctx.state.params.slug);
    })
  • parameter: Use it to validate/parse path parameters. See example:

    import { query, uuid } from 'restea';
    ...
    router.get('/post/:postId', query('slug', uuid()), async (ctx, next) => {
      return await controller.loadPost(ctx.state.params.postId);
    })
  • body: Use it to validate/parse the incoming body of the request:

    import { query, uuid } from 'restea';
    ...
    interface CreatePost {
      title: string;
      content: string;
    }
    const CreatePostSchema: JsonSchema<CreatePost> = {
      type: 'object',
      required: ['title'],
      properties: {
        title: {
          type: 'string',
          maxLength: 255
        },
        content: {
          type: 'string'
        }
      }
    };
    router.post('/post/', body({ schema: CreatePostSchema }), async (ctx, next) => {
      return await controller.createPost(ctx.state.body); // ctx.state.body is `CreatePost`
    })