Socket
Socket
Sign inDemoInstall

json-schema-to-typescript

Package Overview
Dependencies
Maintainers
1
Versions
114
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

json-schema-to-typescript - npm Package Compare versions

Comparing version 14.1.0 to 15.0.0

dist/src/applySchemaTyping.d.ts

4

CHANGELOG.md

@@ -5,2 +5,6 @@ # Changelog

## 15.0.0
- 62cc052 Fixed bug where intersection schemas didn't generate complete types. Improved output readability for intersection types (#603)
## 14.1.0

@@ -7,0 +11,0 @@

@@ -6,2 +6,3 @@ "use strict";

const utils_1 = require("./utils");
const applySchemaTyping_1 = require("./applySchemaTyping");
const util_1 = require("util");

@@ -196,2 +197,17 @@ const rules = new Map();

});
// Precalculation of the schema types is necessary because the ALL_OF type
// is implemented in a way that mutates the schema object. Detection of the
// NAMED_SCHEMA type relies on the presence of the $id property, which is
// hoisted to a parent schema object during the ALL_OF type implementation,
// and becomes unavailable if the same schema is used in multiple places.
//
// Precalculation of the `ALL_OF` intersection schema is necessary because
// the intersection schema needs to participate in the schema cache during
// the parsing step, so it cannot be re-calculated every time the schema
// is encountered.
rules.set('Pre-calculate schema types and intersections', schema => {
if (schema !== null && typeof schema === 'object') {
(0, applySchemaTyping_1.applySchemaTyping)(schema);
}
});
function normalize(rootSchema, dereferencedPaths, filename, options) {

@@ -198,0 +214,0 @@ rules.forEach(rule => (0, utils_1.traverse)(rootSchema, (schema, key) => rule(schema, filename, options, key, dereferencedPaths)));

4

dist/src/parser.d.ts
import { JSONSchema4Type } from 'json-schema';
import { Options } from './';
import { AST } from './types/AST';
import { NormalizedJSONSchema, SchemaType } from './types/JSONSchema';
import type { AST } from './types/AST';
import type { NormalizedJSONSchema, SchemaType } from './types/JSONSchema';
export type Processed = Map<NormalizedJSONSchema, Map<SchemaType, AST>>;
export type UsedNames = Set<string>;
export declare function parse(schema: NormalizedJSONSchema | JSONSchema4Type, options: Options, keyName?: string, processed?: Processed, usedNames?: Set<string>): AST;

@@ -6,3 +6,3 @@ "use strict";

const util_1 = require("util");
const typesOfSchema_1 = require("./typesOfSchema");
const applySchemaTyping_1 = require("./applySchemaTyping");
const AST_1 = require("./types/AST");

@@ -18,25 +18,19 @@ const JSONSchema_1 = require("./types/JSONSchema");

}
const types = (0, typesOfSchema_1.typesOfSchema)(schema);
if (types.length === 1) {
const ast = parseAsTypeWithCache(schema, types[0], options, keyName, processed, usedNames);
(0, utils_1.log)('blue', 'parser', 'Types:', types, 'Input:', schema, 'Output:', ast);
const intersection = schema[JSONSchema_1.Intersection];
const types = schema[JSONSchema_1.Types];
if (intersection) {
const ast = parseAsTypeWithCache(intersection, 'ALL_OF', options, keyName, processed, usedNames);
types.forEach(type => {
ast.params.push(parseAsTypeWithCache(schema, type, options, keyName, processed, usedNames));
});
(0, utils_1.log)('blue', 'parser', 'Types:', [...types], 'Input:', schema, 'Output:', ast);
return ast;
}
// Be careful to first process the intersection before processing its params,
// so that it gets first pick for standalone name.
const ast = parseAsTypeWithCache({
[JSONSchema_1.Parent]: schema[JSONSchema_1.Parent],
$id: schema.$id,
additionalProperties: schema.additionalProperties,
allOf: [],
description: schema.description,
required: schema.required,
title: schema.title,
}, 'ALL_OF', options, keyName, processed, usedNames);
ast.params = types.map(type =>
// We hoist description (for comment) and id/title (for standaloneName)
// to the parent intersection type, so we remove it from the children.
parseAsTypeWithCache((0, utils_1.maybeStripNameHints)(schema), type, options, keyName, processed, usedNames));
(0, utils_1.log)('blue', 'parser', 'Types:', types, 'Input:', schema, 'Output:', ast);
return ast;
if (types.size === 1) {
const type = [...types][0];
const ast = parseAsTypeWithCache(schema, type, options, keyName, processed, usedNames);
(0, utils_1.log)('blue', 'parser', 'Type:', type, 'Input:', schema, 'Output:', ast);
return ast;
}
throw new ReferenceError('Expected intersection schema. Please file an issue on GitHub.');
}

