typescript-json-schema
Advanced tools
Comparing version 0.41.0 to 0.42.0
@@ -224,2 +224,13 @@ "use strict"; | ||
}); | ||
describe("uniqueNames", function () { | ||
assertSchemas("unique-names", "MyObject", { | ||
uniqueNames: true | ||
}); | ||
assertRejection("unique-names", "MyObject", { | ||
uniqueNames: true | ||
}); | ||
assertSchema("unique-names-multiple-subdefinitions", "MyObject", { | ||
uniqueNames: true | ||
}); | ||
}); | ||
describe("other", function () { | ||
@@ -237,5 +248,2 @@ assertSchema("array-and-description", "MyObject"); | ||
}); | ||
assertSchemas("unique-names", "MyObject", { | ||
uniqueNames: true | ||
}); | ||
assertSchema("builtin-names", "Ext.Foo"); | ||
@@ -242,0 +250,0 @@ assertSchema("user-symbols", "*"); |
@@ -171,2 +171,21 @@ "use strict"; | ||
} | ||
function getCanonicalDeclaration(sym) { | ||
if (sym.valueDeclaration !== undefined) { | ||
return sym.valueDeclaration; | ||
} | ||
else if (sym.declarations.length === 1) { | ||
return sym.declarations[0]; | ||
} | ||
throw new Error("Symbol \"" + sym.name + "\" has no valueDeclaration and " + sym.declarations.length + " declarations."); | ||
} | ||
function getSourceFile(sym) { | ||
var currentDecl = getCanonicalDeclaration(sym); | ||
while (currentDecl.kind !== ts.SyntaxKind.SourceFile) { | ||
if (currentDecl.parent === undefined) { | ||
throw new Error("Unable to locate source file for declaration \"" + sym.name + "\"."); | ||
} | ||
currentDecl = currentDecl.parent; | ||
} | ||
return currentDecl; | ||
} | ||
var validationKeywords = { | ||
@@ -754,8 +773,24 @@ multipleOf: true, | ||
if (asTypeAliasRef) { | ||
fullTypeName = this.makeTypeNameUnique(typ, this.tc.getFullyQualifiedName(reffedType.getFlags() & ts.SymbolFlags.Alias ? | ||
var typeName = this.tc.getFullyQualifiedName(reffedType.getFlags() & ts.SymbolFlags.Alias ? | ||
this.tc.getAliasedSymbol(reffedType) : | ||
reffedType).replace(REGEX_FILE_NAME_OR_SPACE, "")); | ||
reffedType).replace(REGEX_FILE_NAME_OR_SPACE, ""); | ||
if (this.args.uniqueNames) { | ||
var sourceFile = getSourceFile(reffedType); | ||
var relativePath = path.relative(process.cwd(), sourceFile.fileName); | ||
fullTypeName = typeName + "." + generateHashOfNode(getCanonicalDeclaration(reffedType), relativePath); | ||
} | ||
else { | ||
fullTypeName = this.makeTypeNameUnique(typ, typeName); | ||
} | ||
} | ||
else if (asRef) { | ||
fullTypeName = this.getTypeName(typ); | ||
if (this.args.uniqueNames) { | ||
var sym = typ.symbol; | ||
var sourceFile = getSourceFile(sym); | ||
var relativePath = path.relative(process.cwd(), sourceFile.fileName); | ||
fullTypeName = this.getTypeName(typ) + "." + generateHashOfNode(getCanonicalDeclaration(sym), relativePath); | ||
} | ||
else { | ||
fullTypeName = this.getTypeName(typ); | ||
} | ||
} | ||
@@ -1015,2 +1050,11 @@ if (asRef) { | ||
} | ||
else if (args.uniqueNames) { | ||
var matchingSymbols = generator.getSymbols(fullTypeName); | ||
if (matchingSymbols.length === 1) { | ||
return generator.getSchemaForSymbol(matchingSymbols[0].name); | ||
} | ||
else { | ||
throw new Error(matchingSymbols.length + " definitions found for requested type \"" + fullTypeName + "\"."); | ||
} | ||
} | ||
else { | ||
@@ -1017,0 +1061,0 @@ return generator.getSchemaForSymbol(fullTypeName); |
{ | ||
"name": "typescript-json-schema", | ||
"version": "0.41.0", | ||
"version": "0.42.0", | ||
"description": "typescript-json-schema generates JSON Schema files from your Typescript sources", | ||
@@ -5,0 +5,0 @@ "main": "dist/typescript-json-schema.js", |
@@ -251,2 +251,38 @@ import * as glob from "glob"; | ||
/** | ||
* Given a Symbol, returns a canonical Definition. That can be either: | ||
* 1) The Symbol's valueDeclaration parameter if defined, or | ||
* 2) The sole entry in the Symbol's declarations array, provided that array has a length of 1. | ||
* | ||
* valueDeclaration is listed as a required parameter in the definition of a Symbol, but I've | ||
* experienced crashes when it's undefined at runtime, which is the reason for this function's | ||
* existence. Not sure if that's a compiler API bug or what. | ||
*/ | ||
function getCanonicalDeclaration(sym: ts.Symbol): ts.Declaration { | ||
if (sym.valueDeclaration !== undefined) { | ||
return sym.valueDeclaration; | ||
} else if (sym.declarations.length === 1) { | ||
return sym.declarations[0]; | ||
} | ||
throw new Error(`Symbol "${sym.name}" has no valueDeclaration and ${sym.declarations.length} declarations.`); | ||
} | ||
/** | ||
* Given a Symbol, finds the place it was declared and chases parent pointers until we find a | ||
* node where SyntaxKind === SourceFile. | ||
*/ | ||
function getSourceFile(sym: ts.Symbol): ts.SourceFile { | ||
let currentDecl: ts.Node = getCanonicalDeclaration(sym); | ||
while (currentDecl.kind !== ts.SyntaxKind.SourceFile) { | ||
if (currentDecl.parent === undefined) { | ||
throw new Error(`Unable to locate source file for declaration "${sym.name}".`); | ||
} | ||
currentDecl = currentDecl.parent; | ||
} | ||
return currentDecl as ts.SourceFile; | ||
} | ||
/** | ||
* JSDoc keywords that should be used to annotate the JSON schema. | ||
@@ -954,12 +990,26 @@ * | ||
if (asTypeAliasRef) { | ||
fullTypeName = this.makeTypeNameUnique( | ||
typ, | ||
this.tc.getFullyQualifiedName( | ||
reffedType!.getFlags() & ts.SymbolFlags.Alias ? | ||
this.tc.getAliasedSymbol(reffedType!) : | ||
reffedType! | ||
).replace(REGEX_FILE_NAME_OR_SPACE, "") | ||
); | ||
const typeName = this.tc.getFullyQualifiedName( | ||
reffedType!.getFlags() & ts.SymbolFlags.Alias ? | ||
this.tc.getAliasedSymbol(reffedType!) : | ||
reffedType! | ||
).replace(REGEX_FILE_NAME_OR_SPACE, ""); | ||
if (this.args.uniqueNames) { | ||
const sourceFile = getSourceFile(reffedType!); | ||
const relativePath = path.relative(process.cwd(), sourceFile.fileName); | ||
fullTypeName = `${typeName}.${generateHashOfNode(getCanonicalDeclaration(reffedType!), relativePath)}`; | ||
} else { | ||
fullTypeName = this.makeTypeNameUnique( | ||
typ, | ||
typeName | ||
); | ||
} | ||
} else if (asRef) { | ||
fullTypeName = this.getTypeName(typ); | ||
if (this.args.uniqueNames) { | ||
const sym = typ.symbol; | ||
const sourceFile = getSourceFile(sym); | ||
const relativePath = path.relative(process.cwd(), sourceFile.fileName); | ||
fullTypeName = `${this.getTypeName(typ)}.${generateHashOfNode(getCanonicalDeclaration(sym), relativePath)}`; | ||
} else { | ||
fullTypeName = this.getTypeName(typ); | ||
} | ||
} | ||
@@ -1241,2 +1291,9 @@ | ||
return generator.getSchemaForSymbols(generator.getMainFileSymbols(program, onlyIncludeFiles)); | ||
} else if (args.uniqueNames) { // Find the hashed type name to use as the root object | ||
const matchingSymbols = generator.getSymbols(fullTypeName); | ||
if (matchingSymbols.length === 1) { | ||
return generator.getSchemaForSymbol(matchingSymbols[0].name); | ||
} else { | ||
throw new Error(`${matchingSymbols.length} definitions found for requested type "${fullTypeName}".`); | ||
} | ||
} else { // Use specific type as root object | ||
@@ -1243,0 +1300,0 @@ return generator.getSchemaForSymbol(fullTypeName); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
197144
2984