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

optolith-tsjsonschemamd

v0.11.1

Published

A tool for generating both JSON Schema definitions and Markdown documentation from TypeScript files.

Downloads

455

Readme

Optolith TypeScript to JSON Schema and Markdown

This tool provides an opinionated solution for generating both JSON Schemas and corresponding Markdown documentation from a set of TypeScript files. The tool does not support all types possible in TypeScript, only those that are needed in Optolith and that can be represented in a JSON Schema as well.

Why?

There are TypeScript to JSON Schema, JSON Schema to Markdown and TypeScript to Markdown converters.

The main issue for JSON Schema with the existing solutions is that the converters that output JSON Schema do not support the full feature set of JSON Schema. The biggest issue is patternProperties, which is very important here, since the files that are validated with the JSON Schema documents are edited by hand and patternProperties can reduce the number of errors without a need for a custom programmatic validation.

The main issue for Markdown with the existing solutions is that if you convert from TypeScript, they usually target developers, and if you convert from Markdown, the output has a lot of files or does not support the full JSON Schema feature set.

Installation

npm i -D optolith-tsjsonschemamd

Usage

Programmatic Usage

import { generate } from "optolith-tsjsonschemamd";
import { jsonSchema, markdown } from "optolith-tsjsonschemamd/renderers";
import { dirname, join } from "path";
import { fileURLToPath } from "url";

const root = dirname(fileURLToPath(import.meta.url))

generate({
  sourceDir: join(root, "src"),
  outputs: [
    {
      targetDir: join(root, "schema"),
      renderer: jsonSchema({ spec: jsonSchemaSpec })
    },
    {
      targetDir: join(root, "docs", "reference"),
      renderer: markdown()
    }
  ]
})

generate takes all TypeScript files from the absolute sourceDir path and its subdirectories and then runs each TypeScript file inside through each output configuration. Built-in output renderers are for JSON Schema definitions (draft-07) and Markdown documentation, so all you need to do is to specify absolute folder paths for them and import them from the module.

It does not do any clean-up in the target directories, it only overwrites existing files. You can activate this explicitly, though, for all outputs and for each output individually.

The output directory structure as well as the contents of the files mirror the TypeScript sources. The relative directory structure inside the specified root source directory is mirrored, and the contents are simply mapped, so that the output will not have any duplicate types, which are referenced by their relative path instead (except for generic types, see below).

This also implies that all types must be present in the specified root source directory or its subdirectories, otherwise references/links in output files will not work.

You can also build your own renderer by conforming to the Renderer type that can be imported.

An error is thrown if the tool encounters an unsupported structure.

CLI Usage

This package can also be used via the command line.

otjsmd [-w | --watch] [-c <path-to-config> | --config <path-to-config>]

Options must be defined in an ECMAScript module files, which defaults to a file called otjsmd.config.js in the directory where the command is run. You can specify a different path using the respective option. Supply the watch option to rebuild whenever a source file changes.

The config file expects the configuration object as the default export of the file.

import { jsonSchema, markdown } from "optolith-tsjsonschemamd/renderers"
import { dirname, join } from "path";
import { fileURLToPath } from "url";

const root = dirname(fileURLToPath(import.meta.url))

/** @type {import("optolith-tsjsonschemamd").GeneratorOptions} */
export default {
  sourceDir: join(root, "src"),
  outputs: [
    {
      targetDir: join(root, "schema"),
      renderer: jsonSchema({ spec: jsonSchemaSpec })
    },
    {
      targetDir: join(root, "docs", "reference"),
      renderer: markdown()
    }
  ]
}

Main type

A module comment may indicate the main type of the module, which can be used by directly importing the JSON Schema without the need to specify the definition inside. The type is referenced to by its name.

Example:

/**
 * @main Attribute
 */

If no @main attribute is present, a default export is used as a fallback.

Supported JSDoc features

JSDoc | TypeScript | Tag Comment Type | JSON Schema | Markdown :-- | :-- | :-- | :-- | :-- Description | all | markdown | description keyword | Description @title | all | string | title keyword | Heading @markdown | string | boolean | — | Type: Markdown-formatted text @minLength | string | number | minLength keyword | Minimum Length @maxLength | string | number | maxLength keyword | Maximum Length @pattern | string | string | pattern keyword | Pattern @format | string | string | format keyword | Format @integer | number | boolean | "type": "integer" instead of "type": "number" | Type: Integer @minimum | number | number | minimum keyword | Minimum @maximum | number | number | maximum keyword | Maximum @exclusiveMinimum | number | number | exclusiveMinimum keyword | Exclusive Minimum @exclusiveMaximum | number | number | exclusiveMaximum keyword | Exclusive Maximum @multipleOf | number | number | multipleOf keyword | Multiple of @minItems | array | number | minItems keyword | Minimum Items @maxItems | array | number | maxItems keyword | Maximum Items @uniqueItems | array | boolean | uniqueItems keyword | Unique Items @minProperties | object | number | minProperties keyword | Minimum Properties @maxProperties | object | number | maxProperties keyword | Maximum Properties @patternProperties | object | string | patternProperties keyword | Values matching pattern readonly modifier | property | boolean | readOnly keyword | Read-only property

Boolean tags

Boolean tags require no additional comment, if they are present, they are set to true, otherwise they are false. You can explicitly set them to true if you prefer (e.g. @integer true).

Pattern Dictionary

Pattern properties are annotated using @patternProperties. The value of this annotation is the pattern that should be used for the indexed properties. It is annotated on the indexed property definition, not the object itself.

Example:

/**
 * @minProperties 1
 */
type Dictionary = {
  /**
   * @patternProperties ^KEY_[1-9]$
   */
  [key: string]: number
}

Generics

Generics are supported, but some export formats may not be able to support them, such as JSON Schema. You can use the resolveTypeParameters for a Renderer to receive an AST without type parameters. Types with type parameters are still present if all of their type parameters have default arguments, which replace all type parameter occurrences in the type definition. The AST type is the same, but you can ignore all type argument and type parameter properties, since they are all undefined.

Defining your own renderer

If you want to write your own renderer, you must provide a value that conforms to the Renderer type. This type consists of three parts. An AST transformer function, a file extension and (optionally) whether to resolve type parameters (see section about generics).

The transformer function receives the AST for a file and meta information about that file and should return a string that represents the generated code or text output, or undefined if no output should be generated for that file. If it’s a string, it is saved to the same relative location as in the root directory, but inside the output directory instead and with the file extension specified for the renderer. For example, if the root is defined as src and the output directory is schema with the .schema.json extension, a file at src/core/Object.ts will be output to schema/core/Object.schema.json.

Examples

You can check out the Optolith flat-file database schema repository, which it has been mainly written for.