@@ -229,4 +223,6 @@ exports.parse = parse;

params: schema.type.map(type => {
const member = Object.assign(Object.assign({}, (0, lodash_1.omit)(schema, '$id', 'description', 'title')), { type, additionalProperties: schema.additionalProperties, required: schema.required });
return parse((0, utils_1.maybeStripDefault)(member), options, undefined, processed, usedNames);
const member = Object.assign(Object.assign({}, (0, lodash_1.omit)(schema, '$id', 'description', 'title')), { type });
(0, utils_1.maybeStripDefault)(member);
(0, applySchemaTyping_1.applySchemaTyping)(member);
return parse(member, options, undefined, processed, usedNames);
}),

@@ -233,0 +229,0 @@ type: 'UNION',

@@ -47,2 +47,4 @@ /// <reference types="lodash" />

}
export declare const Types: unique symbol;
export declare const Intersection: unique symbol;
/**

@@ -54,3 +56,5 @@ * Normalized JSON schema.

export interface NormalizedJSONSchema extends Omit<LinkedJSONSchema, 'definitions' | 'id'> {
[Intersection]?: NormalizedJSONSchema;
[Parent]: NormalizedJSONSchema | null;
[Types]: ReadonlySet<SchemaType>;
additionalItems?: boolean | NormalizedJSONSchema;

@@ -57,0 +61,0 @@ additionalProperties: boolean | NormalizedJSONSchema;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isCompound = exports.isPrimitive = exports.isBoolean = exports.getRootSchema = exports.Parent = void 0;
exports.isCompound = exports.isPrimitive = exports.isBoolean = exports.getRootSchema = exports.Intersection = exports.Types = exports.Parent = void 0;
const lodash_1 = require("lodash");
exports.Parent = Symbol('Parent');
exports.Types = Symbol('Types');
exports.Intersection = Symbol('Intersection');
exports.getRootSchema = (0, lodash_1.memoize)((schema) => {

@@ -7,0 +9,0 @@ const parent = schema[exports.Parent];

@@ -10,2 +10,2 @@ import { JSONSchema, SchemaType } from './types/JSONSchema';

*/
export declare function typesOfSchema(schema: JSONSchema): readonly [SchemaType, ...SchemaType[]];
export declare function typesOfSchema(schema: JSONSchema): Set<SchemaType>;

@@ -17,14 +17,14 @@ "use strict";

