Convert between JSON Schema, TypeScript, GraphQL and Open API
npm install @jnath/typeconv[![npm version][npm-image]][npm-url]
[![downloads][downloads-image]][npm-url]
[![build status][build-image]][build-url]
[![coverage status][coverage-image]][coverage-url]
[![Language grade: JavaScript][lgtm-image]][lgtm-url]
[![Node.JS version][node-version]][node-url]
typeconv is an extremely fast silver bullet type conversion utility.
It converts between any of its supported types, bidirectionally.
typeconv lets you convert between type systems which have [core-types][core-types-github-url] converters, such as JSON Schema, TypeScript, GraphQL, Open API and [SureType][suretype-github-url]. This package can be used as an API programatically or as an application (installed in node_modules/.bin or by using e.g. npx).
By taking advantage of the [core-types][core-types-github-url] ([npm][core-types-npm-url]) toolbox for generic type handling, typeconv can convert and maintain source code location information, comments, descriptions etc. when converting between the different type systems. It is using the following converter packages:
* [core-types-json-schema][core-types-json-schema-github-url] ([npm][core-types-json-schema-npm-url])
* [core-types-ts][core-types-ts-github-url] ([npm][core-types-ts-npm-url])
* [core-types-graphql][core-types-graphql-github-url] ([npm][core-types-graphql-npm-url])
* [core-types-suretype][core-types-suretype-github-url] ([npm][core-types-suretype-npm-url])
These type systems don't share the same set of types and constraints. For example, JSON Schema has value constraints (like "a string must be longer than 5 characters") and GraphQL doesn't have null or key-value objects as a first-class type. Convertions will therefore produce the smallest common denominator of type information, but still be very useful. See [core-types][core-types-github-url] for more information on its supported types, and why not implement a new conversion package yourself!
Convert files from TypeScript ("ts") to GraphQL ("gql"), put the generated files in the gql-schemas directory in the same directory structure as the source files:
``zsh`
$ typeconv -f ts -t gql -o gql-schemas 'types/*/.ts'
This generates gql-schemas/*.graphql for each .ts file in types/ (and sub-directories).
Note that when using glob patterns, put them in quotes to not have the shell try to expand the pattern - typeconv will do it a lot better!
When converting from SureType, typeconv will extract all exported validators.
* Conversion example
* Usage
* Command line
* As API
* JSON Schema
* Open API
* TypeScript
* GraphQL
* SureType
`Converting the following JSON Schema:
json`
{
"definitions": {
"User": {
"type": "object",
"title": "User type",
"description": "This type holds the user information, such as name",
"properties": { "name": { "type": "string", "title": "The real name" } },
"required": [ "name" ]
},
"ChatLine": {
"type": "object",
"title": "A chat line",
"properties": {
"user": { "$ref": "#/definitions/User" },
"line": { "type": "string" }
},
"required": [ "user", "line" ]
}
}
}
` This type holds the user information, such as name*/ /A chat line/ or if converted into TypeScript _declarations_ (for .d.ts... to TypeScript will produce:
ts
/*User type
export interface User {
/The real name/
name: string;
}
export interface ChatLine {
user: User;
line: string;
}
` files), export interface will be export declare interface.
` This type holds the user information, such as name "A chat line"... and to GraphQL will produce:
graphql
"""User type
"""
type User {
"The real name"
name: String!
}
type ChatLine {
user: User!
line: String!
}
`
Conversions are bi-directional, so any of these type systems can convert to any other.
You can depend on typeconv, and if so, you'll have node_modules/.bin/typeconv installed. Or you run it with on-the-fly installation using npx, as npx typeconv args....
Use -f (or --from-type) to specify from which type system to convert, and -t (or --to-type) to specify which type system to convert to. Other options can be used to configure each configuration (both the from and the to) and these options are usually only available for a specific type system.
The types supported are gql (GraphQL), ts (TypeScript), jsc (JSON Schema), oapi (Open API) and st (SureType).
` Options: -h, --help Print (this) help screen Values: -t, --to-type Values: --(no-)shortcut Shortcut conversion if possible (bypassing core-types).$ typeconv --help
Usage: typeconv [options] file ...
--version Print the program version
-v, --verbose Verbose informational output (default: false)
--dry-run Prepare and perform conversion, but write no output (default: false)
--(no-)hidden Include hidden files, i.e. files in .gitignore,
files beginning with '.' and the '.git' directory
(default: true)
-f, --from-type
ts TypeScript
jsc JSON Schema
gql GraphQL
oapi Open API
st SureType
ct core-types
ts TypeScript
jsc JSON Schema
gql GraphQL
oapi Open API
st SureType
ct core-types
This is possible between SureType, JSON Schema and Open API
to preserve all features which would otherwise be erased.
(default: true)
-o, --output-directory
-O, --output-extension
Defaults to 'ts'/'d.ts', 'json', 'yaml' and 'graphql'.
Use '-' to not save a file, but output to stdout instead.
--(no-)strip-annotations Removes all annotations (descriptions, comments, ...) (default: false)
TypeScript
--(no-)ts-declaration Output TypeScript declarations (default: false)
--(no-)ts-disable-lint-header Output comments for disabling linting (default: true)
--(no-)ts-descriptive-header Output the header comment (default: true)
--(no-)ts-use-unknown Use 'unknown' type instead of 'any' (default: true)
GraphQL
--gql-unsupported
Values:
ignore Ignore (skip) type
warn Ignore type, but warn
error Throw an error
--gql-null-typename
Open API
--oapi-format
Values:
json JSON
yaml YAML ('yml' is also allowed)
--oapi-title
Values:
no-refs Don't ref anything, inline all types.
provided Reference types that are explicitly exported
ref-all Ref all provided types and those with names
--(no-)st-inline-types Inline pretty typescript types aside validator code (default: true)
--(no-)st-export-type Export the deduced types (or the pretty types,
depending on --st-inline-types)
(default: true)
--(no-)st-export-schema Export validator schemas (default: false)
--(no-)st-export-validator Export regular validators (default: true)
--(no-)st-export-ensurer Export 'ensurer' validators (default: true)
--(no-)st-export-type-guard Export type guards (is* validators) (default: true)
--(no-)st-use-unknown Use 'unknown' type instead of 'any' (default: true)
--(no-)st-forward-schema Forward the JSON Schema, and create an untyped validator schema
with the raw JSON Schema under the hood
(default: false)
`
To convert from one type system to another, you create a reader for the type system to convert from and a writer for the type system to convert to. The readers and writers for the different type systems have their own set of options. Some have no options (like the JSON Schema reader), some require options (like the Open API writer).
Making a converter is done using makeConverter(reader, writer, options?), which takes a reader and a writer, and optionally options:
#### cwd (string)
The current working directory, only useful when working with files.
#### simplify (boolean) (default true)
When simplify is true, the converter will let core-types
compress the
types after having converted from {reader} format to core-types.
This is usually recommended, but may cause some annotations (comments)
to be dropped.
#### map (ConvertMapFunction)
Custom map function for transforming each type after it has been
converted from the source type (and after it has been simplified),
but before it's written to the target type system.
Type: (node: NamedType, index: number, array: ReadonlyArray
(NamedType ref)
If filter is used as well, this runs before filter.
If transform is used as well, this runs before transform.
#### filter (ConvertFilterFunction)
Custom filter function for filtering types after they have been
converted from the source type.
Type: (node: NamedType, index: number, array: ReadonlyArray
(NamedType ref)
If map is used as well, this runs after map.
If transform is used as well, this runs before transform.
#### transform (ConvertTransformFunction)
Custom filter function for filtering types after they have been
converted from the source type.
Type: ( doc: NodeDocument ) => NodeDocument
(NodeDocument ref)
If map is used as well, this runs after map.
If filter is used as well, this runs after filter.
#### shortcut (boolean) (default true)
Shortcut reader and writer if possible (bypassing core-types).
`ts
import {
getTypeScriptReader,
getOpenApiWriter,
makeConverter,
} from 'typeconv'
const reader = getTypeScriptReader( );
const writer = getOpenApiWriter( { format: 'yaml', title: 'My API', version: 'v1' } );
const { convert } = makeConverter( reader, writer );
const { data } = await convert( { data: "export type Foo = string | number;" } );
data; // This is the Open API yaml as a string
`
There are two exported functions for JSON Schema:
`ts
import { getJsonSchemaReader, getJsonSchemaWriter } from 'typeconv'
const reader = getJsonSchemaReader( );
const writer = getJsonSchemaWriter( );
`
They don't have any options.
typeconv expects the JSON Schema to contain definitions, i.e. to be in the form:
`JSON Schema
json`
{
"definitions": {
"User": {
"type": "object",
"properties": { "name": { "type": "string" } },
"required": [ "name" ]
},
"ChatLine": {
"type": "object",
"properties": {
"user": { "$ref": "#/definitions/User" },
"line": { "type": "string" }
},
"required": [ "user", "line" ]
}
}
}
typeconv doesn't support external references (to other files). If you have that, you need to use a reference parser and merge it into one inline-referenced file before using typeconv.
Converting to or from Open API can be done with both JSON and YAML. The default is JSON.
When reading, if the filename ends with .yml or .yaml, typeconv will interpret the input as YAML.
Writing however, is decided in the writer factory and provided to getOpenApiWriter.
`ts
import { getOpenApiReader, getOpenApiWriter } from 'typeconv'
const reader = getOpenApiReader( );
const writer = getOpenApiWriter( {
format: 'yaml',
title: 'My API',
version: 'v1',
schemaVersion: '3.0.0',
} );
`
The options to getOpenApiWriter is:
`ts`
interface {
format?: string;
title: string;
version: string;
schemaVersion?: string;
}
TypeScript conversion is done using:
`ts
import { getTypeScriptReader, getTypeScriptWriter } from 'typeconv'
const reader = getTypeScriptReader( );
const writer = getTypeScriptWriter( );
`
Both these take an optional argument.
The getTypeScriptReader takes an optionalFromTsOptionscore-types-ts
object from [][core-types-ts-github-url], although warn isn't necessary since it's set by typeconv internally.
The getTypeScriptWriter takes an optionalToTsOptionscore-types-ts
object from [][core-types-ts-github-url], although warn, filename, sourceFilename, userPackage and userPackageUrl aren't necessary since they're set by typeconv internally.
GraphQL conversion is done using;
`ts
import { getGraphQLReader, getGraphQLWriter } from 'typeconv'
const reader = getGraphQLReader( );
const writer = getGraphQLWriter( );
`
Both these take an optional argument.
The getGraphQLReader takes an optionalGraphqlToCoreTypesOptionscore-types-graphql
object from [][core-types-graphql-github-url], although warn isn't necessary since it's set by typeconv internally.
The getGraphQLWriter takes an optionalCoreTypesToGraphqlOptionscore-types-graphql
object from [][core-types-graphql-github-url], although warn, filename, sourceFilename, userPackage and userPackageUrl aren't necessary since they're set by typeconv internally.
SureType conversion is done using;
`ts
import { getSureTypeReader, getSureTypeWriter } from 'typeconv'
const reader = getSureTypeReader( );
const writer = getSureTypeWriter( );
`
Both these take an optional argument from the [core-types-suretype][core-types-suretype-github-url] package.
The getSureTypeReader takes an optionalSuretypeToJsonSchemaOptions.
The getSureTypeWriter takes an optionalJsonSchemaToSuretypeOptions`.
[npm-image]: https://img.shields.io/npm/v/typeconv.svg
[npm-url]: https://npmjs.org/package/typeconv
[downloads-image]: https://img.shields.io/npm/dm/typeconv.svg
[build-image]: https://img.shields.io/github/workflow/status/grantila/typeconv/Master.svg
[build-url]: https://github.com/grantila/typeconv/actions?query=workflow%3AMaster
[coverage-image]: https://coveralls.io/repos/github/grantila/typeconv/badge.svg?branch=master
[coverage-url]: https://coveralls.io/github/grantila/typeconv?branch=master
[lgtm-image]: https://img.shields.io/lgtm/grade/javascript/g/grantila/typeconv.svg?logo=lgtm&logoWidth=18
[lgtm-url]: https://lgtm.com/projects/g/grantila/typeconv/context:javascript
[node-version]: https://img.shields.io/node/v/typeconv
[node-url]: https://nodejs.org/en/
[core-types-npm-url]: https://npmjs.org/package/core-types
[core-types-github-url]: https://github.com/grantila/core-types
[core-types-json-schema-npm-url]: https://npmjs.org/package/core-types-json-schema
[core-types-json-schema-github-url]: https://github.com/grantila/core-types-json-schema
[core-types-ts-npm-url]: https://npmjs.org/package/core-types-ts
[core-types-ts-github-url]: https://github.com/grantila/core-types-ts
[core-types-graphql-npm-url]: https://npmjs.org/package/core-types-graphql
[core-types-graphql-github-url]: https://github.com/grantila/core-types-graphql
[core-types-suretype-npm-url]: https://npmjs.org/package/core-types-suretype
[core-types-suretype-github-url]: https://github.com/grantila/core-types-suretype
[suretype-github-url]: https://github.com/grantila/suretype