@@ -21,6 +21,30 @@ export function getDefaultArgs() {
21
21
} ;
22
22
}
23
23
24
+ export type Definition = {
25
+ $ref ?: string ,
26
+ description ?: string ,
27
+ allOf ?: Definition [ ] ,
28
+ oneOf ?: Definition [ ] ,
29
+ anyOf ?: Definition [ ] ,
30
+ title ?: string ,
31
+ type ?: string | string [ ] ,
32
+ definitions ?: { [ key : string ] : any } ,
33
+ format ?: string ,
34
+ items ?: Definition ,
35
+ minItems ?: number ,
36
+ additionalItems ?: {
37
+ anyOf : Definition
38
+ } ,
39
+ enum ?: string [ ] | Definition [ ] ,
40
+ default ?: string | number | boolean | Object ,
41
+ additionalProperties ?: Definition ,
42
+ required ?: string [ ] ,
43
+ propertyOrder ?: string [ ] ,
44
+ properties ?: { } ,
45
+ defaultProperties ?: string [ ] ,
46
+ } ;
47
+
24
48
export class JsonSchemaGenerator {
25
49
/**
26
50
* JSDoc keywords that should be used to annotate the JSON schema.
@@ -50,15 +74,15 @@ export class JsonSchemaGenerator {
50
74
private inheritingTypes : { [ baseName : string ] : string [ ] } ;
51
75
private tc : ts . TypeChecker ;
52
76
53
- private reffedDefinitions : { [ key : string ] : any } = { } ;
77
+ private reffedDefinitions : { [ key : string ] : Definition } = { } ;
54
78
55
79
constructor ( allSymbols : { [ name : string ] : ts . Type } , inheritingTypes : { [ baseName : string ] : string [ ] } , tc : ts . TypeChecker , private args = getDefaultArgs ( ) ) {
56
80
this . allSymbols = allSymbols ;
57
81
this . inheritingTypes = inheritingTypes ;
58
82
this . tc = tc ;
59
83
}
60
84
61
- public get ReffedDefinitions ( ) : { [ key : string ] : any } {
85
+ public get ReffedDefinitions ( ) : { [ key : string ] : Definition } {
62
86
return this . reffedDefinitions ;
63
87
}
64
88
@@ -76,7 +100,10 @@ export class JsonSchemaGenerator {
76
100
return isNaN ( num ) ? value : num ;
77
101
}
78
102
79
- private parseCommentsIntoDefinition ( symbol : ts . Symbol , definition : { description : string } , otherAnnotations : { } ) : void {
103
+ /**
104
+ * Parse the comments of a symbol into the definition and other annotations.
105
+ */
106
+ private parseCommentsIntoDefinition ( symbol : ts . Symbol , definition : { description ?: string } , otherAnnotations : { } ) : void {
80
107
if ( ! symbol ) {
81
108
return ;
82
109
}
@@ -128,7 +155,7 @@ export class JsonSchemaGenerator {
128
155
return propertyType as any ;
129
156
}
130
157
131
- private getDefinitionForRootType ( propertyType : ts . Type , tc : ts . TypeChecker , reffedType : ts . Symbol , definition : any ) {
158
+ private getDefinitionForRootType ( propertyType : ts . Type , tc : ts . TypeChecker , reffedType : ts . Symbol , definition : Definition ) {
132
159
const symbol = propertyType . getSymbol ( ) ;
133
160
134
161
const tupleType = this . resolveTupleType ( propertyType ) ;
@@ -210,7 +237,7 @@ export class JsonSchemaGenerator {
210
237
211
238
const reffedType = this . getReferencedTypeSymbol ( prop , tc ) ;
212
239
213
- let definition : any = this . getTypeDefinition ( propertyType , tc , undefined , undefined , prop , reffedType ) ;
240
+ let definition = this . getTypeDefinition ( propertyType , tc , undefined , undefined , prop , reffedType ) ;
214
241
if ( this . args . useTitle ) {
215
242
definition . title = propertyName ;
216
243
}
@@ -233,7 +260,7 @@ export class JsonSchemaGenerator {
233
260
vm . runInNewContext ( "sandboxvar=" + initial . getText ( ) , sandbox ) ;
234
261
235
262
initial = sandbox . sandboxvar ;
236
- if ( initial === null || typeof ( initial ) === "string" || typeof ( initial ) === "number" || typeof ( initial ) === "boolean" || Object . prototype . toString . call ( initial ) === "[object Array]" ) {
263
+ if ( initial === null || typeof initial === "string" || typeof initial === "number" || typeof initial === "boolean" || Object . prototype . toString . call ( initial ) === "[object Array]" ) {
237
264
definition . default = initial ;
238
265
} else if ( initial ) {
239
266
console . warn ( "unknown initializer for property " + propertyName + ": " + initial ) ;
@@ -247,12 +274,12 @@ export class JsonSchemaGenerator {
247
274
return definition ;
248
275
}
249
276
250
- private getEnumDefinition ( clazzType : ts . Type , tc : ts . TypeChecker , definition : any ) : any {
277
+ private getEnumDefinition ( clazzType : ts . Type , tc : ts . TypeChecker , definition : Definition ) : Definition {
251
278
const node = clazzType . getSymbol ( ) . getDeclarations ( ) [ 0 ] ;
252
279
const fullName = tc . typeToString ( clazzType , undefined , ts . TypeFormatFlags . UseFullyQualifiedType ) ;
253
280
const enm = < ts . EnumDeclaration > node ;
254
281
255
- var enumValues : any [ ] = [ ] ;
282
+ var enumValues : Definition [ ] = [ ] ;
256
283
let enumTypes : string [ ] = [ ] ;
257
284
258
285
const addType = ( type : string ) => {
@@ -301,16 +328,16 @@ export class JsonSchemaGenerator {
301
328
}
302
329
303
330
if ( enumValues . length > 0 ) {
304
- definition [ " enum" ] = enumValues . sort ( ) ;
331
+ definition . enum = enumValues . sort ( ) ;
305
332
}
306
333
307
334
return definition ;
308
335
}
309
336
310
- private getUnionDefinition ( unionType : ts . UnionType , prop : ts . Symbol , tc : ts . TypeChecker , unionModifier : string , definition : any ) : any {
337
+ private getUnionDefinition ( unionType : ts . UnionType , prop : ts . Symbol , tc : ts . TypeChecker , unionModifier : string , definition : Definition ) {
311
338
const enumValues : ( string | number | boolean ) [ ] = [ ] ;
312
339
const simpleTypes : string [ ] = [ ] ;
313
- const schemas : any [ ] = [ ] ;
340
+ const schemas : Definition [ ] = [ ] ;
314
341
315
342
const addSimpleType = ( type : string ) => {
316
343
if ( simpleTypes . indexOf ( type ) === - 1 ) {
@@ -338,7 +365,11 @@ export class JsonSchemaGenerator {
338
365
} else {
339
366
const keys = Object . keys ( def ) ;
340
367
if ( keys . length === 1 && keys [ 0 ] === "type" ) {
341
- addSimpleType ( def . type ) ;
368
+ if ( typeof def . type !== "string" ) {
369
+ console . error ( "Expected only a simple type." ) ;
370
+ } else {
371
+ addSimpleType ( def . type ) ;
372
+ }
342
373
} else {
343
374
schemas . push ( def ) ;
344
375
}
@@ -356,7 +387,7 @@ export class JsonSchemaGenerator {
356
387
if ( isOnlyBooleans ) {
357
388
addSimpleType ( "boolean" ) ;
358
389
} else {
359
- const enumSchema : any = { enum : enumValues . sort ( ) } ;
390
+ const enumSchema : Definition = { enum : enumValues . sort ( ) } ;
360
391
361
392
// If all values are of the same primitive type, add a "type" field to the schema
362
393
if ( enumValues . every ( ( x ) => { return typeof x === "string" ; } ) ) {
@@ -387,7 +418,7 @@ export class JsonSchemaGenerator {
387
418
return definition ;
388
419
}
389
420
390
- private getClassDefinition ( clazzType : ts . Type , tc : ts . TypeChecker , definition : any ) : any {
421
+ private getClassDefinition ( clazzType : ts . Type , tc : ts . TypeChecker , definition : Definition ) : Definition {
391
422
const node = clazzType . getSymbol ( ) . getDeclarations ( ) [ 0 ] ;
392
423
const clazz = < ts . ClassDeclaration > node ;
393
424
const props = tc . getPropertiesOfType ( clazzType ) ;
@@ -476,7 +507,7 @@ export class JsonSchemaGenerator {
476
507
description : true
477
508
} ;
478
509
479
- private addSimpleType ( def : any , type : string ) {
510
+ private addSimpleType ( def : Definition , type : string ) {
480
511
for ( let k in def ) {
481
512
if ( ! this . simpleTypesAllowedProperties [ k ] ) {
482
513
return false ;
@@ -485,7 +516,7 @@ export class JsonSchemaGenerator {
485
516
486
517
if ( ! def . type ) {
487
518
def . type = type ;
488
- } else if ( def . type . push ) {
519
+ } else if ( typeof def . type !== "string" ) {
489
520
if ( ! ( < Object [ ] > def . type ) . every ( ( val ) => { return typeof val === "string" ; } ) ) {
490
521
return false ;
491
522
}
@@ -505,7 +536,7 @@ export class JsonSchemaGenerator {
505
536
return true ;
506
537
}
507
538
508
- private makeNullable ( def : any ) {
539
+ private makeNullable ( def : Definition ) {
509
540
if ( ! this . addSimpleType ( def , "null" ) ) {
510
541
let union = def . oneOf || def . anyOf ;
511
542
if ( union ) {
@@ -524,8 +555,8 @@ export class JsonSchemaGenerator {
524
555
return def ;
525
556
}
526
557
527
- private getTypeDefinition ( typ : ts . Type , tc : ts . TypeChecker , asRef = this . args . useRef , unionModifier : string = "anyOf" , prop ?: ts . Symbol , reffedType ?: ts . Symbol ) : any {
528
- const definition : any = { } ; // real definition
558
+ private getTypeDefinition ( typ : ts . Type , tc : ts . TypeChecker , asRef = this . args . useRef , unionModifier : string = "anyOf" , prop ?: ts . Symbol , reffedType ?: ts . Symbol ) : Definition {
559
+ const definition : Definition = { } ; // real definition
529
560
let returnedDefinition = definition ; // returned definition, may be a $ref
530
561
531
562
const symbol = typ . getSymbol ( ) ;
@@ -605,7 +636,7 @@ export class JsonSchemaGenerator {
605
636
return returnedDefinition ;
606
637
}
607
638
608
- public getSchemaForSymbol ( symbolName : string , includeReffedDefinitions : boolean = true ) : any {
639
+ public getSchemaForSymbol ( symbolName : string , includeReffedDefinitions : boolean = true ) : Definition {
609
640
if ( ! this . allSymbols [ symbolName ] ) {
610
641
throw `type ${ symbolName } not found` ;
611
642
}
@@ -619,7 +650,7 @@ export class JsonSchemaGenerator {
619
650
return def ;
620
651
}
621
652
622
- public getSchemaForSymbols ( symbols : { [ name : string ] : ts . Type } ) : any {
653
+ public getSchemaForSymbols ( symbols : { [ name : string ] : ts . Type } ) : Definition {
623
654
const root = {
624
655
"$schema" : "http://json-schema.org/draft-04/schema#" ,
625
656
definitions : { }
@@ -698,7 +729,7 @@ export function generateSchema(program: ts.Program, fullTypeName: string, args =
698
729
} ) ;
699
730
700
731
const generator = new JsonSchemaGenerator ( allSymbols , inheritingTypes , typeChecker , args ) ;
701
- let definition : any ;
732
+ let definition : Definition ;
702
733
if ( fullTypeName === "*" ) { // All types in file(s)
703
734
definition = generator . getSchemaForSymbols ( userSymbols ) ;
704
735
} else { // Use specific type as root object
0 commit comments