Skip to content

Commit 3198456

Browse files
author
Zak Henry
committed
feat(JsonSchemaGenerator): Added buildGenerator function to expose the loaded JsonSchemaGenerator
1 parent f0a5d64 commit 3198456

File tree

5 files changed

+45
-21
lines changed

5 files changed

+45
-21
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export interface MyObject {
22
/**
3-
* A name
3+
* A name
44
*/
55
name?: string;
66
description?: string;

test/programs/comments-override/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
/**
2+
/**
33
* Type-level description
44
* @additionalProperties true
55
*/

test/programs/comments/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type Vector3D = number[];
1212
* Description of MyObject, a top level object,
1313
* which also has a comment that spans
1414
* multiple lines
15-
*
15+
*
1616
* @additionalProperties false
1717
* @unsupportedAnnotationThatShouldBeIgnored
1818
*/

test/schema.test.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const ajv = new Ajv();
1010
const base = "test/programs/";
1111

1212
export function assertSchema(group: string, name: string, type: string, settings: any = {}, compilerOptions?: CompilerOptions) {
13-
it(group + " should create correct schema", function() {
13+
it(group + " should create correct schema", () => {
1414
const defaults = TJS.getDefaultArgs();
1515
defaults.generateRequired = true;
1616

@@ -34,7 +34,19 @@ export function assertSchema(group: string, name: string, type: string, settings
3434
});
3535
}
3636

37-
describe("schema", function () {
37+
describe("interfaces", () => {
38+
it("should return an instance of JsonSchemaGenerator", () => {
39+
40+
const defaults = TJS.getDefaultArgs();
41+
const program = TJS.getProgramFromFiles([resolve(base + "array-and-description/main.ts")]);
42+
const generator = TJS.buildGenerator(program, defaults);
43+
44+
assert.instanceOf(generator, TJS.JsonSchemaGenerator);
45+
assert.doesNotThrow(() => generator.getSchemaForSymbol("MyObject"));
46+
});
47+
});
48+
49+
describe("schema", () => {
3850
assertSchema("array-and-description", "main.ts", "MyObject");
3951
assertSchema("class-single", "main.ts", "MyObject");
4052

typescript-json-schema.ts

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,15 @@ export class JsonSchemaGenerator {
7474
};
7575

7676
private allSymbols: { [name: string]: ts.Type };
77+
private userSymbols: { [name: string]: ts.Type };
7778
private inheritingTypes: { [baseName: string]: string[] };
7879
private tc: ts.TypeChecker;
7980

8081
private reffedDefinitions: { [key: string]: Definition } = {};
8182

82-
constructor(allSymbols: { [name: string]: ts.Type }, inheritingTypes: { [baseName: string]: string[] }, tc: ts.TypeChecker, private args = getDefaultArgs()) {
83+
constructor(allSymbols: { [name: string]: ts.Type }, userSymbols: { [name: string]: ts.Type }, inheritingTypes: { [baseName: string]: string[] }, tc: ts.TypeChecker, private args = getDefaultArgs()) {
8384
this.allSymbols = allSymbols;
85+
this.userSymbols = userSymbols;
8486
this.inheritingTypes = inheritingTypes;
8587
this.tc = tc;
8688
}
@@ -674,6 +676,10 @@ export class JsonSchemaGenerator {
674676
}
675677
return root;
676678
}
679+
680+
public getUserSymbols(): { [name: string]: ts.Type } {
681+
return this.userSymbols;
682+
}
677683
}
678684

679685
export function getProgramFromFiles(files: string[], compilerOptions: ts.CompilerOptions = {}): ts.Program {
@@ -689,7 +695,7 @@ export function getProgramFromFiles(files: string[], compilerOptions: ts.Compile
689695
return ts.createProgram(files, options);
690696
}
691697

692-
export function generateSchema(program: ts.Program, fullTypeName: string, args = getDefaultArgs()) {
698+
export function buildGenerator(program: ts.Program, args = getDefaultArgs()): JsonSchemaGenerator {
693699
const typeChecker = program.getTypeChecker();
694700

695701
var diagnostics = ts.getPreEmitDiagnostics(program);
@@ -704,10 +710,10 @@ export function generateSchema(program: ts.Program, fullTypeName: string, args =
704710
function inspect(node: ts.Node, tc: ts.TypeChecker) {
705711

706712
if (node.kind === ts.SyntaxKind.ClassDeclaration
707-
|| node.kind === ts.SyntaxKind.InterfaceDeclaration
708-
|| node.kind === ts.SyntaxKind.EnumDeclaration
709-
|| node.kind === ts.SyntaxKind.TypeAliasDeclaration
710-
) {
713+
|| node.kind === ts.SyntaxKind.InterfaceDeclaration
714+
|| node.kind === ts.SyntaxKind.EnumDeclaration
715+
|| node.kind === ts.SyntaxKind.TypeAliasDeclaration
716+
) {
711717
const symbol: ts.Symbol = (<any>node).symbol;
712718
let fullName = tc.getFullyQualifiedName(symbol);
713719

@@ -742,27 +748,33 @@ export function generateSchema(program: ts.Program, fullTypeName: string, args =
742748
inspect(sourceFile, typeChecker);
743749
});
744750

745-
const generator = new JsonSchemaGenerator(allSymbols, inheritingTypes, typeChecker, args);
746-
let definition: Definition;
747-
if (fullTypeName === "*") { // All types in file(s)
748-
definition = generator.getSchemaForSymbols(userSymbols);
749-
} else { // Use specific type as root object
750-
definition = generator.getSchemaForSymbol(fullTypeName);
751-
}
752-
return definition;
751+
return new JsonSchemaGenerator(allSymbols, userSymbols, inheritingTypes, typeChecker, args);
753752
} else {
754753
diagnostics.forEach((diagnostic) => {
755754
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
756755
if(diagnostic.file) {
757-
let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
758-
console.warn(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
756+
let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
757+
console.warn(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
759758
} else {
760759
console.warn(message);
761760
}
762761
});
763762
}
764763
}
765764

765+
export function generateSchema(program: ts.Program, fullTypeName: string, args = getDefaultArgs()) {
766+
767+
const generator = buildGenerator(program, args);
768+
769+
let definition: Definition;
770+
if (fullTypeName === "*") { // All types in file(s)
771+
definition = generator.getSchemaForSymbols(generator.getUserSymbols());
772+
} else { // Use specific type as root object
773+
definition = generator.getSchemaForSymbol(fullTypeName);
774+
}
775+
return definition;
776+
}
777+
766778
export function programFromConfig(configFileName: string) {
767779
// basically a copy of https://github.com/Microsoft/TypeScript/blob/3663d400270ccae8b69cbeeded8ffdc8fa12d7ad/src/compiler/tsc.ts -> parseConfigFile
768780
const result = ts.parseConfigFileTextToJson(configFileName, ts.sys.readFile(configFileName));

0 commit comments

Comments
 (0)