UNPKG

json-schema-to-typescript

Version:
153 lines (134 loc) 3.83 kB
import {JSONSchema4, JSONSchema4Type, JSONSchema4TypeName} from 'json-schema' import {isPlainObject, memoize} from 'lodash' export type SchemaType = | 'ALL_OF' | 'UNNAMED_SCHEMA' | 'ANY' | 'ANY_OF' | 'BOOLEAN' | 'NAMED_ENUM' | 'NAMED_SCHEMA' | 'NEVER' | 'NULL' | 'NUMBER' | 'STRING' | 'OBJECT' | 'ONE_OF' | 'TYPED_ARRAY' | 'REFERENCE' | 'UNION' | 'UNNAMED_ENUM' | 'UNTYPED_ARRAY' | 'CUSTOM_TYPE' export type JSONSchemaTypeName = JSONSchema4TypeName export type JSONSchemaType = JSONSchema4Type export interface JSONSchema extends JSONSchema4 { /** * schema extension to support numeric enums */ tsEnumNames?: string[] /** * schema extension to support custom types */ tsType?: string /** * property exists at least in https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.3 */ deprecated?: boolean } export const Parent = Symbol('Parent') export interface LinkedJSONSchema extends JSONSchema { /** * A reference to this schema's parent node, for convenience. * `null` when this is the root schema. */ [Parent]: LinkedJSONSchema | null additionalItems?: boolean | LinkedJSONSchema additionalProperties?: boolean | LinkedJSONSchema items?: LinkedJSONSchema | LinkedJSONSchema[] definitions?: { [k: string]: LinkedJSONSchema } properties?: { [k: string]: LinkedJSONSchema } patternProperties?: { [k: string]: LinkedJSONSchema } dependencies?: { [k: string]: LinkedJSONSchema | string[] } allOf?: LinkedJSONSchema[] anyOf?: LinkedJSONSchema[] oneOf?: LinkedJSONSchema[] not?: LinkedJSONSchema } export const Types = Symbol('Types') export const Intersection = Symbol('Intersection') /** * Normalized JSON schema. * * Note: `definitions` and `id` are removed by the normalizer. Use `$defs` and `$id` instead. */ export interface NormalizedJSONSchema extends Omit<LinkedJSONSchema, 'definitions' | 'id'> { [Intersection]?: NormalizedJSONSchema [Parent]: NormalizedJSONSchema | null [Types]: ReadonlySet<SchemaType> additionalItems?: boolean | NormalizedJSONSchema additionalProperties: boolean | NormalizedJSONSchema extends?: string[] items?: NormalizedJSONSchema | NormalizedJSONSchema[] $defs?: { [k: string]: NormalizedJSONSchema } properties?: { [k: string]: NormalizedJSONSchema } patternProperties?: { [k: string]: NormalizedJSONSchema } dependencies?: { [k: string]: NormalizedJSONSchema | string[] } allOf?: NormalizedJSONSchema[] anyOf?: NormalizedJSONSchema[] oneOf?: NormalizedJSONSchema[] not?: NormalizedJSONSchema required: string[] } export interface EnumJSONSchema extends NormalizedJSONSchema { enum: JSONSchema4Type[] } export interface NamedEnumJSONSchema extends NormalizedJSONSchema { tsEnumNames: string[] } export interface SchemaSchema extends NormalizedJSONSchema { properties: { [k: string]: NormalizedJSONSchema } required: string[] } export interface JSONSchemaWithDefinitions extends NormalizedJSONSchema { $defs: { [k: string]: NormalizedJSONSchema } } export interface CustomTypeJSONSchema extends NormalizedJSONSchema { tsType: string } export const getRootSchema = memoize((schema: NormalizedJSONSchema): NormalizedJSONSchema => { const parent = schema[Parent] if (!parent) { return schema } return getRootSchema(parent) }) export function isBoolean(schema: LinkedJSONSchema | JSONSchemaType): schema is boolean { return schema === true || schema === false } export function isPrimitive(schema: LinkedJSONSchema | JSONSchemaType): schema is JSONSchemaType { return !isPlainObject(schema) } export function isCompound(schema: JSONSchema): boolean { return Array.isArray(schema.type) || 'anyOf' in schema || 'oneOf' in schema }