Awesome
<!--[![Actions Status](https://github.com/brettz9/jsdoc-jsonschema/workflows/Node%20CI/badge.svg)](https://github.com/brettz9/jsdoc-jsonschema/actions)--> <!-- [![Actions Status](https://github.com/brettz9/jsdoc-jsonschema/workflows/Coverage/badge.svg)](https://github.com/brettz9/jsdoc-jsonschema/actions) --> <!--[![License](https://img.shields.io/npm/l/jsdoc-jsonschema.svg)](LICENSE-MIT.txt)-->(see also licenses for dev. deps.)
jsdoc-jsonschema
Convert standard JSDoc @typedef
comment blocks into JSON Schema (with
support for nonstandard expansions).
Use cases
- Validating the arguments passed to one's code at run-time
- For command-line scripts, one may need to apply schemas to the strings passed in in order to get typed info back out.
JSDoc is needed within code for good API docs anyways (one could build them from JSON Schema, but then they wouldn't be integrated into one's code), but since the information is redundant with JSON Schema, it can save time from having to build both.
Current features
JSDoc | JSON Schema | Notes |
---|---|---|
@typedef | {type: 'object'} | |
/** Some desc.\n\n* @typedef */ | {type: 'object', description: 'Some desc.'} | |
@typedef typeName | {type: 'object', title: 'typeName'} | |
@property {integer} propName | {properties: {propName: {type: 'integer'}}, required: ['propName']} | |
@property {3|4|5} propName | {properties: {propName: {type: 'number', enum: [3, 4, 5]}}, required: ['propName']} | Can force to integer type |
@typedef {3|4|5} | {type: 'number', enum: [3, 4, 5]} | Can force to integer type |
@typedef {SomeType & (AnotherType | YetAnotherType)} | {allOf: [{classRelation: 'is-a', $ref: '$defs/SomeType'}, {anyOf: [{classRelation: 'is-a', $ref: '$defs/AnotherType'}, {classRelation: 'is-a', $ref: '$defs/YetAnotherType'}]}]} | Inner parenthesized unions and/or intersections |
@property {integer} [propName] Prop desc. | {properties: {propName: {type: 'integer', description: 'Prop desc.'}}} | Supported JSON Schema types: 'null', 'boolean', 'object', 'array', 'number', 'string', 'integer'; with tolerateCase option not disabled, will allow Integer , etc., as well |
@property {string[]} [propName] Prop. desc. | {properties: {propName: {type: 'array', description: 'Prop desc.', items: {type: 'string'}}}} | |
`@property {string[] | number[]} [propName] Prop. desc.` | {properties: {propName: {type: 'array', description: 'Prop desc.', items: {anyOf: [{type: 'string'}, {type: 'number'}]}}}} |
FAQ
Why not just use JSON Schema?
While JSON Schema is nicely structured for consumption by JavaScript, it is not integrated within one's code.
And when the schema is discoverable within one's code in the context where it is defined and maintained, one is surely more likely to keep it up to date.
Won't you become unable to express certain JSON Schema features coming from JSDoc?
JSDoc already has certain standard tags that can express certain JSON schema
features like type
and properties
. We want to leverage those standard
features where they exist.
However, JSDoc can support definition of custom tags, so if necessary, we can add certain features that can be converted into other JSON Schema features.
Installation
npm i jsdoc-jsonschema
Usage
import {jsdocToJsonSchema} from 'jsdoc-jsonschema';
jsdocToJsonSchema(`
/**
* @typedef {PlainObject} ParentType
* @property {number} numName
*/
`);
{
"type": "object",
"properties": {
"numName": {
"type": "number"
}
}
}
Options
As a second argument, one can supply an options object with the following properties:
$defs
- Boolean (defaultfalse
) on whether to produce a schema with$defs
. Expected when seeking to buildis-a
structures (with a single root).preferInteger
- Boolean (defaultfalse
) on whether to preferinteger
as a schematype
when the number has no decimal value.tolerateCase
- Boolean (defaulttrue
) on whether to allow types defined in different casing, e.g.,Object
, to avoid throwing and be converted to their lower-case counterpart understood by JSON Schema.throwOnUnrecognizedName
- Boolean (defaulttrue
) on whether to throw upon encountering a type that is not a JSON-schema type (unless a custom type is supplied).types
- Object (defaults to{PlainObject: {type: 'object'}}
) whose keys are custom type names and whose values are objects withtype
and/orformat
. If one of the custom types is found in a jsdoc type, its conversion to JSON Schema will result in the object'stype
and/orformat
.
CLI
Scope
This project does not aim to convert other similar sources such as TypeScript definition files (though see the links below for that).
However, it is, for now, using jsdoctypeparser
(over the standard jsdoc catharsis)
so that, in theory, we could allow conversion of TypeScript-specific types
within jsdoc comments into suitable schema features (e.g., intersections).
See also
- Converting from JSON Schema to jsdoc: json-schema-to-jsdoc.
- jsdoc to Typescript:
- TypeScript to jsdoc: json-schema-to-typescript
- Linting your JSDoc comments: eslint-plugin-jsdoc
To-dos
- Switch from
jsdoctypeparser
tojsdoc-type-pratt-parser
- Get binary to support saving separate typedefs within a file to different output files
- Add whitelist option so only get desired typedef and its parents out of
a file (may be useful with
command-line-basics
). - Add support in
json-schema-to-jsdoc
(#41) for@typedef
's referencing other@typedef
's to complete commented out sanity checks in tests; resume using stable version once may be merged
Lower-priority to-dos
- Support file globs and output directory
- Get working with mixed union types (and for TS, intersection types)
- Add mixed literals as
enum
withtype
array - Nested types, e.g., nullable
- Use
title
with@property
despite being redundant withproperties
key? - Convert TS negated type to
not
? - Option to read from file, optionally filtering out only the
@typedef
's of interest (by whitelist and/or blacklist) - Option to save to file (based on
@typedef
tag name and/or other custom tags?) - Add method to support parsing entire
import
/require
pipeline for@typedef
's for conversion to schemas (could use es-file-traverse)