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 2.4.1 to 2.4.2

example/index.js

10

dist/index.d.ts
/// <reference types="node" />
import { JSONSchema } from './JSONSchema';
import { TsType } from './TsTypes';
export declare function compile(schema: JSONSchema, path: string | undefined, settings?: TsType.TsTypeSettings): string;
export interface Settings {
declareReferenced?: boolean;
endPropertyWithSemicolon?: boolean;
endTypeWithSemicolon?: boolean;
useConstEnums?: boolean;
useFullReferencePathAsName?: boolean;
}
export declare function compile(schema: JSONSchema, path: string | undefined, settings?: Settings): string;
export declare function compileFromFile(inputFilename: string): Promise<string | NodeJS.ErrnoException>;

103

dist/index.js
"use strict";
var TsTypes_1 = require('./TsTypes');
var TsType = require('./TsTypes');
var fs_1 = require('fs');

@@ -36,4 +36,3 @@ var lodash_1 = require('lodash');

this.schema = schema;
var path = path_1.resolve(filePath);
this.filePath = path_1.parse(path);
this.filePath = path_1.parse(path_1.resolve(filePath));
this.declarations = new Map;

@@ -118,5 +117,5 @@ this.namedEnums = new Map;

var contents = tryFn(function () { return JSON.parse(file.toString()); }, function () { throw new TypeError("Referenced local schema \"" + fullPath + "\" contains malformed JSON"); });
var targetType = this.toTsType(contents, propName, false, true);
var targetType = this.toTsType(contents, propName, true);
var id = targetType.id
? targetType.toSafeType(this.settings)
? targetType.toType(this.settings)
: path_1.parse(fullPath).name;

@@ -126,3 +125,3 @@ if (this.settings.declareReferenced) {

}
return new TsTypes_1.TsType.Reference(id);
return new TsType.Reference(id);
};

@@ -133,3 +132,3 @@ // eg. "#/definitions/diskDevice" => ["definitions", "diskDevice"]

if (refPath === '#' || refPath === '#/') {
return TsTypes_1.TsType.Interface.reference(this.id);
return TsType.Interface.reference(this.id);
}

