Skip to content

Commit 815ddb3

Browse files
committed
Recurse in to types on properties
1 parent 0321404 commit 815ddb3

File tree

3 files changed

+159
-70
lines changed

3 files changed

+159
-70
lines changed

flight-recorder-generator/flight-recorder-json-generator.d.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ export declare class FlightRecorderJsonGenerator {
33
private specification;
44
constructor(specification: Specification);
55
export(folder: string): void;
6-
private toType;
6+
private createRequestResponse;
77
private dispatchInterface;
8-
private createEnumSchema;
8+
private static createValueType;
9+
private static createEnumSchema;
10+
private lookupType;
911
private createTypeSchema;
1012
private createArraySchema;
1113
private createDictionarySchema;

flight-recorder-generator/flight-recorder-json-generator.js

Lines changed: 77 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flight-recorder-generator/flight-recorder-json-generator.ts

Lines changed: 78 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,88 +7,132 @@ export class FlightRecorderJsonGenerator {
77
constructor(private specification: Specification) { }
88

99
export(folder: string) {
10-
1110
const f = path.join(__dirname, folder);
11+
if (!fs.existsSync(f))
12+
fs.mkdirSync(f);
1213
this.specification.endpoints.forEach(api => {
1314
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+
};
1521
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+
};
1731
fs.writeFileSync(pathPrefix + "_response.json", JSON.stringify(response, null, 2));
1832
});
1933

2034
}
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);
2440
}
2541

26-
private dispatchInterface(i: Domain.Interface) {
42+
private dispatchInterface(i: Domain.Interface, seenTypes: Set<string>) {
2743
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+
}
2849

29-
switch (i.name) {
50+
private static createValueType(typeName) {
51+
switch (typeName) {
3052
case "Uri" : return "__uri__";
3153
case "Date" : return "__date__";
3254
case "TimeSpan" : return "__duration__";
55+
case "TDocument" :
56+
case "TPartialDocument" :
3357
case "SourceDocument" : return "__source__";
58+
case "T" : return "__value__";
59+
case "TResult" : return "__value__";
60+
case "string" :
61+
case "boolean" :
3462
case "short" :
3563
case "byte" :
3664
case "integer" :
3765
case "long" :
3866
case "float" :
3967
case "double" :
40-
return i.name;
68+
return typeName;
69+
case "object" :
70+
return {}
4171
}
42-
return i.properties.reduce((o, p) => ({...o, [p.name]: this.createInterfaceProperty(p)}), {});
72+
return null
4373
}
4474

45-
private createEnumSchema(enumType: Domain.Enum) {
75+
private static createEnumSchema(enumType: Domain.Enum) {
4676
return {
4777
type: "string",
4878
description: enumType.flags ? "flags" : null,
4979
enum: enumType.members.map(e => e.name)
5080
};
5181
}
5282

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;
5697

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);
60103
}
61104

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)];
64107
}
65108

66-
private createDictionarySchema(dict: Domain.Dictionary) {
109+
private createDictionarySchema(dict: Domain.Dictionary, seenTypes: Set<string>) {
67110
// 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) };
69112
}
70113

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);
73116
}
74117

75-
private createUnionOfSchema(union: Domain.UnionOf) {
118+
private createUnionOfSchema(union: Domain.UnionOf, seenTypes: Set<string>) {
76119
// union should be oneOf but open api does not support the full json-schema draft 4
77120
return { __anyOf__ : [
78-
union.items.map(i => this.dispatchInstanceOf(i))
121+
union.items.map(i => this.dispatchInstanceOf(i, seenTypes))
79122
] };
80123
}
81124

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);
87131
return { type: "object", description: "Unknown InstanceOf" };
88132
}
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};
93137
}
94138
}

0 commit comments

Comments
 (0)