if (schema.tsType) {
return ['CUSTOM_TYPE'];
return new Set(['CUSTOM_TYPE']);
}
// Collect matched types
const matchedTypes = [];
const matchedTypes = new Set();
for (const [schemaType, f] of Object.entries(matchers)) {
if (f(schema)) {
matchedTypes.push(schemaType);
matchedTypes.add(schemaType);
}
}
// Default to an unnamed schema
if (!matchedTypes.length) {
return ['UNNAMED_SCHEMA'];
if (!matchedTypes.size) {
matchedTypes.add('UNNAMED_SCHEMA');
}

@@ -31,0 +31,0 @@ return matchedTypes;

@@ -1,2 +0,2 @@

import { JSONSchema, LinkedJSONSchema, NormalizedJSONSchema } from './types/JSONSchema';
import { JSONSchema, LinkedJSONSchema } from './types/JSONSchema';
import { JSONSchema4 } from 'json-schema';

@@ -34,13 +34,5 @@ export declare function Try<T>(fn: () => T, err: (e: Error) => any): T;

export declare function maybeStripDefault(schema: LinkedJSONSchema): LinkedJSONSchema;
/**
* Removes the schema's `$id`, `name`, and `description` properties
* if they exist.
* Useful when parsing intersections.
*
* Mutates `schema`.
*/
export declare function maybeStripNameHints(schema: NormalizedJSONSchema): NormalizedJSONSchema;
export declare function appendToDescription(existingDescription: string | undefined, ...values: string[]): string;
export declare function isSchemaLike(schema: LinkedJSONSchema): boolean;
export declare function isSchemaLike(schema: any): schema is LinkedJSONSchema;
export declare function parseFileAsJSONSchema(filename: string | null, contents: string): JSONSchema4;
export {};

@@ -6,3 +6,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.parseFileAsJSONSchema = exports.isSchemaLike = exports.appendToDescription = exports.maybeStripNameHints = exports.maybeStripDefault = exports.pathTransform = exports.escapeBlockComment = exports.log = exports.error = exports.generateName = exports.toSafeString = exports.stripExtension = exports.justName = exports.traverse = exports.Try = void 0;
exports.parseFileAsJSONSchema = exports.isSchemaLike = exports.appendToDescription = exports.maybeStripDefault = exports.pathTransform = exports.escapeBlockComment = exports.log = exports.error = exports.generateName = exports.toSafeString = exports.stripExtension = exports.justName = exports.traverse = exports.Try = void 0;
const lodash_1 = require("lodash");

@@ -69,2 +69,15 @@ const path_1 = require("path");

}
function traverseIntersection(schema, callback, processed) {
if (typeof schema !== 'object' || !schema) {
return;
}
const r = schema;
const intersection = r[JSONSchema_1.Intersection];
if (!intersection) {
return;
}
if (Array.isArray(intersection.allOf)) {
traverseArray(intersection.allOf, callback, processed);
}
}
function traverse(schema, callback, processed = new Set(), key) {

@@ -124,2 +137,3 @@ // Handle recursive schemas

}
traverseIntersection(schema, callback, processed);
// technically you can put definitions on any key

@@ -318,22 +332,2 @@ Object.keys(schema)

