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

jsonschema-docgen

v1.0.3

Published

A documentation generator for JSON schemas

Downloads

96

Readme

JSON Schema Documentation Generator

NPM SIZE SPONSOR

Generates simple, customizable (with great defaults), easy to read documentation for JSON schemas. Made by the creator of LintLens to document the requirements/options of ESLint rules, this powerful, yet simple, documentation generator can now be used in your projects, too. It features a provider-based formatting system that allows you to easily create any output style you wish, or use the simple and intuitive default provider. The default format provider (the one used by LintLens) displays JSON schemas in a JSON(ish) format that is intuitive and easy to read.

Simple to use! Just pass in your JSON schema and get incredibly easy to read documentation. Want something different? Create your own custom formatter and pass that in as the second argument.

Example (using the default (JSON-ish) format provider):

{
  "useAllowList": boolean (default: false),
  "allowedValues": [
    // unique
    ...string
  ],
  "suggestedAmount": integer (x > 0) | "none",
  "sortOrder": [
    // required: 4 items
    // unique
    ..."name" | "position" | "location" | "company"
  ],
  "ignoreCase": boolean (default: true)
}

Installation

npm install jsonschema-docgen

Usage

API

function getSchemaDocumentation(schema: JSONSchema, formatter?: FormatProvider): string;

Custom Format Providers API

type FormatProvider = {
    // A function to initialize a mutable object, which is passed to every formatter function below
    getInitialState: () => any;

    // A function for each type found in a JSON schema
    // Example:  object(doc, baseFunc, state) { ... }

    any: FormatterFunction<AnySchemaDoc>;
    not: FormatterFunction<NotSchemaDoc>;
    nullvalue: FormatterFunction<NullvalueSchemaDoc>;
    object: FormatterFunction<ObjectSchemaDoc>;
    tuple: FormatterFunction<TupleSchemaDoc>;
    array: FormatterFunction<ArraySchemaDoc>;
    enumeration: FormatterFunction<EnumerationSchemaDoc>;
    constant: FormatterFunction<ConstantSchemaDoc>;
    string: FormatterFunction<StringSchemaDoc>;
    numeric: FormatterFunction<NumericSchemaDoc>;
    boolean: FormatterFunction<BooleanSchemaDoc>;
    anyOf: FormatterFunction<AnyOfSchemaDoc>;
    oneOf: FormatterFunction<OneOfSchemaDoc>;
    allOf: FormatterFunction<AllOfSchemaDoc>;
    ifThenElse: FormatterFunction<IfThenElseSchemaDoc>;
    multiType: FormatterFunction<MultiTypeSchemaDoc>;
    externalRef: FormatterFunction<ExternalRefSchemaDoc>;
    empty: FormatterFunction<EmptySchemaDoc>;
    invalid: FormatterFunction<InvalidSchemaDoc>;
};

type FormatterFunction<TSchemaDoc extends SchemaDoc> = (doc: TSchemaDoc, formatFunc: BaseFormatFunction, state: any) => string;

type BaseFormatFunction = (doc: SchemaDoc) => string;

Implementation

import { getSchemaDocumentation } from 'jsonschema-docgen';

const documentation = getSchemaDocumentation(schema);

Using a custom format provider

// myFormatProvider.js

export function getInitialState() { /* ... */ }
export function externalRef(doc, formatFunc, state) { /* ... */ }
export function empty(doc, formatFunc, state) { /* ... */ }
export function any(doc, formatFunc, state) { /* ... */ }
export function not(doc, formatFunc, state) { /* ... */ }
export function nullvalue(doc, formatFunc, state) { /* ... */ }
export function object(doc, formatFunc, state) { /* ... */ }
export function tuple(doc, formatFunc, state) { /* ... */ }
export function array(doc, formatFunc, state) { /* ... */ }
export function enumeration(doc, formatFunc, state) { /* ... */ }
export function constant(doc, formatFunc, state) { /* ... */ }
export function string(doc, formatFunc, state) { /* ... */ }
export function numeric(doc, formatFunc, state) { /* ... */ }
export function boolean(doc, formatFunc, state) { /* ... */ }
export function anyOf(doc, formatFunc, state) { /* ... */ }
export function oneOf(doc, formatFunc, state) { /* ... */ }
export function allOf(doc, formatFunc, state) { /* ... */ }
export function ifThenElse(doc, formatFunc, state) { /* ... */ }
export function multiType(doc, formatFunc, state) { /* ... */ }
export function invalid(doc, formatFunc, state) { /* ... */ }
// app.js

import { getSchemaDocumentation } from 'jsonschema-docgen';
import * as myFormatProvider from './myFormatProvider';

const documentation = getSchemaDocumentation(schema, myFormatProvider);

Overriding the default provider

// myFormatFunctions.js

export function string(doc, formatFunc, state) { /* ... */ }
export function constant(doc, formatFunc, state) { /* ... */ }
export function invalid(doc, formatFunc, state) { /* ... */ }
// app.js

import { getSchemaDocumentation, jsonishFormatter } from 'jsonschema-docgen';
import { string, constant, invalid } from './myFormatFunctions';

