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

@stoplight/http-spec

v7.1.0

Published

## What is it?

Downloads

469,908

Readme

@stoplight/http-spec

What is it?

HTTP Spec is yet another, hopefully more pragmatic, attempt to standardise OpenAPI v2, OpenAPI v3, Postman Collections and other HTTP-related specification under a single AST to rule them all (at least in Stoplight).

There have been a lot of other attempts to have a universal specification such as API Elements, API Flow and they all failed for a number of reasons. Some of those have been discussed here.

Why build it?

Stoplight needs a way to interact with these documents in a standardized way, and relying on some dying intermediate format does not make that much sense. It's better to accept the sad state of the industry and work on a minimal superset format that can encompass the majority of the use cases.

How's HTTP Spec formed?

This repository contains exclusively converters functions that take OpenAPI v2, OpenAPI v3.x, or Postman Collection documents and transforms them into the http-spec interface.

You can explore the whole structure by looking at the IHttpService definition and checking out its descendants. You'll probably notice that it resembles a lot the current OpenAPI 3.x specification, and that's on purpose. OpenAPI 3.0 has first support and we gracefully upgrade/downgrade the other specification formats to it.

How do I write a converter?

If you would like to add support for another API description format, like RAML, follow these steps:

  1. Create a new directory in the src/ directory
  2. Create a function that from your input returns an IHttpService
  3. Let the TypeScript errors guide you while filling out the missing fields (such as Security Schemes, Servers)
  4. Create a function that's able to return an array of IHttpOperation from your own input
  5. Profit

When should I use withContext?

If a given fragment of a document needs to be represented as a standalone node, and as such an id is needed, you should wrap a converter with withContext. withContext ensures parentId will be set properly to all descendant converters - it's important to call this.generateId first, though.

Example:

import { isPlainObject } from '@stoplight/json';
import type { Optional } from '@stoplight/types';

import { withContext } from './context';
import { isNonNullable } from './guards';
import type { ArrayCallbackParameters, TranslateFunction } from './types';

type Item = {
  id: string;
  value: number;
};

type Object = {
  id: string;
  name: string;
  items: Item[];
};

export const translateItem = withContext<
  TranslateFunction<
    // Oas2TranslateFunction & Oas3TranslateFunction are available too
    Record<string, unknown>, // type of the entire doc, should be skipped whe Oas{2,3} TranslateFunction is used
    ArrayCallbackParameters<[object: unknown]>, // fn parameters, ArrayCallbackParameters is a shorthand
    Optional<Item> // fn return type
  >
>(function (object, index) {
  if (!isPlainObject(object)) return;

  const id = this.generateId(`my-item-${index}`); // can also be any of src/generators.ts like this.generateId.httpQuery({ keyOrName: 'whatever' })
  return {
    id,
    value: index,
  };
});

export const translateObject = withContext<
  TranslateFunction<Record<string, unknown>, [object: unknown], Optional<Object>>
>(function (object) {
  if (!isPlainObject(object)) return;

  const id = this.generateId('my_id'); // can also be any of src/generators.ts like this.generateId.httpQuery({ keyOrName: 'whatever' })
  return {
    id,
    name: 'some-name',
    items: Array.isArray(object.items) ? object.items.map(translateItem, this).filter(isNonNullable) : [],
  };
});

IHttpOperation merger

src/merge.ts contains a utility that reduces the list of IHttpOperation's into a minimal set. This tool particularly handy if you have a recorded list of request/response pairs, and you want to infer a specification out of it.

The strategy is the following:

  1. group operations by paths
  2. for each group:
    1. merge request definitions, headers, query parameters, body schemas
    2. group responses by the code
    3. for each response code:
      1. merge headers, examples, encodings, ...
      2. group contents by media type
      3. for each media type: merge body schemas

Merging strategy highlights

  • Conflicting examples will make the merger relax the constraints. That means e.g. if a header is required in one request and not required in another one then the resulting operation will not require that header to be present.
  • Different JSON Schemas are coupled with anyOf.
  • By default, additionalProperties are permitted.