@@ -140,13 +139,13 @@ if (refPath[0] !== '#') {

var parts = refPath.slice(2).split('/');
var ret = this.settings.declareReferenced ? this.declarations.get(parts.join('/')) : undefined;
if (!ret) {
var cur = this.schema;
for (var i = 0; cur && i < parts.length; ++i) {
cur = cur[parts[i]];
}
ret = this.toTsType(cur);
if (this.settings.declareReferenced && (this.settings.declareSimpleType || !ret.isSimpleType()))
this.declareType(ret, parts.join('/'), this.settings.useFullReferencePathAsName ? parts.join('/') : lodash_1.last(parts));
var existingRef = this.declarations.get(parts.join('/'));
// resolve existing declaration?
if (existingRef) {
return existingRef;
}
return ret;
// resolve from elsewhere in the schema
var type = this.toTsType(lodash_1.get(this.schema, parts.join('.')));
if (this.settings.declareReferenced || !type.isSimpleType()) {
this.declareType(type, parts.join('/'), this.settings.useFullReferencePathAsName ? parts.join('/') : lodash_1.last(parts));
}
return type;
};

@@ -158,24 +157,7 @@ Compiler.prototype.declareType = function (type, refPath, id) {

};
Compiler.prototype.toStringLiteral = function (a) {
var _this = this;
switch (typeof a) {
case 'boolean':
case 'number':
case 'string':
return new TsTypes_1.TsType.Literal(a);
default: return new TsTypes_1.TsType.Interface(lodash_1.map(a, function (v, k) {
return {
name: k,
required: true,
type: _this.toStringLiteral(v)
};
}));
}
};
Compiler.prototype.generateEnumName = function (rule, propName) {
return rule.id || propName || "Enum" + this.namedEnums.size;
};
Compiler.prototype.generateTsType = function (rule, propName, isTop, isReference) {
Compiler.prototype.generateTsType = function (rule, propName, isReference) {
var _this = this;
if (isTop === void 0) { isTop = false; }
if (isReference === void 0) { isReference = false; }

@@ -187,26 +169,26 @@ switch (this.getRuleType(rule)) {

case RuleType.Enum:
return new TsTypes_1.TsType.Union(rule.enum.map(function (_) { return new TsTypes_1.TsType.Literal(_); }));
return new TsType.Union(rule.enum.map(function (_) { return new TsType.Literal(_); }));
case RuleType.NamedEnum:
Compiler.validateNamedEnum(rule);
var name = this.generateEnumName(rule, propName);
var tsEnum = new TsTypes_1.TsType.Enum(name, lodash_1.zip(rule.tsEnumNames, rule.enum).map(function (_) { return new TsTypes_1.TsType.EnumValue(_); }));
var tsEnum = new TsType.Enum(name, lodash_1.zip(rule.tsEnumNames, rule.enum).map(function (_) { return new TsType.EnumValue(_); }));
this.namedEnums.set(name, tsEnum);
return tsEnum;
case RuleType.Any: return new TsTypes_1.TsType.Any;
case RuleType.Literal: return new TsTypes_1.TsType.Literal(rule);
case RuleType.TypedArray: return new TsTypes_1.TsType.Array(this.toTsType(rule.items));
case RuleType.Array: return new TsTypes_1.TsType.Array;
case RuleType.Boolean: return new TsTypes_1.TsType.Boolean;
case RuleType.Null: return new TsTypes_1.TsType.Null;
case RuleType.Number: return new TsTypes_1.TsType.Number;
case RuleType.Object: return new TsTypes_1.TsType.Object;
case RuleType.String: return new TsTypes_1.TsType.String;
case RuleType.Any: return new TsType.Any;
case RuleType.Literal: return new TsType.Literal(rule);
case RuleType.TypedArray: return new TsType.Array(this.toTsType(rule.items));
case RuleType.Array: return new TsType.Array;
case RuleType.Boolean: return new TsType.Boolean;
case RuleType.Null: return new TsType.Null;
case RuleType.Number: return new TsType.Number;
case RuleType.Object: return new TsType.Object;
case RuleType.String: return new TsType.String;
case RuleType.AllOf:
return new TsTypes_1.TsType.Intersection(rule.allOf.map(function (_) { return _this.toTsType(_); }));
return new TsType.Intersection(rule.allOf.map(function (_) { return _this.toTsType(_); }));
case RuleType.AnyOf:
return new TsTypes_1.TsType.Union(rule.anyOf.map(function (_) { return _this.toTsType(_); }));
return new TsType.Union(rule.anyOf.map(function (_) { return _this.toTsType(_); }));
case RuleType.Reference:
return this.resolveRef(rule.$ref, propName);
case RuleType.Union:
return new TsTypes_1.TsType.Union(rule.type.map(function (_) { return _this.toTsType({ type: _ }); }));
return new TsType.Union(rule.type.map(function (_) { return _this.toTsType({ type: _ }); }));
}

@@ -223,6 +205,5 @@ throw new Error('Unknown rule:' + rule.toString());

};
Compiler.prototype.toTsType = function (rule, propName, isTop, isReference) {
if (isTop === void 0) { isTop = false; }
Compiler.prototype.toTsType = function (rule, propName, isReference) {
if (isReference === void 0) { isReference = false; }
var type = this.generateTsType(rule, propName, isTop, isReference);
var type = this.generateTsType(rule, propName, isReference);
if (!type.id) {

@@ -249,3 +230,3 @@ // the type is not declared, let's check if we should declare it or keep it inline

if ('default' in schema)
return new TsTypes_1.TsType.Null;
return new TsType.Null;
}

@@ -255,4 +236,4 @@ if (this.supportsAdditionalProperties(copy)) {

if (short && props.length === 0)
return new TsTypes_1.TsType.Any;
var type = short ? new TsTypes_1.TsType.Any : this.toTsType(copy.additionalProperties);
return new TsType.Any;
var type = short ? new TsType.Any : this.toTsType(copy.additionalProperties);
props.push({

@@ -262,7 +243,13 @@ name: '[k: string]',

type: type
});
}); // TODO: fix type
}
return new TsTypes_1.TsType.Interface(props);
return new TsType.Interface(props);
};
Compiler.DEFAULT_SETTINGS = TsTypes_1.TsType.DEFAULT_SETTINGS;
Compiler.DEFAULT_SETTINGS = {
declareReferenced: true,
endPropertyWithSemicolon: true,
endTypeWithSemicolon: true,
useConstEnums: true,
useFullReferencePathAsName: false
};
Compiler.DEFAULT_SCHEMA = {

@@ -269,0 +256,0 @@ additionalProperties: true,

@@ -1,98 +0,80 @@

export declare namespace TsType {
interface TsTypeSettings {
declareReferenced?: boolean;
declareSimpleType?: boolean;
endPropertyWithSemicolon?: boolean;
endTypeWithSemicolon?: boolean;
useConstEnums?: boolean;
useFullReferencePathAsName?: boolean;
}
const DEFAULT_SETTINGS: TsTypeSettings;
abstract class TsTypeBase {
id: string;
description?: string;
protected generateComment(string: string): string[];
protected safeId(): string;
protected toBlockComment(settings: TsTypeSettings): string;
protected _toDeclaration(decl: string, settings: TsTypeSettings): string;
protected abstract _type(settings: TsTypeSettings): string;
isSimpleType(): boolean;
toDeclaration(settings: TsTypeSettings): string;
toSafeType(settings: TsTypeSettings): string;
toType(settings: TsTypeSettings): string;
toString(): string;
}
interface TsProp {
name: string;
required: boolean;
type: TsTypeBase;
}
class Any extends TsTypeBase {
_type(): string;
}
class String extends TsTypeBase {
_type(): string;
}
class Boolean extends TsTypeBase {
_type(): string;
}
class Number extends TsTypeBase {
_type(): string;
}
class Object extends TsTypeBase {
_type(): string;
}
class Null extends TsTypeBase {
_type(): string;
}
class Literal extends TsTypeBase {
private value;
constructor(value: any);
_type(): string;
}
class Reference extends TsTypeBase {
private value;
constructor(value: string);
_type(): string;
}
class EnumValue {
identifier: string;
value: string;
constructor(enumValues: string[]);
toDeclaration(): string;
toString(): string;
}
class Enum extends TsTypeBase {
id: string;
enumValues: EnumValue[];
constructor(id: string, enumValues: EnumValue[]);
isSimpleType(): boolean;
_type(settings: TsTypeSettings): string;
toSafeType(settings: TsTypeSettings): string;
toDeclaration(settings: TsTypeSettings): string;
}
class Array extends TsTypeBase {
private type;
constructor(type?: TsTypeBase);
_type(settings: TsTypeSettings): string;
}
class Intersection extends TsTypeBase {
protected data: TsTypeBase[];
constructor(data: TsTypeBase[]);
isSimpleType(): boolean;
_type(settings: TsTypeSettings): string;
toSafeType(settings: TsTypeSettings): string;
}
class Union extends Intersection {
isSimpleType(): boolean;
_type(settings: TsTypeSettings): string;
}
class Interface extends TsTypeBase {
private props;
constructor(props: TsProp[]);
static reference(id: string): Interface;
protected _type(settings: TsTypeSettings): string;
isSimpleType(): boolean;
toDeclaration(settings: TsTypeSettings): string;
}
import { Settings } from './index';
export declare abstract class TsType<T> {
protected value: T;
id: string;
description?: string;
constructor(value: T);
protected safeId(): string;
protected toBlockComment(): string;
isSimpleType(): boolean;
toDeclaration(settings: Settings): string;
toType(settings: Settings): string;
abstract toString(settings: Settings): string;
}
export interface TsProp<T> {
name: string;
required: boolean;
type: TsType<T>;
}
export declare class Any extends TsType<void> {
constructor();
toString(): string;
}
export declare class String extends TsType<void> {
constructor();
toString(): string;
}
export declare class Boolean extends TsType<void> {
constructor();
toString(): string;
}
export declare class Number extends TsType<void> {
constructor();
toString(): string;
}
export declare class Object extends TsType<void> {
constructor();
toString(): string;
}
export declare class Null extends TsType<void> {
constructor();
toString(): string;
}
export declare class Literal<T> extends TsType<T> {
toString(): string;
}
export declare class Reference extends TsType<string> {
toString(): string;
}
export declare class EnumValue extends TsType<string> {
identifier: string;
value: string;
constructor([identifier, value]: string[]);
toDeclaration(): string;
toString(): string;
}
export declare class Enum extends TsType<EnumValue[]> {
id: string;
constructor(id: string, value: EnumValue[]);
isSimpleType(): boolean;
toString(settings: Settings): string;
toDeclaration(settings: Settings): string;
}
export declare class Array extends TsType<TsType<any>> {
constructor(value?: TsType<any>);
toString(settings: Settings): string;
}
export declare class Intersection<T> extends TsType<TsType<T>[]> {
isSimpleType(): boolean;
toString(settings: Settings): string;
}
export declare class Union<T> extends TsType<TsType<T>[]> {
isSimpleType(): boolean;
toString(settings: Settings): string;
}
export declare class Interface extends TsType<TsProp<any>[]> {
static reference(id: string): Interface;
toString(settings: Settings): string;
isSimpleType(): boolean;
toDeclaration(settings: Settings): string;
}

@@ -12,253 +12,220 @@ "use strict";

var INDENT_STRING = ' ';
var TsType;
(function (TsType) {
TsType.DEFAULT_SETTINGS = {
declareReferenced: true,
declareSimpleType: false,
endPropertyWithSemicolon: true,
endTypeWithSemicolon: true,
useConstEnums: true,
useFullReferencePathAsName: false
var TsType = (function () {
function TsType(value) {
this.value = value;
}
TsType.prototype.safeId = function () {
return nameToTsSafeName(this.id);
};
var TsTypeBase = (function () {
function TsTypeBase() {
}
TsTypeBase.prototype.generateComment = function (string) {
return [
COMMENT_START
].concat(string.split('\n').map(function (_) { return COMMENT_INDENT + _; }), [
COMMENT_END
]);
};
TsTypeBase.prototype.safeId = function () {
return nameToTsSafeName(this.id);
};
TsTypeBase.prototype.toBlockComment = function (settings) {
return this.description && !this.isSimpleType()
? this.generateComment(this.description).join('\n') + "\n"
: '';
};
TsTypeBase.prototype._toDeclaration = function (decl, settings) {
return this.toBlockComment(settings) + decl + (settings.endTypeWithSemicolon ? ';' : '');
};
TsTypeBase.prototype.isSimpleType = function () { return true; };
TsTypeBase.prototype.toDeclaration = function (settings) {
return this._toDeclaration("export type " + this.safeId() + " = " + this._type(settings), settings);
};
TsTypeBase.prototype.toSafeType = function (settings) {
return this.toType(settings);
};
TsTypeBase.prototype.toType = function (settings) {
return this.safeId() || this._type(settings);
};
TsTypeBase.prototype.toString = function () {
return this._type(TsType.DEFAULT_SETTINGS);
};
return TsTypeBase;
}());
TsType.TsTypeBase = TsTypeBase;
var Any = (function (_super) {
__extends(Any, _super);
function Any() {
_super.apply(this, arguments);
}
Any.prototype._type = function () {
return 'any';
};
return Any;
}(TsTypeBase));
TsType.Any = Any;
var String = (function (_super) {
__extends(String, _super);
function String() {
_super.apply(this, arguments);
}
String.prototype._type = function () {
return 'string';
};
return String;
}(TsTypeBase));
TsType.String = String;
var Boolean = (function (_super) {
__extends(Boolean, _super);
function Boolean() {
_super.apply(this, arguments);
}
Boolean.prototype._type = function () {
return 'boolean';
};
return Boolean;
}(TsTypeBase));
TsType.Boolean = Boolean;
var Number = (function (_super) {
__extends(Number, _super);
function Number() {
_super.apply(this, arguments);
}
Number.prototype._type = function () {
return 'number';
};
return Number;
}(TsTypeBase));
TsType.Number = Number;
var Object = (function (_super) {
__extends(Object, _super);
function Object() {
_super.apply(this, arguments);
}
Object.prototype._type = function () {
return 'Object';
};
return Object;
}(TsTypeBase));
TsType.Object = Object;
var Null = (function (_super) {
__extends(Null, _super);
function Null() {
_super.apply(this, arguments);
}
Null.prototype._type = function () {
return 'null';
};
return Null;
}(TsTypeBase));
TsType.Null = Null;
var Literal = (function (_super) {
__extends(Literal, _super);
function Literal(value) {
_super.call(this);
this.value = value;
}
Literal.prototype._type = function () {
return JSON.stringify(this.value);
};
return Literal;
}(TsTypeBase));
TsType.Literal = Literal;
var Reference = (function (_super) {
__extends(Reference, _super);
function Reference(value) {
_super.call(this);
this.value = value;
}
Reference.prototype._type = function () { return this.value; };
return Reference;
}(TsTypeBase));
TsType.Reference = Reference;
var EnumValue = (function () {
function EnumValue(enumValues) {
this.identifier = enumValues[0];
this.value = enumValues[1];
}
EnumValue.prototype.toDeclaration = function () {
// if there is a value associated with the identifier, declare as identifier=value
// else declare as identifier
return "" + this.identifier + (this.value ? (' = ' + this.value) : '');
};
EnumValue.prototype.toString = function () {
return "Enum" + this.identifier;
};
return EnumValue;
}());
TsType.EnumValue = EnumValue;
var Enum = (function (_super) {
__extends(Enum, _super);
function Enum(id, enumValues) {
_super.call(this);
this.id = id;
this.enumValues = enumValues;
}
Enum.prototype.isSimpleType = function () { return false; };
Enum.prototype._type = function (settings) {
return this.safeId();
};
Enum.prototype.toSafeType = function (settings) {
return "" + this.toType(settings);
};
Enum.prototype.toDeclaration = function (settings) {
return this.toBlockComment(settings)
+ ("export " + (settings.useConstEnums ? 'const ' : '') + "enum " + this.safeId() + " {")
+ '\n'
+ INDENT_STRING
+ this.enumValues.map(function (_) { return _.toDeclaration(); }).join(",\n" + INDENT_STRING)
+ '\n'
+ '}';
};
return Enum;
}(TsTypeBase));
TsType.Enum = Enum;
var Array = (function (_super) {
__extends(Array, _super);
function Array(type) {
_super.call(this);
this.type = type;
}
Array.prototype._type = function (settings) {
var type = (this.type || new Any()).toSafeType(settings);
return (type.indexOf('|') > -1 || type.indexOf('&') > -1 ? "(" + type + ")" : type) + "[]"; // hacky
};
return Array;
}(TsTypeBase));
TsType.Array = Array;
var Intersection = (function (_super) {
__extends(Intersection, _super);
function Intersection(data) {
_super.call(this);
this.data = data;
}
Intersection.prototype.isSimpleType = function () { return this.data.filter(function (_) { return !(_ instanceof Null); }).length <= 1; };
Intersection.prototype._type = function (settings) {
return this.data
.filter(function (_) { return !(_ instanceof Null); })
.map(function (_) { return _.toSafeType(settings); })
.join(' & ');
};
Intersection.prototype.toSafeType = function (settings) {
return "" + this.toType(settings);
};
return Intersection;
}(TsTypeBase));
TsType.Intersection = Intersection;
var Union = (function (_super) {
__extends(Union, _super);
function Union() {
_super.apply(this, arguments);
}
Union.prototype.isSimpleType = function () { return this.data.length <= 1; };
Union.prototype._type = function (settings) {
return this.data
.map(function (_) { return _.toSafeType(settings); })
.join(' | ');
};
return Union;
}(Intersection));
TsType.Union = Union;
var Interface = (function (_super) {
__extends(Interface, _super);
function Interface(props) {
_super.call(this);
this.props = props;
}
Interface.reference = function (id) {
var ret = new Interface([]);
ret.id = id;
return ret;
};
Interface.prototype._type = function (settings) {
var _this = this;
return "{\n"
+ (this.props.map(function (_) {
return ("" + INDENT_STRING + (_.type.description
? _this.generateComment(_.type.description).join("\n" + INDENT_STRING) + ("\n" + INDENT_STRING)
: '') + _.name + (_.required ? '' : '?') + ": " + _.type.toType(settings).replace(/\n/g, '\n' + INDENT_STRING) + (settings.endPropertyWithSemicolon ? ';' : ''));
}).join('\n') + "\n}");
};
Interface.prototype.isSimpleType = function () { return false; };
Interface.prototype.toDeclaration = function (settings) {
return this.toBlockComment(settings) + "export interface " + this.safeId() + " " + this._type(settings);
};
return Interface;
}(TsTypeBase));
TsType.Interface = Interface;
})(TsType = exports.TsType || (exports.TsType = {}));
TsType.prototype.toBlockComment = function () {
return this.description && !this.isSimpleType()
? generateComment(this.description).join('\n') + "\n"
: '';
};
TsType.prototype.isSimpleType = function () { return true; };
TsType.prototype.toDeclaration = function (settings) {
return this.toBlockComment()
+ ("export type " + this.safeId() + " = " + this.toString(settings))
+ (settings.endTypeWithSemicolon ? ';' : '');
};
TsType.prototype.toType = function (settings) {
return this.safeId() || this.toString(settings);
};
return TsType;
}());
exports.TsType = TsType;
var Any = (function (_super) {
__extends(Any, _super);
function Any() {
_super.call(this, undefined);
}
Any.prototype.toString = function () {
return 'any';
};
return Any;
}(TsType));
exports.Any = Any;
var String = (function (_super) {
__extends(String, _super);
function String() {
_super.call(this, undefined);
}
String.prototype.toString = function () {
return 'string';
};
return String;
}(TsType));
exports.String = String;
var Boolean = (function (_super) {
__extends(Boolean, _super);
function Boolean() {
_super.call(this, undefined);
}
Boolean.prototype.toString = function () {
return 'boolean';
};
return Boolean;
}(TsType));
exports.Boolean = Boolean;
var Number = (function (_super) {
__extends(Number, _super);
function Number() {
_super.call(this, undefined);
}
Number.prototype.toString = function () {
return 'number';
};
return Number;
}(TsType));
exports.Number = Number;
var Object = (function (_super) {
__extends(Object, _super);
function Object() {
_super.call(this, undefined);
}
Object.prototype.toString = function () {
return 'Object';
};
return Object;
}(TsType));
exports.Object = Object;
var Null = (function (_super) {
__extends(Null, _super);
function Null() {
_super.call(this, undefined);
}
Null.prototype.toString = function () {
return 'null';
};
return Null;
}(TsType));
exports.Null = Null;
var Literal = (function (_super) {
__extends(Literal, _super);
function Literal() {
_super.apply(this, arguments);
}
Literal.prototype.toString = function () {
return JSON.stringify(this.value);
};
return Literal;
}(TsType));
exports.Literal = Literal;
var Reference = (function (_super) {
__extends(Reference, _super);
function Reference() {
_super.apply(this, arguments);
}
Reference.prototype.toString = function () { return this.value; };
return Reference;
}(TsType));
exports.Reference = Reference;
var EnumValue = (function (_super) {
__extends(EnumValue, _super);
function EnumValue(_a) {
var identifier = _a[0], value = _a[1];
_super.call(this, value);
this.identifier = identifier;
}
EnumValue.prototype.toDeclaration = function () {
// if there is a value associated with the identifier, declare as identifier=value
// else declare as identifier
return "" + this.identifier + (this.value ? (' = ' + this.value) : '');
};
EnumValue.prototype.toString = function () {
return "Enum" + this.identifier;
};
return EnumValue;
}(TsType));
exports.EnumValue = EnumValue;
var Enum = (function (_super) {
__extends(Enum, _super);
function Enum(id, value) {
_super.call(this, value);
this.id = id;
}
Enum.prototype.isSimpleType = function () { return false; };
Enum.prototype.toString = function (settings) {
return this.safeId();
};
Enum.prototype.toDeclaration = function (settings) {
return this.toBlockComment()
+ ("export " + (settings.useConstEnums ? 'const ' : '') + "enum " + this.safeId() + " {")
+ '\n'
+ INDENT_STRING
+ this.value.map(function (_) { return _.toDeclaration(); }).join(",\n" + INDENT_STRING)
+ '\n'
+ '}';
};
return Enum;
}(TsType));
exports.Enum = Enum;
var Array = (function (_super) {
__extends(Array, _super);
function Array(value) {
if (value === void 0) { value = new Any; }
_super.call(this, value);
}
Array.prototype.toString = function (settings) {
var type = this.value.toType(settings);
return (type.indexOf('|') > -1 || type.indexOf('&') > -1 ? "(" + type + ")" : type) + "[]"; // hacky
};
return Array;
}(TsType));
exports.Array = Array;
var Intersection = (function (_super) {
__extends(Intersection, _super);
function Intersection() {
_super.apply(this, arguments);
}
Intersection.prototype.isSimpleType = function () { return this.value.length <= 1; };
Intersection.prototype.toString = function (settings) {
return this.value
.filter(function (_) { return !(_ instanceof Null); })
.map(function (_) { return _.toType(settings); })
.join(' & ');
};
return Intersection;
}(TsType));
exports.Intersection = Intersection;
var Union = (function (_super) {
__extends(Union, _super);
function Union() {
_super.apply(this, arguments);
}
Union.prototype.isSimpleType = function () { return this.value.length <= 1; };
Union.prototype.toString = function (settings) {
return this.value
.map(function (_) { return _.toType(settings); })
.join(' | ');
};
return Union;
}(TsType));
exports.Union = Union;
var Interface = (function (_super) {
__extends(Interface, _super);
function Interface() {
_super.apply(this, arguments);
}
Interface.reference = function (id) {
var ret = new Interface([]);
ret.id = id;
return ret;
};
Interface.prototype.toString = function (settings) {
return "{\n"
+ (this.value.map(function (_) {
return ("" + INDENT_STRING + (_.type.description
? generateComment(_.type.description).join("\n" + INDENT_STRING) + ("\n" + INDENT_STRING)
: '') + _.name + (_.required ? '' : '?') + ": " + _.type.toType(settings).replace(/\n/g, '\n' + INDENT_STRING) // ghetto nested indents
+ (settings.endPropertyWithSemicolon ? ';' : ''));
}).join('\n') + "\n}");
};
Interface.prototype.isSimpleType = function () { return false; };
Interface.prototype.toDeclaration = function (settings) {
return this.toBlockComment() + "export interface " + this.safeId() + " " + this.toString(settings);
};
return Interface;
}(TsType));
exports.Interface = Interface;
// eg.

@@ -273,2 +240,9 @@ // foo -> Foo

}
function generateComment(string) {
return [
COMMENT_START
].concat(string.split('\n').map(function (_) { return COMMENT_INDENT + _; }), [
COMMENT_END
]);
}
//# sourceMappingURL=TsTypes.js.map
{
"name": "json-schema-to-typescript",
"version": "2.4.1",
"version": "2.4.2",
"description": "compile json schema to typescript typings",

@@ -10,4 +10,4 @@ "main": "dist/index.js",

"build-sources": "tsc -p ./tsconfig.json",
"build-tests": "tsc -p ./tsconfig.test.json",
"watch": "tsc -p ./tsconfig.json --watch && tsc -p ./tsconfig.test.json --watch",
"build-tests": "rm -rf ./dist_tests && tsc -p ./tsconfig.test.json",
"watch": "tsc -p ./tsconfig.json --watch & tsc -p ./tsconfig.test.json --watch",
"lint": "tslint -c tslint.json src/*.ts",

@@ -14,0 +14,0 @@ "test": "npm run build-tests && ava",

@@ -60,5 +60,8 @@ # json-schema-to-typescript [![Build Status][build]](https://circleci.com/gh/bcherny/json-schema-to-typescript) [![npm]](https://www.npmjs.com/package/json-schema-to-typescript) [![mit]](https://opensource.org/licenses/MIT)

import {compileFromFile} from 'json-schema-to-typescript'
fs.writeFileSync('foo.d.ts', await compileFromFile('foo.json'))
fs.writeFileSync('dist/foo.d.ts', await compileFromFile('src/foo.json'))
```
See [/example](example) for a fully working demo.
## Tests

@@ -65,0 +68,0 @@

import { EnumJSONSchema, JSONSchema, NamedEnumJSONSchema } from './JSONSchema'
import { TsType } from './TsTypes'
import * as TsType from './TsTypes'
import { readFile, readFileSync } from 'fs'
import { isPlainObject, last, map, merge, zip } from 'lodash'
import { get, isPlainObject, last, map, merge, zip } from 'lodash'
import { join, parse, ParsedPath, resolve } from 'path'

@@ -14,5 +14,20 @@

export interface Settings {
declareReferenced?: boolean
endPropertyWithSemicolon?: boolean
endTypeWithSemicolon?: boolean
useConstEnums?: boolean
useFullReferencePathAsName?: boolean
}
class Compiler {
static DEFAULT_SETTINGS = TsType.DEFAULT_SETTINGS
static DEFAULT_SETTINGS: Settings = {
declareReferenced: true,
endPropertyWithSemicolon: true,
endTypeWithSemicolon: true,
useConstEnums: true,
useFullReferencePathAsName: false
}
static DEFAULT_SCHEMA: JSONSchema = {

@@ -28,6 +43,5 @@ additionalProperties: true,

filePath: string | undefined = '',
settings?: TsType.TsTypeSettings
settings?: Settings
) {
let path = resolve(filePath)
this.filePath = parse(path)
this.filePath = parse(resolve(filePath))
this.declarations = new Map

@@ -37,3 +51,3 @@ this.namedEnums = new Map

this.settings = Object.assign({}, Compiler.DEFAULT_SETTINGS, settings)
this.declareType(this.toTsType(this.schema, '', true), this.id, this.id)
this.declareType(this.toTsType(this.schema, '', true) as TsType.Interface, this.id, this.id)
}

@@ -51,5 +65,5 @@

private settings: TsType.TsTypeSettings
private settings: Settings
private id: string
private declarations: Map<string, TsType.TsTypeBase>
private declarations: Map<string, TsType.TsType<any>>
private namedEnums: Map<string, TsType.Enum>

@@ -123,3 +137,3 @@ private filePath: ParsedPath

private resolveRefFromLocalFS(refPath: string, propName: string): TsType.TsTypeBase {
private resolveRefFromLocalFS<T>(refPath: string, propName: string): TsType.Reference {
const fullPath = resolve(join(this.filePath.dir, refPath))

@@ -139,9 +153,9 @@

)
const targetType = this.toTsType(contents, propName, false, true)
const targetType = this.toTsType(contents, propName, true)
const id = targetType.id
? targetType.toSafeType(this.settings)
? targetType.toType(this.settings)
: parse(fullPath).name
if (this.settings.declareReferenced) {
this.declareType(targetType, id, id)
this.declareType(targetType as TsType.Interface, id, id)
}

@@ -154,3 +168,3 @@

// only called in case of a $ref type
private resolveRef(refPath: string, propName: string): TsType.TsTypeBase {
private resolveRef(refPath: string, propName: string): TsType.TsType<any> {
if (refPath === '#' || refPath === '#/'){

@@ -165,17 +179,18 @@ return TsType.Interface.reference(this.id)

const parts = refPath.slice(2).split('/')
let ret = this.settings.declareReferenced ? this.declarations.get(parts.join('/')) : undefined
const existingRef = this.declarations.get(parts.join('/'))
if (!ret) {
let cur: any = this.schema
for (let i = 0; cur && i < parts.length; ++i) {
cur = cur[parts[i]]
}
ret = this.toTsType(cur)
if (this.settings.declareReferenced && (this.settings.declareSimpleType || !ret.isSimpleType()))
this.declareType(ret, parts.join('/'), this.settings.useFullReferencePathAsName ? parts.join('/') : last(parts))
// resolve existing declaration?
if (existingRef) {
return existingRef
}
return ret
// resolve from elsewhere in the schema
const type = this.toTsType(get(this.schema, parts.join('.')))
if (this.settings.declareReferenced || !type.isSimpleType()) {
this.declareType(type as TsType.Interface, parts.join('/'), this.settings.useFullReferencePathAsName ? parts.join('/') : last(parts))
}
return type
}
private declareType(type: TsType.TsTypeBase, refPath: string, id: string) {
private declareType(type: TsType.Interface, refPath: string, id: string) {
type.id = id

@@ -186,23 +201,2 @@ this.declarations.set(refPath, type)

private toStringLiteral(a: boolean | number | string | Object): TsType.TsTypeBase {
switch (typeof a) {
case 'boolean':
case 'number':
case 'string':
return new TsType.Literal(a)
default: return new TsType.Interface(map(
(a as any),
(v: JSONSchema, k: string) => {
return {
name: k,
required: true,
type: this.toStringLiteral(v)
}
}))
// TODO: support array types?
// TODO: support enums of enums
// TODO: support nulls
}
}
private generateEnumName(rule: JSONSchema, propName: string | undefined): string {

@@ -212,3 +206,3 @@ return rule.id || propName || `Enum${this.namedEnums.size}`

private generateTsType (rule: JSONSchema, propName?: string, isTop: boolean = false, isReference: boolean = false): TsType.TsTypeBase {
private generateTsType (rule: JSONSchema, propName?: string, isReference: boolean = false): TsType.TsType<any> {
switch (this.getRuleType(rule)) {

@@ -267,9 +261,8 @@ case RuleType.AnonymousSchema:

private toTsType(
private toTsType<T>(
rule: JSONSchema,
propName?: string,
isTop: boolean = false,
isReference: boolean = false
): TsType.TsTypeBase {
const type = this.generateTsType(rule, propName, isTop, isReference)
): TsType.TsType<T> {
const type = this.generateTsType(rule, propName, isReference)
if (!type.id) {

@@ -284,3 +277,3 @@ // the type is not declared, let's check if we should declare it or keep it inline

}
private toTsDeclaration(schema: JSONSchema): TsType.TsTypeBase {
private toTsDeclaration(schema: JSONSchema): TsType.Interface | TsType.Null {
const copy = merge({}, Compiler.DEFAULT_SCHEMA, schema)

@@ -308,4 +301,4 @@ const props = map(

required: true,
type: type
})
type
} as any) // TODO: fix type
}

@@ -319,3 +312,3 @@ return new TsType.Interface(props)

path: string | undefined,
settings?: TsType.TsTypeSettings
settings?: Settings
): string {

@@ -322,0 +315,0 @@ return new Compiler(schema, path, settings).toString()

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

import { Settings } from './index'
import { camelCase, upperFirst } from 'lodash'

@@ -8,211 +9,170 @@

export namespace TsType {
export abstract class TsType<T> {
id: string
description?: string
export interface TsTypeSettings {
declareReferenced?: boolean
declareSimpleType?: boolean
endPropertyWithSemicolon?: boolean
endTypeWithSemicolon?: boolean
useConstEnums?: boolean
useFullReferencePathAsName?: boolean
}
constructor(protected value: T) {}
export const DEFAULT_SETTINGS: TsTypeSettings = {
declareReferenced: true,
declareSimpleType: false,
endPropertyWithSemicolon: true,
endTypeWithSemicolon: true,
useConstEnums: true,
useFullReferencePathAsName: false
protected safeId() {
return nameToTsSafeName(this.id)
}
export abstract class TsTypeBase {
id: string
description?: string
protected generateComment(string: string): string[] {
return [
COMMENT_START,
...string.split('\n').map(_ => COMMENT_INDENT + _),
COMMENT_END
]
}
protected safeId() {
return nameToTsSafeName(this.id)
}
protected toBlockComment(settings: TsTypeSettings) {
return this.description && !this.isSimpleType()
? `${this.generateComment(this.description).join('\n')}\n`
: ''
}
protected _toDeclaration(decl: string, settings: TsTypeSettings): string {
return this.toBlockComment(settings) + decl + (settings.endTypeWithSemicolon ? ';' : '')
}
protected abstract _type(settings: TsTypeSettings): string
isSimpleType() { return true }
toDeclaration(settings: TsTypeSettings): string {
return this._toDeclaration(`export type ${this.safeId()} = ${this._type(settings)}`, settings)
}
toSafeType(settings: TsTypeSettings): string {
return this.toType(settings)
}
toType(settings: TsTypeSettings): string {
return this.safeId() || this._type(settings)
}
toString(): string {
return this._type(DEFAULT_SETTINGS)
}
protected toBlockComment() {
return this.description && !this.isSimpleType()
? `${generateComment(this.description).join('\n')}\n`
: ''
}
export interface TsProp {
name: string
required: boolean
type: TsTypeBase
isSimpleType() { return true }
toDeclaration(settings: Settings): string {
return this.toBlockComment()
+ `export type ${this.safeId()} = ${this.toString(settings)}`
+ (settings.endTypeWithSemicolon ? ';' : '')
}
toType(settings: Settings): string {
return this.safeId() || this.toString(settings)
}
abstract toString(settings: Settings): string
}
export class Any extends TsTypeBase {
_type() {
return 'any'
}
export interface TsProp<T> {
name: string
required: boolean
type: TsType<T>
}
export class Any extends TsType<void> {
constructor() { super(undefined) }
toString() {
return 'any'
}
export class String extends TsTypeBase {
_type() {
return 'string'
}
}
export class String extends TsType<void> {
constructor() { super(undefined) }
toString() {
return 'string'
}
export class Boolean extends TsTypeBase {
_type() {
return 'boolean'
}
}
export class Boolean extends TsType<void> {
constructor() { super(undefined) }
toString() {
return 'boolean'
}
export class Number extends TsTypeBase {
_type() {
return 'number'
}
}
export class Number extends TsType<void> {
constructor() { super(undefined) }
toString() {
return 'number'
}
export class Object extends TsTypeBase {
_type() {
return 'Object'
}
}
export class Object extends TsType<void> {
constructor() { super(undefined) }
toString() {
return 'Object'
}
export class Null extends TsTypeBase {
_type() {
return 'null'
}
}
export class Null extends TsType<void> {
constructor() { super(undefined) }
toString() {
return 'null'
}
export class Literal extends TsTypeBase {
constructor(private value: any) { super() }
_type() {
return JSON.stringify(this.value)
}
}
export class Literal<T> extends TsType<T> {
toString() {
return JSON.stringify(this.value)
}
}
export class Reference extends TsTypeBase {
constructor(private value: string) { super() }
_type() { return this.value }
}
export class Reference extends TsType<string> {
toString() { return this.value }
}
export class EnumValue {
identifier: string
value: string
export class EnumValue extends TsType<string> {
identifier: string
value: string
constructor(enumValues: string[]) {
this.identifier = enumValues[0]
this.value = enumValues[1]
}
constructor([identifier, value]: string[]) {
super(value)
this.identifier = identifier
}
toDeclaration(){
// if there is a value associated with the identifier, declare as identifier=value
// else declare as identifier
return `${this.identifier}${this.value ? (' = ' + this.value) : ''}`
}
toDeclaration(){
// if there is a value associated with the identifier, declare as identifier=value
// else declare as identifier
return `${this.identifier}${this.value ? (' = ' + this.value) : ''}`
}
toString(){
return `Enum${this.identifier}`
}
toString(){
return `Enum${this.identifier}`
}
}
export class Enum extends TsTypeBase {
constructor(public id: string, public enumValues: EnumValue[]) {
super()
}
isSimpleType() { return false }
_type(settings: TsTypeSettings): string {
return this.safeId()
}
toSafeType(settings: TsTypeSettings) {
return `${this.toType(settings)}`
}
toDeclaration(settings: TsTypeSettings): string {
return this.toBlockComment(settings)
+ `export ${settings.useConstEnums ? 'const ' : ''}enum ${this.safeId()} {`
+ '\n'
+ INDENT_STRING
+ this.enumValues.map(_ => _.toDeclaration()).join(`,\n${INDENT_STRING}`)
+ '\n'
+ '}'
}
export class Enum extends TsType<EnumValue[]> {
constructor(public id: string, value: EnumValue[]) {
super(value)
}
isSimpleType() { return false }
toString(settings: Settings): string {
return this.safeId()
}
toDeclaration(settings: Settings): string {
return this.toBlockComment()
+ `export ${settings.useConstEnums ? 'const ' : ''}enum ${this.safeId()} {`
+ '\n'
+ INDENT_STRING
+ this.value.map(_ => _.toDeclaration()).join(`,\n${INDENT_STRING}`)
+ '\n'
+ '}'
}
}
export class Array extends TsTypeBase {
constructor(private type?: TsTypeBase) { super() }
_type(settings: TsTypeSettings) {
const type = (this.type || new Any()).toSafeType(settings)
return `${type.indexOf('|') > -1 || type.indexOf('&') > -1 ? `(${type})` : type}[]` // hacky
}
export class Array extends TsType<TsType<any>> {
constructor(value: TsType<any> = new Any) { super(value) }
toString(settings: Settings) {
const type = this.value.toType(settings)
return `${type.indexOf('|') > -1 || type.indexOf('&') > -1 ? `(${type})` : type}[]` // hacky
}
export class Intersection extends TsTypeBase {
constructor(protected data: TsTypeBase[]) {
super()
}
isSimpleType() { return this.data.filter(_ => !(_ instanceof Null)).length <= 1 }
_type(settings: TsTypeSettings) {
return this.data
.filter(_ => !(_ instanceof Null))
.map(_ => _.toSafeType(settings))
.join(' & ')
}
toSafeType(settings: TsTypeSettings) {
return `${this.toType(settings)}`
}
}
export class Intersection<T> extends TsType<TsType<T>[]> {
isSimpleType() { return this.value.length <= 1 }
toString(settings: Settings) {
return this.value
.filter(_ => !(_ instanceof Null))
.map(_ => _.toType(settings))
.join(' & ')
}
export class Union extends Intersection {
isSimpleType() { return this.data.length <= 1 }
_type(settings: TsTypeSettings) {
return this.data
.map(_ => _.toSafeType(settings))
.join(' | ')
}
}
export class Union<T> extends TsType<TsType<T>[]> {
isSimpleType() { return this.value.length <= 1 }
toString(settings: Settings) {
return this.value
.map(_ => _.toType(settings))
.join(' | ')
}
}
export class Interface extends TsTypeBase {
constructor(private props: TsProp[]) {
super()
}
static reference(id: string) {
let ret = new Interface([])
ret.id = id
return ret
}
protected _type(settings: TsTypeSettings) {
return `{\n`
+ `${this.props.map(_ =>
`${INDENT_STRING}${_.type.description
? this.generateComment(_.type.description).join(`\n${INDENT_STRING}`) + `\n${INDENT_STRING}`
: ''
}${_.name}${_.required ? '' : '?'}: ${
_.type.toType(settings).replace(/\n/g, '\n' + INDENT_STRING)
}${
settings.endPropertyWithSemicolon ? ';' : ''
}`
).join('\n')}
export class Interface extends TsType<TsProp<any>[]> {
static reference(id: string) {
let ret = new Interface([])
ret.id = id
return ret
}
toString(settings: Settings) {
return `{\n`
+ `${this.value.map(_ =>
`${INDENT_STRING}${_.type.description
? generateComment(_.type.description).join(`\n${INDENT_STRING}`) + `\n${INDENT_STRING}`
: ''
}${_.name}${_.required ? '' : '?'}: ${
_.type.toType(settings).replace(/\n/g, '\n' + INDENT_STRING) // ghetto nested indents
}${
settings.endPropertyWithSemicolon ? ';' : ''
}`
).join('\n')}
}`
}
isSimpleType() { return false }
toDeclaration(settings: TsTypeSettings): string {
return `${this.toBlockComment(settings)}export interface ${this.safeId()} ${this._type(settings)}`
}
}
isSimpleType() { return false }
toDeclaration(settings: Settings): string {
return `${this.toBlockComment()}export interface ${this.safeId()} ${this.toString(settings)}`
}
}

@@ -229,1 +189,9 @@

}
function generateComment(string: string): string[] {
return [
COMMENT_START,
...string.split('\n').map(_ => COMMENT_INDENT + _),
COMMENT_END
]
}

@@ -38,3 +38,2 @@ export var schema = {

export var types = `export interface Foo {

@@ -41,0 +40,0 @@ a: string;

@@ -33,7 +33,7 @@ export var schema = {

"enum": [1, 2, 3],
"tsEnumNames": ["One","Two","Three"]
"tsEnumNames": ["One", "Two", "Three"]
},
"impliedNamedIntegerEnum": {
"enum": [4, 5, 6],
"tsEnumNames": ["Four","Five","Six"]
"tsEnumNames": ["Four", "Five", "Six"]
},

@@ -40,0 +40,0 @@ "impliedHeterogeneousEnum": {

@@ -150,3 +150,3 @@ export var schema = {

"default": {}
};
}

@@ -156,3 +156,2 @@ export var configurations = [

settings: {
declareSimpleType: true
},

@@ -210,55 +209,3 @@ types: `export type PositiveInteger = number;

}`
},
{
settings: {
declareSimpleType: false
},
types:`export type SimpleTypes = "array" | "boolean" | "integer" | "null" | "number" | "object" | "string";
/**
* Core schema meta-schema
*/
export interface HttpJsonSchemaOrgDraft04Schema {
id?: string;
$schema?: string;
title?: string;
description?: string;
default?: any;
multipleOf?: number;
maximum?: number;
exclusiveMaximum?: boolean;
minimum?: number;
exclusiveMinimum?: boolean;
maxLength?: number;
minLength?: number;
pattern?: string;
additionalItems?: boolean | HttpJsonSchemaOrgDraft04Schema;
items?: HttpJsonSchemaOrgDraft04Schema | HttpJsonSchemaOrgDraft04Schema[];
maxItems?: number;
minItems?: number;
uniqueItems?: boolean;
maxProperties?: number;
minProperties?: number;
required?: string[];
additionalProperties?: boolean | HttpJsonSchemaOrgDraft04Schema;
definitions?: {
[k: string]: HttpJsonSchemaOrgDraft04Schema;
};
properties?: {
[k: string]: HttpJsonSchemaOrgDraft04Schema;
};
patternProperties?: {
[k: string]: HttpJsonSchemaOrgDraft04Schema;
};
dependencies?: {
[k: string]: HttpJsonSchemaOrgDraft04Schema | string[];
};
enum?: any[];
type?: SimpleTypes | SimpleTypes[];
allOf?: HttpJsonSchemaOrgDraft04Schema[];
anyOf?: HttpJsonSchemaOrgDraft04Schema[];
oneOf?: HttpJsonSchemaOrgDraft04Schema[];
not?: HttpJsonSchemaOrgDraft04Schema;
[k: string]: any;
}`
}
]

@@ -1,7 +0,6 @@

import { compile } from '../src/index'
import { compile, Settings } from '../src/index'
import { JSONSchema } from '../src/JSONSchema'
import { TsType } from '../src/TsTypes'
import test from 'ava'
import * as fs from 'fs'
import { find } from 'lodash'
import * as fs from 'fs'
import * as path from 'path'

@@ -14,15 +13,19 @@

// exporting `const only=true` will only run that test
// exporting `const exclude=true` will not run that test
const only = find(modules, _ => _[1].only)
if (only) {
run(only[1], only[0])
} else {
modules.forEach(_ => run(_[1], _[0]))
modules
.filter(_ => !_[1].exclude)
.forEach(_ => run(_[1], _[0]))
}
interface TestCase {
configurations?: { settings: TsType.TsTypeSettings, types: string }[]
configurations?: { settings: Settings, types: string }[]
error?: { type: ErrorConstructor }
exclude?: boolean
schema: JSONSchema
settings?: TsType.TsTypeSettings
settings?: Settings
types?: string

@@ -29,0 +32,0 @@ only?: boolean

@@ -24,3 +24,5 @@ {

"no-unused-variable": true,
"no-var-keyword": true,
"object-literal-key-quotes": [true, "as-needed"],
"object-literal-shorthand": true,
"object-literal-sort-keys": true,

@@ -27,0 +29,0 @@ "one-line": [true, "check-catch", "check-finally", "check-else", "check-open-brace"],

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