exports.maybeStripDefault = maybeStripDefault;
/**
* Removes the schema's `$id`, `name`, and `description` properties
* if they exist.
* Useful when parsing intersections.
*
* Mutates `schema`.
*/
function maybeStripNameHints(schema) {
if ('$id' in schema) {
delete schema.$id;
}
if ('description' in schema) {
delete schema.description;
}
if ('name' in schema) {
delete schema.name;
}
return schema;
}
exports.maybeStripNameHints = maybeStripNameHints;
function appendToDescription(existingDescription, ...values) {

@@ -350,2 +344,3 @@ if (existingDescription) {

}
// top-level schema
const parent = schema[JSONSchema_1.Parent];

@@ -352,0 +347,0 @@ if (parent === null) {

{
"name": "json-schema-to-typescript",
"version": "14.1.0",
"version": "15.0.0",
"description": "compile json schema to typescript typings",

@@ -5,0 +5,0 @@ "main": "dist/src/index.js",

import {JSONSchemaTypeName, LinkedJSONSchema, NormalizedJSONSchema, Parent} from './types/JSONSchema'
import {appendToDescription, escapeBlockComment, isSchemaLike, justName, toSafeString, traverse} from './utils'
import {Options} from './'
import {applySchemaTyping} from './applySchemaTyping'
import {DereferencedPaths} from './resolver'

@@ -234,2 +235,18 @@ import {isDeepStrictEqual} from 'util'

// Precalculation of the schema types is necessary because the ALL_OF type
// is implemented in a way that mutates the schema object. Detection of the
// NAMED_SCHEMA type relies on the presence of the $id property, which is
// hoisted to a parent schema object during the ALL_OF type implementation,
// and becomes unavailable if the same schema is used in multiple places.
//
// Precalculation of the `ALL_OF` intersection schema is necessary because
// the intersection schema needs to participate in the schema cache during
// the parsing step, so it cannot be re-calculated every time the schema
// is encountered.
rules.set('Pre-calculate schema types and intersections', schema => {
if (schema !== null && typeof schema === 'object') {
applySchemaTyping(schema)
}
})
export function normalize(

@@ -236,0 +253,0 @@ rootSchema: LinkedJSONSchema,

@@ -5,27 +5,15 @@ import {JSONSchema4Type, JSONSchema4TypeName} from 'json-schema'

import {Options} from './'
import {typesOfSchema} from './typesOfSchema'
import {
AST,
T_ANY,
T_ANY_ADDITIONAL_PROPERTIES,
TInterface,
TInterfaceParam,
TNamedInterface,
TTuple,
T_UNKNOWN,
T_UNKNOWN_ADDITIONAL_PROPERTIES,
TIntersection,
} from './types/AST'
import {
import {applySchemaTyping} from './applySchemaTyping'
import type {AST, TInterface, TInterfaceParam, TIntersection, TNamedInterface, TTuple} from './types/AST'
import {T_ANY, T_ANY_ADDITIONAL_PROPERTIES, T_UNKNOWN, T_UNKNOWN_ADDITIONAL_PROPERTIES} from './types/AST'
import type {
EnumJSONSchema,
getRootSchema,
isBoolean,
isPrimitive,
JSONSchemaWithDefinitions,
LinkedJSONSchema,
NormalizedJSONSchema,
Parent,
SchemaSchema,
SchemaType,
} from './types/JSONSchema'
import {generateName, log, maybeStripDefault, maybeStripNameHints} from './utils'
import {Intersection, Types, getRootSchema, isBoolean, isPrimitive} from './types/JSONSchema'
import {generateName, log, maybeStripDefault} from './utils'

@@ -51,36 +39,24 @@ export type Processed = Map<NormalizedJSONSchema, Map<SchemaType, AST>>

const types = typesOfSchema(schema)
if (types.length === 1) {
const ast = parseAsTypeWithCache(schema, types[0], options, keyName, processed, usedNames)
log('blue', 'parser', 'Types:', types, 'Input:', schema, 'Output:', ast)
const intersection = schema[Intersection]
const types = schema[Types]
if (intersection) {
const ast = parseAsTypeWithCache(intersection, 'ALL_OF', options, keyName, processed, usedNames) as TIntersection
types.forEach(type => {
ast.params.push(parseAsTypeWithCache(schema, type, options, keyName, processed, usedNames))
})
log('blue', 'parser', 'Types:', [...types], 'Input:', schema, 'Output:', ast)
return ast
}
// Be careful to first process the intersection before processing its params,
// so that it gets first pick for standalone name.
const ast = parseAsTypeWithCache(
{
[Parent]: schema[Parent],
$id: schema.$id,
additionalProperties: schema.additionalProperties,
allOf: [],
description: schema.description,
required: schema.required,
title: schema.title,
},
'ALL_OF',
options,
keyName,
processed,
usedNames,
) as TIntersection
if (types.size === 1) {
const type = [...types][0]
const ast = parseAsTypeWithCache(schema, type, options, keyName, processed, usedNames)
log('blue', 'parser', 'Type:', type, 'Input:', schema, 'Output:', ast)
return ast
}
ast.params = types.map(type =>
// We hoist description (for comment) and id/title (for standaloneName)
// to the parent intersection type, so we remove it from the children.
parseAsTypeWithCache(maybeStripNameHints(schema), type, options, keyName, processed, usedNames),
)
log('blue', 'parser', 'Types:', types, 'Input:', schema, 'Output:', ast)
return ast
throw new ReferenceError('Expected intersection schema. Please file an issue on GitHub.')
}

@@ -298,9 +274,6 @@

params: (schema.type as JSONSchema4TypeName[]).map(type => {
const member: NormalizedJSONSchema = {
...omit(schema, '$id', 'description', 'title'),
type,
additionalProperties: schema.additionalProperties,
required: schema.required,
}
return parse(maybeStripDefault(member as any), options, undefined, processed, usedNames)
const member: LinkedJSONSchema = {...omit(schema, '$id', 'description', 'title'), type}
maybeStripDefault(member)
applySchemaTyping(member)
return parse(member, options, undefined, processed, usedNames)
}),

@@ -307,0 +280,0 @@ type: 'UNION',

@@ -73,2 +73,5 @@ import {JSONSchema4, JSONSchema4Type, JSONSchema4TypeName} from 'json-schema'

export const Types = Symbol('Types')
export const Intersection = Symbol('Intersection')
/**

@@ -80,3 +83,5 @@ * Normalized JSON schema.

export interface NormalizedJSONSchema extends Omit<LinkedJSONSchema, 'definitions' | 'id'> {
[Intersection]?: NormalizedJSONSchema
[Parent]: NormalizedJSONSchema | null
[Types]: ReadonlySet<SchemaType>

@@ -83,0 +88,0 @@ additionalItems?: boolean | NormalizedJSONSchema

@@ -12,13 +12,13 @@ import {isPlainObject} from 'lodash'

*/
export function typesOfSchema(schema: JSONSchema): readonly [SchemaType, ...SchemaType[]] {
export function typesOfSchema(schema: JSONSchema): Set<SchemaType> {
// tsType is an escape hatch that supercedes all other directives
if (schema.tsType) {
return ['CUSTOM_TYPE']
return new Set(['CUSTOM_TYPE'])
}
// Collect matched types
const matchedTypes: SchemaType[] = []
const matchedTypes = new Set<SchemaType>()
for (const [schemaType, f] of Object.entries(matchers)) {
if (f(schema)) {
matchedTypes.push(schemaType as SchemaType)
matchedTypes.add(schemaType as SchemaType)
}

@@ -28,7 +28,7 @@ }

// Default to an unnamed schema
if (!matchedTypes.length) {
return ['UNNAMED_SCHEMA']
if (!matchedTypes.size) {
matchedTypes.add('UNNAMED_SCHEMA')
}
return matchedTypes as [SchemaType, ...SchemaType[]]
return matchedTypes
}

@@ -35,0 +35,0 @@

import {deburr, isPlainObject, trim, upperFirst} from 'lodash'
import {basename, dirname, extname, normalize, sep, posix} from 'path'
import {JSONSchema, LinkedJSONSchema, NormalizedJSONSchema, Parent} from './types/JSONSchema'
import {Intersection, JSONSchema, LinkedJSONSchema, NormalizedJSONSchema, Parent} from './types/JSONSchema'
import {JSONSchema4} from 'json-schema'

@@ -74,2 +74,22 @@ import yaml from 'js-yaml'

function traverseIntersection(
schema: LinkedJSONSchema,
callback: (schema: LinkedJSONSchema, key: string | null) => void,
processed: Set<LinkedJSONSchema>,
) {
if (typeof schema !== 'object' || !schema) {
return
}
const r = schema as unknown as Record<string | symbol, unknown>
const intersection = r[Intersection] as NormalizedJSONSchema | undefined
if (!intersection) {
return
}
if (Array.isArray(intersection.allOf)) {
traverseArray(intersection.allOf, callback, processed)
}
}
export function traverse(

@@ -134,2 +154,3 @@ schema: LinkedJSONSchema,

}
traverseIntersection(schema, callback, processed)

@@ -336,22 +357,2 @@ // technically you can put definitions on any key

/**
* Removes the schema's `$id`, `name`, and `description` properties
* if they exist.
* Useful when parsing intersections.
*
* Mutates `schema`.
*/
export function maybeStripNameHints(schema: NormalizedJSONSchema): NormalizedJSONSchema {
if ('$id' in schema) {
delete schema.$id
}
if ('description' in schema) {
delete schema.description
}
if ('name' in schema) {
delete schema.name
}
return schema
}
export function appendToDescription(existingDescription: string | undefined, ...values: string[]): string {

@@ -364,6 +365,8 @@ if (existingDescription) {

export function isSchemaLike(schema: LinkedJSONSchema) {
export function isSchemaLike(schema: any): schema is LinkedJSONSchema {
if (!isPlainObject(schema)) {
return false
}
// top-level schema
const parent = schema[Parent]

@@ -370,0 +373,0 @@ if (parent === null) {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc