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

swagger-ui-plugin-contracts

v0.0.2

Published

Extend Swagger UI to pretty-display operation contracts.

Downloads

2

Readme

Swagger-ui-plugin-contracts

Check

npm

This is a Swagger UI plugin which renders the contracts of your operations (x-contracts).

screenshot of the plugin

Usage

There are two ways to include the plugin in Swagger UI: via npm and via unpkg.

Via npm

Install the module with npm:

npm install --save swagger-ui-plugin-contracts

Require it in your client-side application:

const ContractsPlugin = require('swagger-ui-plugin-contracts');

const ui = SwaggerUI({
  // your options here...
  plugins: [
    // other plugins...
    ContractsPlugin
  ]
})

Via unpkg

Specify the plugin in your HTML page and load it through unpkg:

<script>
<!-- Load Swagger UI -->
<script src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"></script> 
<!-- Load the PrettyJSONViewPlugin -->
<script src="https://unpkg.com/swagger-ui-plugin-contracts"></script>

<script>
window.onload = function() {
  SwaggerUI({
    // your options here...
    plugins: [
      // other plugins...
      ContractsPlugin
    ]
  })
}
</script>

Contracts

The contracts are specified as the extension x-contracts for each operation. The contracts consist of:

  • preconditions, a list of pre-conditions that need to hold before the execution,
  • snapshots, a list of snapshots of "old" values which are captured before the execution, and
  • postconditions, a list of post-conditions that need to hold after the execution.

Condition

The preconditions and postconditions are defined as objects:

{
  "enforced": boolean,
  "text": string,
  "language": string,
  "statusCode": integer
}

enforced. If the condition is enforced, it means that the server will indeed check it on each request. Otherwise, the condition is merely documented, but will not be executed during a request.

Unenforced conditions are still an important piece of documentation! For example, they help the client to understand formally the request logic and what inputs or outputs are expected. Though the condition is not enforced in production, the client can still assume that the condition was at least executed during, e.g., testing.

text. Formal definition of the condition. For example, the source code in the backend's language.

language. The language in which the condition (text) was formulated. Usually the programming language of the backend.

statusCode. The status code set in the response if the condition is violated.

Example

Here is an example of a post-condition:

{
  "enforced": true,
  "text": "has_book(book.identifier)",
  "language": "python3",
  "statusCode": 500
}

Snapshot

The snapshots are defined as objects:

{
  "name": string,
  "enabled": boolean,
  "text": string,
  "language": string
}

name. The name of the snapshot which identifies how the "old" value will be referenced.

enabled. If enabled, the snapshot is captured at every request. Otherwise, the snapshot is only documented in the schema, but it is not captured. A disabled snapshot is still useful for the reader so that she can follow the logic of (analogously) unenforced post-conditions using the values of disabled snapshots.

text. Formal definition of a snapshot. For example, the source code in the backend's language.

language. The language in which the snapshot (text) was formulated. Usually the programming language of the backend.

Example

Here is an example of a snapshot:

{
  "name": "book_count",
  "enabled": true,
  "text": "book_count()",
  "language": "python3"
}

Full Example

Here is an example of a schema that specifies contracts. The irrelevant parts have been omitted for readability.

(The complete schema can be viewed at manual_test/openapi.json.)

{
  "paths": {
    "/upsert_book": {
      "post": {
        "operationId": "add_book_upsert_book_post",
        "x-contracts": {
          "preconditions": [],
          "snapshots": [
            {
              "name": "book_count",
              "enabled": true,
              "text": "book_count()",
              "language": "python3"
            },
            {
              "name": "has_book",
              "enabled": true,
              "text": "has_book(book.identifier)",
              "language": "python3"
            }
          ],
          "postconditions": [
            {
              "enforced": true,
              "text": "awaited_to(\n        lambda a_book_count: (\n                OLD.book_count + 1 == a_book_count if not OLD.has_book\n                else OLD.book_count == a_book_count),\n        book_count())",
              "language": "python3",
              "statusCode": 500
            },
            {
              "enforced": true,
              "text": "has_book(book.identifier)",
              "language": "python3",
              "statusCode": 500
            }
          ]
        }
      }
    }
  }
}

Who Uses It?

We developed this plugin to be used in conjunction with fastapi-icontract, a FastAPI extension for defining icontracts for the endpoints.

Please let us know (e.g., by creating a new issue) if you use the plugin so that we can list it here!

How Can You Contribute?

Feature requests and bug reports are highly welcome! Please create a new issue.

If you want to contribute in code, please see the contributing guidelines.