@@ -7,88 +7,132 @@ export class FlightRecorderJsonGenerator {
7
7
constructor ( private specification : Specification ) { }
8
8
9
9
export ( folder : string ) {
10
-
11
10
const f = path . join ( __dirname , folder ) ;
11
+ if ( ! fs . existsSync ( f ) )
12
+ fs . mkdirSync ( f ) ;
12
13
this . specification . endpoints . forEach ( api => {
13
14
const pathPrefix = path . join ( f , api . name ) ;
14
- const request = this . toType ( api . typeMapping . request ) ;
15
+ const request = {
16
+ api : api . name ,
17
+ args : {
18
+ body : this . createRequestResponse ( api . typeMapping . request )
19
+ }
20
+ } ;
15
21
fs . writeFileSync ( pathPrefix + "_request.json" , JSON . stringify ( request , null , 2 ) ) ;
16
- const response = this . toType ( api . typeMapping . response ) ;
22
+ const response = {
23
+ api : api . name ,
24
+ headers : { } ,
25
+ payload : {
26
+ body : this . createRequestResponse ( api . typeMapping . response )
27
+
28
+ } ,
29
+ statusCode : [ 200 ]
30
+ } ;
17
31
fs . writeFileSync ( pathPrefix + "_response.json" , JSON . stringify ( response , null , 2 ) ) ;
18
32
} ) ;
19
33
20
34
}
21
- private toType ( typeName : string ) {
22
- const type = this . specification . typeLookup [ typeName ] ;
23
- return this . toSchema ( type ) ;
35
+ private createRequestResponse ( typeName : string ) {
36
+ const type = this . lookupType ( typeName ) ;
37
+ const seenTypes = new Set < string > ( ) ;
38
+ seenTypes . add ( typeName ) ;
39
+ return this . toSchema ( type , seenTypes , typeName ) ;
24
40
}
25
41
26
- private dispatchInterface ( i : Domain . Interface ) {
42
+ private dispatchInterface ( i : Domain . Interface , seenTypes : Set < string > ) {
27
43
if ( i . inheritsFromUnresolved . some ( t => t === "String" ) ) return "__" + i . name + "__" ;
44
+ const valueType = FlightRecorderJsonGenerator . createValueType ( i . name ) ;
45
+ if ( valueType !== null ) return valueType ;
46
+
47
+ return i . properties . reduce ( ( o , p ) => ( { ...o , [ p . name ] : this . createInterfaceProperty ( p , seenTypes ) } ) , { } ) ;
48
+ }
28
49
29
- switch ( i . name ) {
50
+ private static createValueType ( typeName ) {
51
+ switch ( typeName ) {
30
52
case "Uri" : return "__uri__" ;
31
53
case "Date" : return "__date__" ;
32
54
case "TimeSpan" : return "__duration__" ;
55
+ case "TDocument" :
56
+ case "TPartialDocument" :
33
57
case "SourceDocument" : return "__source__" ;
58
+ case "T" : return "__value__" ;
59
+ case "TResult" : return "__value__" ;
60
+ case "string" :
61
+ case "boolean" :
34
62
case "short" :
35
63
case "byte" :
36
64
case "integer" :
37
65
case "long" :
38
66
case "float" :
39
67
case "double" :
40
- return i . name ;
68
+ return typeName ;
69
+ case "object" :
70
+ return { }
41
71
}
42
- return i . properties . reduce ( ( o , p ) => ( { ... o , [ p . name ] : this . createInterfaceProperty ( p ) } ) , { } ) ;
72
+ return null
43
73
}
44
74
45
- private createEnumSchema ( enumType : Domain . Enum ) {
75
+ private static createEnumSchema ( enumType : Domain . Enum ) {
46
76
return {
47
77
type : "string" ,
48
78
description : enumType . flags ? "flags" : null ,
49
79
enum : enumType . members . map ( e => e . name )
50
80
} ;
51
81
}
52
82
53
- private createTypeSchema ( type : Domain . Type ) {
54
- if ( type . name === "boolean" ) return "boolean" ;
55
- if ( type . name === "string" ) return "string" ;
83
+ private lookupType ( typeName ) {
84
+ let i = this . specification . typeLookup [ typeName ] ;
85
+ if ( i != null ) return i ;
86
+ typeName = typeName . replace ( / < .+ $ / , "" ) ;
87
+ i = this . specification . typeLookup [ typeName ] ;
88
+ if ( i == null && typeName !== "object" &&
89
+ ( ! typeName . endsWith ( "Response" ) && ! typeName . endsWith ( "Request" ) ) )
90
+ throw Error ( "Can not find " + typeName ) ;
91
+ return i ;
92
+ }
93
+
94
+ private createTypeSchema ( type : Domain . Type , seenTypes ) {
95
+ const valueType = FlightRecorderJsonGenerator . createValueType ( type . name ) ;
96
+ if ( valueType !== null ) return valueType ;
56
97
57
- const i = this . specification . typeLookup [ type . name ] ;
58
- return { }
59
- // return this.toSchema(i);
98
+ if ( seenTypes . has ( type . name ) ) return { $type : `Circular reference to: ${ type . name } ` } ;
99
+ seenTypes . add ( type . name ) ;
100
+
101
+ const i = this . lookupType ( type . name ) ;
102
+ return this . toSchema ( i , seenTypes , type . name ) ;
60
103
}
61
104
62
- private createArraySchema ( arr : Domain . ArrayOf ) {
63
- return [ this . dispatchInstanceOf ( arr . of ) ] ;
105
+ private createArraySchema ( arr : Domain . ArrayOf , seenTypes ) {
106
+ return [ this . dispatchInstanceOf ( arr . of , seenTypes ) ] ;
64
107
}
65
108
66
- private createDictionarySchema ( dict : Domain . Dictionary ) {
109
+ private createDictionarySchema ( dict : Domain . Dictionary , seenTypes : Set < string > ) {
67
110
// todo handle additionalProperties and find out how we can type the key.
68
- return { __name__ : this . dispatchInstanceOf ( dict . value ) } ;
111
+ return { __name__ : this . dispatchInstanceOf ( dict . value , seenTypes ) } ;
69
112
}
70
113
71
- private createInterfaceProperty ( property : Domain . InterfaceProperty ) {
72
- return this . dispatchInstanceOf ( property . type ) ;
114
+ private createInterfaceProperty ( property : Domain . InterfaceProperty , seenTypes : Set < string > ) {
115
+ return this . dispatchInstanceOf ( property . type , seenTypes ) ;
73
116
}
74
117
75
- private createUnionOfSchema ( union : Domain . UnionOf ) {
118
+ private createUnionOfSchema ( union : Domain . UnionOf , seenTypes : Set < string > ) {
76
119
// union should be oneOf but open api does not support the full json-schema draft 4
77
120
return { __anyOf__ : [
78
- union . items . map ( i => this . dispatchInstanceOf ( i ) )
121
+ union . items . map ( i => this . dispatchInstanceOf ( i , seenTypes ) )
79
122
] } ;
80
123
}
81
124
82
- private dispatchInstanceOf ( type : Domain . InstanceOf ) {
83
- if ( type instanceof Domain . Dictionary ) return this . createDictionarySchema ( type ) ;
84
- if ( type instanceof Domain . UnionOf ) return this . createUnionOfSchema ( type ) ;
85
- if ( type instanceof Domain . Type ) return this . createTypeSchema ( type ) ;
86
- if ( type instanceof Domain . ArrayOf ) return this . createArraySchema ( type ) ;
125
+ private dispatchInstanceOf ( type : Domain . InstanceOf , seenTypes : Set < string > ) {
126
+
127
+ if ( type instanceof Domain . Dictionary ) return this . createDictionarySchema ( type , seenTypes ) ;
128
+ if ( type instanceof Domain . UnionOf ) return this . createUnionOfSchema ( type , seenTypes ) ;
129
+ if ( type instanceof Domain . Type ) return this . createTypeSchema ( type , seenTypes ) ;
130
+ if ( type instanceof Domain . ArrayOf ) return this . createArraySchema ( type , seenTypes ) ;
87
131
return { type : "object" , description : "Unknown InstanceOf" } ;
88
132
}
89
- private toSchema ( type : Domain . TypeDeclaration ) {
90
- if ( type instanceof Domain . Enum ) return this . createEnumSchema ( type ) ;
91
- if ( type instanceof Domain . Interface ) return this . dispatchInterface ( type ) ;
92
- return { type : "object" , description : "Unknown TypeDeclaration" } ;
133
+ private toSchema ( type : Domain . TypeDeclaration , seenTypes : Set < string > , lastAddedType : string ) {
134
+ if ( type instanceof Domain . Enum ) return FlightRecorderJsonGenerator . createEnumSchema ( type ) ;
135
+ if ( type instanceof Domain . Interface ) return this . dispatchInterface ( type , seenTypes ) ;
136
+ return { type : "object" , description : "undefined in spec" + lastAddedType } ;
93
137
}
94
138
}
0 commit comments