npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

the-bodyguard

v1.4.0

Published

An opinionated microservice wrapper for rapid development based off OpenAPI documentation

Downloads

21

Readme

The bodyguard

A an opinionated request body validation generator - and it achieves that by relying on an existing set of tools rather than re-inventing the wheel. Just wrapping them around in a convenient plug and play package.

#f03c15 This package is very much under active development & not production ready for time being. #f03c15

The core of the process is as follows:

  • Parse & Validate specification (js-yaml as an initial pass)
  • Extract & Flatten JSON Schemas from an OpenAPI specification (@stoplight/json-ref-resolver)
  • Generate typescript models for the same schemas json-schema-to-typescript (json-schema-to-typescript)
  • Generate a set of standalone validators for each of the Schemas (ajv is absolutely amazing, we also utilize standlone)
  • Generate a single bundled and minified output, that can be inserted into any platform without relying on any dependencies ((esbuild)[https://esbuild.github.io/])

The goals

This package has been designed with a few key points in mind:

We should use OpenAPI as single source of truth - for both requests & responses, and wherever else is applicable.

  • Every other framework or library comes with their own set of custom decorators that you have to re-learn time and time again - why should you spend ages trying to re-learn a different tool to achieve the same job. And some of them have their own sets of edge cases, or do not support certain scenarios. Also, I prefer to just write an OpenAPI specification first, and work from there.

  • Allowing the validation to be lifted and shifted between the frameworks, if one day I decide I want to switch from express to serverless, or Azure Functions, why should I have to re-write something as simple as a request body validation layer...

We should have a platform agnostic result

  • Leverage type generation as much as possible to minimize drift between documentation and code. Ideally I would want to just treat generated validators as a dependency, & not have to worry about validating their code. With this generator you get all of the relevant declarions, but final bundle is just a common.js import - in a single file. Bundled, tree-shaken & minified (sourcemaps are optional)

  • Generates a fast authentication layer that's immune to cold start issues (i.e. processing a complex json schema can take precious milliseconds, doing it on repeat - on FaaS infrastructure is quite wasteful.. ) - we can sidestep that with ajv standalone & esbuild.

  • Error output should be as straightfoward and focus on the actual errors, no custom object, random exceptions being thrown unexpectedly etc. A few different variations should be available, whether we just need a true/false or something a bit more verbose.

Installation

NPM Version

NPM - the-bodyguard

npm i the-bodyguard --save-dev

Usage

Generation

Usage: the-bodyguard [options]

Options:
  --openapi <string>  Path to the OpenAPI specification
  --output <string>   Output path
  --force             Force generation even if checksums match (default: false)
  --sourcemaps        Generate sourcemaps (default: false)
  -h, --help          display help for command

Via package.json

...
  "scripts": {
    "build-validation": "the-bodyguard --openapi petstore.yaml --output .validation",

And then

npm run build-validation

Via npx

npx the-bodyguard --openapi petstore.yaml --output .api

Implementation

Now that generation is complete, we can make use of our:

  • Types
    • {SchemaName} - OpenApi schemas have been converted to
  • JSON Schemas
  • Validators
    • {SchemaName}Validator - a validator accepting any objects, and resulting in a true/false output
    • {SchemaName}ValidatorWithErrors - a validator accepting any objects, and resulting in output of [validatedInstance, errors]
      • In case of a valid result validatedInstance, the error will be null
      • In case of invalid result, the validatedInstance will be null

For example, given OpenApi Schema of a category that can be found in the popular petstore example:

component:
  schemas:
    Category:
      title: Pet category
      description: A category for a pet
      type: object
      properties:
        id:
          type: integer
        name:
          type: string

We can do the following:

Use exact types

import { Category } from './.api';

const myCategory: Category = {
    id: 1
    name: "Bobbie"
};

Validate unknown objects

import { Category, CategoryValidator } from './.api';

const invalidCategory = {
    id: "1"
}

if (!CategoryValidator(invalidCategory)) {
    console.log("Category is not valid");
    return;
}

// We can safely proceed

Validate & point out the exact issues

import { Category, CategoryWithErrors } from './.api';

const [category, errors] = UserValidatorWithErrors({
    id: "1"
});

// If validation errors are defined
if (errors) {
    console.log("Category is not valid");
    console.log(errors);
    return;
}

// We can safely proceed & category is correctly typed
console.log(`Category ${category.id} is valid`)