const customFormatProvider = {
    ...jsonishFormatter,
    string,
    constant,
    invalid
};

const documentation = getSchemaDocumentation(schema, customFormatProvider);

Custom Format Providers

A format provider is a JS object containing a function for each schema type. As your schema is crawled, whenever a particular schema type is reached, the formatter function for that type is called with a schema doc (information specific to its type), a base format function (to be called for any children), and a mutable state object you can use for anything you need to keep track of while formatting a schema document (ex: indentation).

Format Function Signature

// TSchema is specific to the type represented by this function
(doc: TSchemaDoc, formatFunc: (doc: SchemaDoc) => string, state: any) => string;

Schema document types

type SchemaDoc = ExternalRefSchemaDoc | EmptySchemaDoc | AnySchemaDoc | NotSchemaDoc | NullvalueSchemaDoc | ObjectSchemaDoc | TupleSchemaDoc | ArraySchemaDoc | EnumerationSchemaDoc | ConstantSchemaDoc | StringSchemaDoc | NumericSchemaDoc | BooleanSchemaDoc | AnyOfSchemaDoc | OneOfSchemaDoc | AllOfSchemaDoc | IfThenElseSchemaDoc | MultiTypeSchemaDoc | InvalidSchemaDoc;

type BareSchemaDoc = {
    schemaType: SchemaTypes;
};
type BaseSchemaDoc = BareSchemaDoc & {
    default?: Value;
    deprecated?: boolean;
    annotations?: Annotations;
};

type ExternalRefSchemaDoc = BareSchemaDoc & {
    baseUri: string;
    reference: string;
};
type EmptySchemaDoc = BareSchemaDoc & {
    schema: Schema;
};
type InvalidSchemaDoc = BareSchemaDoc & {
    schema: Schema;
};
type AnySchemaDoc = BaseSchemaDoc & {};
type NotSchemaDoc = BaseSchemaDoc & {
    schema: SchemaDoc;
};
type NullvalueSchemaDoc = BaseSchemaDoc & {};
type ObjectSchemaDoc = BaseSchemaDoc & {
    properties: Property[];
    indexProperties?: Property[];
    requirements?: ObjectRequirements;
};
type TupleSchemaDoc = BaseSchemaDoc & {
    items: SchemaDoc[];
    additionalItems?: SchemaDoc;
    requirements?: ArrayRequirements;
};
type ArraySchemaDoc = BaseSchemaDoc & {
    schema: SchemaDoc;
    requirements?: ArrayRequirements;
};
type EnumerationSchemaDoc = BaseSchemaDoc & {
    values: Value[];
};
type ConstantSchemaDoc = BaseSchemaDoc & {
    value: Value;
};
type gSchemaDoc = BaseSchemaDoc & {
    requirements?: StringRequirements;
};
type NumericSchemaDoc = BaseSchemaDoc & {
    numericType: string;
    requirements?: NumericRequirements;
};
type BooleanSchemaDoc = BaseSchemaDoc & {};
type OneOfSchemaDoc = BaseSchemaDoc & {
    items: SchemaDoc[];
};
type AnyOfSchemaDoc = BaseSchemaDoc & {
    items: SchemaDoc[];
};
type AllOfSchemaDoc = BaseSchemaDoc & {
    items: SchemaDoc[];
};
type IfThenElseSchemaDoc = BaseSchemaDoc & {
    if: SchemaDoc;
    then: SchemaDoc;
    else: SchemaDoc;
};
type MultiTypeSchemaDoc = BaseSchemaDoc & {
    types: SchemaTypeName[];
};

type Property = {
    key: string;
    value: SchemaDoc;
    required: boolean;
};

type Annotations = {
    title?: string;
    description?: string;
    examples?: Value[];
    readOnly?: boolean;
    writeOnly?: boolean;
};

type Requirement = {
    message: string;
};
type ObjectRequirements = {
    size?: Requirement & {
        minProperties?: number;
        maxProperties?: number;
    };
    propertyNames?: Requirement & {
        minLength?: number;
        maxLength?: number;
        pattern?: string;
        format?: string;
    };
};
type ArrayRequirements = {
    length?: Requirement & {
        minItems?: number;
        maxItems?: number;
    };
    uniqueItems?: Requirement & {
        value: true;
    };
};
type StringRequirements = {
    length?: Requirement & {
        minLength?: number;
        maxLength?: number;
    };
    pattern?: Requirement & {
        value: string;
    };
    format?: Requirement & {
        value: string;
    };
};
type NumericRequirements = {
    range?: Requirement & {
        minimum?: number;
        maximum?: number;
        exclusiveMinimum?: number | boolean;
        exclusiveMaximum?: number | boolean;
    };
    multipleOf?: Requirement & {
        value: number;
    };
};

Current limitations

  • Does not read from external schemas (for now... Later, we will allow multiple schemas to be loaded at once)
  • Does not support non-standard JSON schema keywords/types, etc.
  • Does not support the contains keyword (for arrays)
  • Does not handle schema composition when used as part of another schema type (anyOf, oneOf, allOf, not)
  • Does not handle if/then/else when used as part of another schema type
  • Does not handle conditional object subschemas (dependentRequired, dependentSchemas)