Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

typescript-json-schema

Package Overview
Dependencies
Maintainers
1
Versions
93
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

typescript-json-schema - npm Package Compare versions

Comparing version 0.0.8 to 0.1.0

test/programs/array-and-description/main.ts

2

package.json
{
"name": "typescript-json-schema",
"version": "0.0.8",
"version": "0.1.0",
"description": "typescript-json-schema generates JSON Schema files from your Typescript sources",

@@ -5,0 +5,0 @@ "main": "typescript-json-schema.js",

@@ -8,6 +8,8 @@ import {assert} from "chai";

export function assertSchema(group: string, name: string, type: string) {
export function assertSchema(group: string, name: string, type: string, settings?: any) {
it(group + " should create correct schema", function() {
let settings = TJS.defaultArgs;
settings.generateRequired = true;
if(!settings) {
settings = TJS.getDefaultArgs();
settings.generateRequired = true;
}

@@ -25,2 +27,3 @@ const actual = TJS.generateSchema(TJS.getProgramFromFiles([resolve(base + group + "/" + name)]), type, settings);

describe("schema", function () {
assertSchema("array-and-description", "main.ts", "MyObject");
assertSchema("class-single", "main.ts", "MyObject");

@@ -30,7 +33,11 @@

assertSchema("interface-multi", "main.ts", "MyObject");
let settings = TJS.getDefaultArgs();
settings.useRootRef = true;
assertSchema("interface-recursion", "main.ts", "MyObject", settings); // this sample needs rootRef
assertSchema("module-interface-single", "main.ts", "MyObject");
// not supported right now
// assertSchema("module-interface-deep", "main.ts", "Def");
//assertSchema("module-interface-deep", "main.ts", "Def");

@@ -43,2 +50,3 @@ assertSchema("enums-string", "main.ts", "MyObject");

assertSchema("array-types", "main.ts", "MyArray");
assertSchema("type-union", "main.ts", "MyType");
assertSchema("type-aliases", "main.ts", "MyString");

@@ -45,0 +53,0 @@ assertSchema("type-aliases-fixed-size-array", "main.ts", "MyFixedSizeArray");

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

"use strict";
var ts = require("typescript");

@@ -8,13 +7,16 @@ var glob = require("glob");

(function (TJS) {
TJS.defaultArgs = {
useRef: true,
useRootRef: false,
useTitle: false,
useDefaultProperties: false,
usePropertyOrder: false,
generateRequired: false
};
function getDefaultArgs() {
return {
useRef: true,
useRootRef: false,
useTitle: false,
useDefaultProperties: false,
usePropertyOrder: false,
generateRequired: false
};
}
TJS.getDefaultArgs = getDefaultArgs;
var JsonSchemaGenerator = (function () {
function JsonSchemaGenerator(allSymbols, inheritingTypes, tc, args) {
if (args === void 0) { args = TJS.defaultArgs; }
if (args === void 0) { args = getDefaultArgs(); }
this.args = args;

@@ -83,3 +85,3 @@ this.sandbox = { sandboxvar: null };

};
JsonSchemaGenerator.prototype.getDefinitionForType = function (propertyType, tc, unionModifier) {
JsonSchemaGenerator.prototype.getDefinitionForRootType = function (propertyType, tc, definition, unionModifier) {
var _this = this;

@@ -90,10 +92,8 @@ if (unionModifier === void 0) { unionModifier = "oneOf"; }

var types = unionType.types.map(function (propType) {
return _this.getDefinitionForType(propType, tc);
return _this.getTypeDefinition(propType, tc);
});
var definition_1 = {};
definition_1[unionModifier] = types;
return definition_1;
definition[unionModifier] = types;
return definition;
}
var propertyTypeString = tc.typeToString(propertyType, undefined, ts.TypeFormatFlags.UseFullyQualifiedType);
var definition = {};
switch (propertyTypeString.toLowerCase()) {

@@ -115,3 +115,3 @@ case "string":

var tupleType = propertyType;
var fixedTypes = tupleType.elementTypes.map(function (elType) { return _this.getDefinitionForType(elType, tc); });
var fixedTypes = tupleType.elementTypes.map(function (elType) { return _this.getTypeDefinition(elType, tc); });
definition.type = "array";

@@ -127,3 +127,3 @@ definition.items = fixedTypes;

definition.type = "array";
definition.items = this.getDefinitionForType(arrayType, tc);
definition.items = this.getTypeDefinition(arrayType, tc);
}

@@ -140,3 +140,3 @@ else {

var propertyTypeString = tc.typeToString(propertyType, undefined, ts.TypeFormatFlags.UseFullyQualifiedType);
var definition = this.getDefinitionForType(propertyType, tc);
var definition = this.getTypeDefinition(propertyType, tc);
if (this.args.useTitle) {

@@ -179,17 +179,3 @@ definition.title = propertyName;

};
JsonSchemaGenerator.prototype.getTypeDefinition = function (typ, tc, asRef) {
if (asRef === void 0) { asRef = this.args.useRef; }
if (!typ.getSymbol()) {
return this.getDefinitionForType(typ, tc);
}
var node = typ.getSymbol().getDeclarations()[0];
if (node.kind == ts.SyntaxKind.EnumDeclaration) {
return this.getEnumDefinition(typ, tc, asRef);
}
else {
return this.getClassDefinition(typ, tc, asRef);
}
};
JsonSchemaGenerator.prototype.getEnumDefinition = function (clazzType, tc, asRef) {
if (asRef === void 0) { asRef = this.args.useRef; }
JsonSchemaGenerator.prototype.getEnumDefinition = function (clazzType, tc, definition) {
var node = clazzType.getSymbol().getDeclarations()[0];

@@ -219,22 +205,11 @@ var fullName = tc.typeToString(clazzType, undefined, ts.TypeFormatFlags.UseFullyQualifiedType);

});
var definition = {
type: "string",
title: fullName
};
definition.type = "string";
definition.title = fullName;
if (enumValues.length > 0) {
definition["enum"] = enumValues;
}
if (asRef) {
this.reffedDefinitions[fullName] = definition;
return {
"$ref": "#/definitions/" + fullName
};
}
else {
return definition;
}
return definition;
};
JsonSchemaGenerator.prototype.getClassDefinition = function (clazzType, tc, asRef) {
JsonSchemaGenerator.prototype.getClassDefinition = function (clazzType, tc, definition) {
var _this = this;
if (asRef === void 0) { asRef = this.args.useRef; }
var node = clazzType.getSymbol().getDeclarations()[0];

@@ -244,3 +219,3 @@ var clazz = node;

var fullName = tc.typeToString(clazzType, undefined, ts.TypeFormatFlags.UseFullyQualifiedType);
if (props.length == 0 && clazz.members.length == 1 && clazz.members[0].kind == ts.SyntaxKind.IndexSignature) {
if (props.length == 0 && clazz.members && clazz.members.length == 1 && clazz.members[0].kind == ts.SyntaxKind.IndexSignature) {
var indexSignature = clazz.members[0];

@@ -256,7 +231,5 @@ if (indexSignature.parameters.length != 1) {

var typ = tc.getTypeAtLocation(indexSignature.type);
var def = this.getDefinitionForType(typ, tc, "anyOf");
var definition = {
type: "array",
items: def
};
var def = this.getTypeDefinition(typ, tc, undefined, "anyOf");
definition.type = "array";
definition.items = def;
return definition;

@@ -268,5 +241,3 @@ }

});
var definition = {
"oneOf": oneOf
};
definition.oneOf = oneOf;
return definition;

@@ -277,12 +248,10 @@ }

var propertyName = prop.getName();
var definition = _this.getDefinitionForProperty(prop, tc, node);
if (definition != null) {
all[propertyName] = definition;
var propDef = _this.getDefinitionForProperty(prop, tc, node);
if (propDef != null) {
all[propertyName] = propDef;
}
return all;
}, {});
var definition = {
type: "object",
properties: propertyDefinitions
};
definition.type = "object";
definition.properties = propertyDefinitions;
if (this.args.useTitle) {

@@ -312,22 +281,43 @@ definition.title = fullName;

}
}
};
JsonSchemaGenerator.prototype.getTypeDefinition = function (typ, tc, asRef, unionModifier) {
if (asRef === void 0) { asRef = this.args.useRef; }
if (unionModifier === void 0) { unionModifier = "oneOf"; }
var fullName = tc.typeToString(typ, undefined, ts.TypeFormatFlags.UseFullyQualifiedType);
var definition = {};
if (!typ.getSymbol() || typ.getSymbol().name == "Array") {
return this.getDefinitionForRootType(typ, tc, definition, unionModifier);
}
if (!asRef || !this.reffedDefinitions[fullName]) {
if (asRef) {
this.reffedDefinitions[fullName] = definition;
return {
"$ref": "#/definitions/" + fullName
};
}
var node = typ.getSymbol().getDeclarations()[0];
if (node.kind == ts.SyntaxKind.EnumDeclaration) {
this.getEnumDefinition(typ, tc, definition);
}
else {
return definition;
this.getClassDefinition(typ, tc, definition);
}
}
if (asRef) {
return {
"$ref": "#/definitions/" + fullName
};
}
else {
return definition;
}
};
JsonSchemaGenerator.prototype.getClassDefinitionByName = function (clazzName, includeReffedDefinitions) {
JsonSchemaGenerator.prototype.getSchemaForSymbol = function (symbolName, includeReffedDefinitions) {
if (includeReffedDefinitions === void 0) { includeReffedDefinitions = true; }
if (!this.allSymbols[clazzName]) {
throw "type {clazzName} not found";
if (!this.allSymbols[symbolName]) {
throw "type " + symbolName + " not found";
}
var def = this.getTypeDefinition(this.allSymbols[clazzName], this.tc, this.args.useRootRef);
var def = this.getTypeDefinition(this.allSymbols[symbolName], this.tc, this.args.useRootRef);
if (this.args.useRef && includeReffedDefinitions && Object.keys(this.reffedDefinitions).length > 0) {
def.definitions = this.reffedDefinitions;
}
def["$schema"] = "http://json-schema.org/draft-04/schema#";
return def;

@@ -342,3 +332,3 @@ };

return JsonSchemaGenerator;
}());
})();
function getProgramFromFiles(files) {

@@ -352,8 +342,8 @@ var options = {

function generateSchema(program, fullTypeName, args) {
if (args === void 0) { args = TJS.defaultArgs; }
if (args === void 0) { args = getDefaultArgs(); }
var tc = program.getTypeChecker();
var diagnostics = ts.getPreEmitDiagnostics(program);
if (diagnostics.length == 0) {
var allSymbols_1 = {};
var inheritingTypes_1 = {};
var allSymbols = {};
var inheritingTypes = {};
program.getSourceFiles().forEach(function (sourceFile) {

@@ -366,12 +356,12 @@ function inspect(node, tc) {

var nodeType = tc.getTypeAtLocation(node);
var fullName_1 = tc.getFullyQualifiedName(node.symbol);
fullName_1 = fullName_1.replace(/".*"\./, "");
allSymbols_1[fullName_1] = nodeType;
var fullName = tc.getFullyQualifiedName(node.symbol);
fullName = fullName.replace(/".*"\./, "");
allSymbols[fullName] = nodeType;
var baseTypes = nodeType.getBaseTypes() || [];
baseTypes.forEach(function (baseType) {
var baseName = tc.typeToString(baseType, undefined, ts.TypeFormatFlags.UseFullyQualifiedType);
if (!inheritingTypes_1[baseName]) {
inheritingTypes_1[baseName] = [];
if (!inheritingTypes[baseName]) {
inheritingTypes[baseName] = [];
}
inheritingTypes_1[baseName].push(fullName_1);
inheritingTypes[baseName].push(fullName);
});

@@ -385,5 +375,4 @@ }

});
var generator = new JsonSchemaGenerator(allSymbols_1, inheritingTypes_1, tc, args);
var definition = generator.getClassDefinitionByName(fullTypeName);
definition["$schema"] = "http://json-schema.org/draft-04/schema#";
var generator = new JsonSchemaGenerator(allSymbols, inheritingTypes, tc, args);
var definition = generator.getSchemaForSymbol(fullTypeName);
return definition;

@@ -416,3 +405,3 @@ }

function exec(filePattern, fullTypeName, args) {
if (args === void 0) { args = TJS.defaultArgs; }
if (args === void 0) { args = getDefaultArgs(); }
var program;

@@ -431,16 +420,17 @@ if (path.basename(filePattern) == "tsconfig.json") {

var helpText = "Usage: node typescript-json-schema.js <path-to-typescript-files-or-tsconfig> <type>";
var defaultArgs = getDefaultArgs();
var args = require("yargs")
.usage(helpText)
.demand(2)
.boolean("refs").default("refs", TJS.defaultArgs.useRef)
.boolean("refs").default("refs", defaultArgs.useRef)
.describe("refs", "Create shared ref definitions.")
.boolean("topRef").default("topRef", TJS.defaultArgs.useRootRef)
.boolean("topRef").default("topRef", defaultArgs.useRootRef)
.describe("topRef", "Create a top-level ref definition.")
.boolean("titles").default("titles", TJS.defaultArgs.useTitle)
.boolean("titles").default("titles", defaultArgs.useTitle)
.describe("titles", "Creates titles in the output schema.")
.boolean("defaultProps").default("defaultProps", TJS.defaultArgs.useDefaultProperties)
.boolean("defaultProps").default("defaultProps", defaultArgs.useDefaultProperties)
.describe("defaultProps", "Create default properties definitions.")
.boolean("propOrder").default("propOrder", TJS.defaultArgs.usePropertyOrder)
.boolean("propOrder").default("propOrder", defaultArgs.usePropertyOrder)
.describe("propOrder", "Create property order definitions.")
.boolean("required").default("required", TJS.defaultArgs.generateRequired)
.boolean("required").default("required", defaultArgs.generateRequired)
.describe("required", "Create required array for non-optional properties.")

@@ -447,0 +437,0 @@ .argv;

@@ -10,10 +10,12 @@ import * as ts from "typescript";

export module TJS {
export const defaultArgs = {
useRef: true,
useRootRef: false,
useTitle: false,
useDefaultProperties: false,
usePropertyOrder: false,
generateRequired: false
};
export function getDefaultArgs() {
return {
useRef: true,
useRootRef: false,
useTitle: false,
useDefaultProperties: false,
usePropertyOrder: false,
generateRequired: false
};
}

@@ -38,3 +40,3 @@ class JsonSchemaGenerator {

constructor(allSymbols: { [name: string]: ts.Type }, inheritingTypes: { [baseName: string]: string[] }, tc: ts.TypeChecker, private args = defaultArgs) {
constructor(allSymbols: { [name: string]: ts.Type }, inheritingTypes: { [baseName: string]: string[] }, tc: ts.TypeChecker, private args = getDefaultArgs()) {
this.allSymbols = allSymbols;

@@ -122,9 +124,8 @@ this.inheritingTypes = inheritingTypes;

private getDefinitionForType(propertyType: ts.Type, tc: ts.TypeChecker, unionModifier: string = "oneOf") {
private getDefinitionForRootType(propertyType: ts.Type, tc: ts.TypeChecker, definition: any, unionModifier: string = "oneOf") {
if (propertyType.flags & ts.TypeFlags.Union) {
const unionType = <ts.UnionType>propertyType;
const types = unionType.types.map((propType) => {
return this.getDefinitionForType(propType, tc);
return this.getTypeDefinition(propType, tc);
});
let definition = {};
definition[unionModifier] = types;

@@ -136,5 +137,2 @@ return definition;

let definition: any = {
};
switch (propertyTypeString.toLowerCase()) {

@@ -156,3 +154,3 @@ case "string":

const tupleType: ts.TupleType = <ts.TupleType>propertyType;
const fixedTypes = tupleType.elementTypes.map(elType => this.getDefinitionForType(elType, tc));
const fixedTypes = tupleType.elementTypes.map(elType => this.getTypeDefinition(elType, tc));
definition.type = "array";

@@ -167,4 +165,6 @@ definition.items = fixedTypes;

definition.type = "array";
definition.items = this.getDefinitionForType(arrayType, tc);
definition.items = this.getTypeDefinition(arrayType, tc);
} else {
// TODO
definition = this.getTypeDefinition(propertyType, tc);

@@ -181,5 +181,3 @@ }

let definition: any = this.getDefinitionForType(propertyType, tc);
let definition: any = this.getTypeDefinition(propertyType, tc);
if (this.args.useTitle) {

@@ -226,15 +224,3 @@ definition.title = propertyName;

private getTypeDefinition(typ: ts.Type, tc: ts.TypeChecker, asRef = this.args.useRef): any {
if(!typ.getSymbol()) {
return this.getDefinitionForType(typ, tc);
}
const node = typ.getSymbol().getDeclarations()[0];
if (node.kind == ts.SyntaxKind.EnumDeclaration) {
return this.getEnumDefinition(typ, tc, asRef);
} else {
return this.getClassDefinition(typ, tc, asRef);
}
}
private getEnumDefinition(clazzType: ts.Type, tc: ts.TypeChecker, asRef = this.args.useRef): any {
private getEnumDefinition(clazzType: ts.Type, tc: ts.TypeChecker, definition: any): any {
const node = clazzType.getSymbol().getDeclarations()[0];

@@ -270,6 +256,4 @@ const fullName = tc.typeToString(clazzType, undefined, ts.TypeFormatFlags.UseFullyQualifiedType);

var definition = {
type: "string",
title: fullName
};
definition.type = "string";
definition.title = fullName;

@@ -280,13 +264,6 @@ if (enumValues.length > 0) {

if (asRef) {
this.reffedDefinitions[fullName] = definition;
return {
"$ref": "#/definitions/" + fullName
};
} else {
return definition;
}
return definition;
}
private getClassDefinition(clazzType: ts.Type, tc: ts.TypeChecker, asRef = this.args.useRef): any {
private getClassDefinition(clazzType: ts.Type, tc: ts.TypeChecker, definition: any): any {
const node = clazzType.getSymbol().getDeclarations()[0];

@@ -297,3 +274,3 @@ const clazz = <ts.ClassDeclaration>node;

if(props.length == 0 && clazz.members.length == 1 && clazz.members[0].kind == ts.SyntaxKind.IndexSignature) {
if(props.length == 0 && clazz.members && clazz.members.length == 1 && clazz.members[0].kind == ts.SyntaxKind.IndexSignature) {
// for case "array-types"

@@ -311,9 +288,6 @@ const indexSignature = <ts.IndexSignatureDeclaration>clazz.members[0];

const typ = tc.getTypeAtLocation(indexSignature.type);
const def = this.getDefinitionForType(typ, tc, "anyOf");
const definition: any = {
type: "array",
items: def
};
const def = this.getTypeDefinition(typ, tc, undefined, "anyOf");
definition.type = "array";
definition.items = def;
return definition;

@@ -325,5 +299,3 @@ } else if (clazz.flags & ts.NodeFlags.Abstract) {

const definition = {
"oneOf": oneOf
};
definition.oneOf = oneOf;

@@ -334,5 +306,5 @@ return definition;

const propertyName = prop.getName();
const definition = this.getDefinitionForProperty(prop, tc, node);
if (definition != null) {
all[propertyName] = definition;
const propDef = this.getDefinitionForProperty(prop, tc, node);
if (propDef != null) {
all[propertyName] = propDef;
}

@@ -342,6 +314,4 @@ return all;

let definition: any = {
type: "object",
properties: propertyDefinitions
};
definition.type = "object";
definition.properties = propertyDefinitions;

@@ -376,19 +346,39 @@ if (this.args.useTitle) {

}
if (asRef) {
this.reffedDefinitions[fullName] = definition;
return {
"$ref": "#/definitions/" + fullName
};
}
}
private getTypeDefinition(typ: ts.Type, tc: ts.TypeChecker, asRef = this.args.useRef, unionModifier: string = "oneOf"): any {
const fullName = tc.typeToString(typ, undefined, ts.TypeFormatFlags.UseFullyQualifiedType);
let definition = {};
if(!typ.getSymbol() || typ.getSymbol().name == "Array") { // this is a type alias or raw type, don't do refs for these types
return this.getDefinitionForRootType(typ, tc, definition, unionModifier);
}
if (!asRef || !this.reffedDefinitions[fullName]) {
if(asRef) {
this.reffedDefinitions[fullName] = definition;
}
const node = typ.getSymbol().getDeclarations()[0];
if (node.kind == ts.SyntaxKind.EnumDeclaration) {
this.getEnumDefinition(typ, tc, definition);
} else {
return definition;
}
this.getClassDefinition(typ, tc, definition);
}
}
if (asRef) {
return {
"$ref": "#/definitions/" + fullName
};
} else {
return definition;
}
}
public getClassDefinitionByName(clazzName: string, includeReffedDefinitions: boolean = true): any {
if(!this.allSymbols[clazzName]) {
throw `type {clazzName} not found`;
public getSchemaForSymbol(symbolName: string, includeReffedDefinitions: boolean = true): any {
if(!this.allSymbols[symbolName]) {
throw `type ${symbolName} not found`;
}
let def = this.getTypeDefinition(this.allSymbols[clazzName], this.tc, this.args.useRootRef);
let def = this.getTypeDefinition(this.allSymbols[symbolName], this.tc, this.args.useRootRef);

@@ -398,3 +388,4 @@ if (this.args.useRef && includeReffedDefinitions && Object.keys(this.reffedDefinitions).length > 0) {

}
def["$schema"] = "http://json-schema.org/draft-04/schema#";
//console.log(JSON.stringify(def, null, 4) + "\n");
return def;

@@ -412,3 +403,3 @@ }

export function generateSchema(program: ts.Program, fullTypeName: string, args = defaultArgs) {
export function generateSchema(program: ts.Program, fullTypeName: string, args = getDefaultArgs()) {
const tc = program.getTypeChecker();

@@ -464,4 +455,4 @@

const generator = new JsonSchemaGenerator(allSymbols, inheritingTypes, tc, args);
let definition = generator.getClassDefinitionByName(fullTypeName);
definition["$schema"] = "http://json-schema.org/draft-04/schema#";
let definition = generator.getSchemaForSymbol(fullTypeName);
return definition;

@@ -495,3 +486,3 @@ } else {

}
export function exec(filePattern: string, fullTypeName: string, args = defaultArgs) {
export function exec(filePattern: string, fullTypeName: string, args = getDefaultArgs()) {
let program: ts.Program;

@@ -510,3 +501,3 @@ if(path.basename(filePattern) == "tsconfig.json") {

var helpText = "Usage: node typescript-json-schema.js <path-to-typescript-files-or-tsconfig> <type>";
const defaultArgs = getDefaultArgs();
var args = require("yargs")

@@ -545,3 +536,7 @@ .usage(helpText)

//TJS.exec("example/**/*.ts", "Invoice");
//const result = TJS.generateSchema(TJS.getProgramFromFiles(["test/programs/interface-single/main.ts"]), "MyObject");
//console.log(JSON.stringify(result));
/*
let args = TJS.defaultArgs;
args.useRootRef = true;
const result = TJS.generateSchema(TJS.getProgramFromFiles(["test/programs/interface-recursion/main.ts"]), "MyObject", args);
console.log(JSON.stringify(result));
*/

Sorry, the diff of this file is not supported yet

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