@f3liz/rescript-autogen-openapi 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @f3liz/rescript-autogen-openapi might be problematic. Click here for more details.
- package/lib/es6/src/bindings/Toposort.mjs +12 -0
- package/lib/es6/src/core/CodegenUtils.mjs +75 -0
- package/lib/es6/src/core/SchemaIR.mjs +72 -2
- package/lib/es6/src/core/SchemaIRParser.mjs +244 -51
- package/lib/es6/src/generators/ComponentSchemaGenerator.mjs +118 -36
- package/lib/es6/src/generators/EndpointGenerator.mjs +4 -3
- package/lib/es6/src/generators/IRToSuryGenerator.mjs +271 -34
- package/lib/es6/src/generators/IRToTypeGenerator.mjs +491 -285
- package/lib/es6/src/generators/IRToTypeScriptGenerator.mjs +1 -1
- package/lib/es6/src/generators/ModuleGenerator.mjs +1 -1
- package/lib/es6/src/generators/SchemaCodeGenerator.mjs +1 -1
- package/lib/es6/src/types/GenerationContext.mjs +25 -2
- package/package.json +3 -2
- package/src/bindings/Toposort.res +16 -0
- package/src/core/CodegenUtils.res +50 -0
- package/src/core/SchemaIR.res +33 -0
- package/src/core/SchemaIRParser.res +96 -2
- package/src/generators/ComponentSchemaGenerator.res +133 -50
- package/src/generators/EndpointGenerator.res +7 -3
- package/src/generators/IRToSuryGenerator.res +175 -40
- package/src/generators/IRToTypeGenerator.res +212 -63
- package/src/generators/IRToTypeScriptGenerator.res +6 -1
- package/src/generators/ModuleGenerator.res +2 -1
- package/src/generators/SchemaCodeGenerator.res +2 -1
- package/src/types/GenerationContext.res +34 -1
|
@@ -10,318 +10,490 @@ import * as GenerationContext from "../types/GenerationContext.mjs";
|
|
|
10
10
|
import * as IRToSuryGenerator from "./IRToSuryGenerator.mjs";
|
|
11
11
|
import * as ReferenceResolver from "../core/ReferenceResolver.mjs";
|
|
12
12
|
|
|
13
|
-
function generateTypeWithContext(ctx,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return "bool";
|
|
28
|
-
case "Null" :
|
|
29
|
-
return "unit";
|
|
30
|
-
case "Unknown" :
|
|
31
|
-
return "JSON.t";
|
|
13
|
+
function generateTypeWithContext(ctx, _depthOpt, _inlineOpt, _irType) {
|
|
14
|
+
while (true) {
|
|
15
|
+
let depthOpt = _depthOpt;
|
|
16
|
+
let inlineOpt = _inlineOpt;
|
|
17
|
+
let irType = _irType;
|
|
18
|
+
let depth = depthOpt !== undefined ? depthOpt : 0;
|
|
19
|
+
let inline = inlineOpt !== undefined ? inlineOpt : false;
|
|
20
|
+
if (depth > 100) {
|
|
21
|
+
GenerationContext.addWarning(ctx, {
|
|
22
|
+
TAG: "DepthLimitReached",
|
|
23
|
+
depth: depth,
|
|
24
|
+
path: ctx.path
|
|
25
|
+
});
|
|
26
|
+
return "JSON.t";
|
|
32
27
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
case "Integer" :
|
|
40
|
-
return "int";
|
|
41
|
-
case "Array" :
|
|
42
|
-
return `array<` + recurse(irType.items) + `>`;
|
|
43
|
-
case "Object" :
|
|
44
|
-
let additionalProperties = irType.additionalProperties;
|
|
45
|
-
let properties = irType.properties;
|
|
46
|
-
if (properties.length === 0) {
|
|
47
|
-
if (additionalProperties !== undefined) {
|
|
48
|
-
return `dict<` + recurse(additionalProperties) + `>`;
|
|
49
|
-
} else {
|
|
50
|
-
return "JSON.t";
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
let fields = properties.map(param => {
|
|
54
|
-
let name = param[0];
|
|
55
|
-
let typeCode = recurse(param[1]);
|
|
56
|
-
let finalType = param[2] ? typeCode : `option<` + typeCode + `>`;
|
|
57
|
-
let camelName = JsConvertCase.toCamelCase(name);
|
|
58
|
-
let escapedName = CodegenUtils.escapeKeyword(camelName);
|
|
59
|
-
let aliasAnnotation = escapedName !== name ? `@as("` + name + `") ` : "";
|
|
60
|
-
return ` ` + aliasAnnotation + escapedName + `: ` + finalType + `,`;
|
|
61
|
-
}).join("\n");
|
|
62
|
-
return `{\n` + fields + `\n}`;
|
|
63
|
-
case "Literal" :
|
|
64
|
-
let tmp = irType._0;
|
|
65
|
-
if (typeof tmp !== "object") {
|
|
28
|
+
let recurseInline = nextIrType => generateTypeWithContext(ctx, depth + 1 | 0, true, nextIrType);
|
|
29
|
+
if (typeof irType !== "object") {
|
|
30
|
+
switch (irType) {
|
|
31
|
+
case "Boolean" :
|
|
32
|
+
return "bool";
|
|
33
|
+
case "Null" :
|
|
66
34
|
return "unit";
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
35
|
+
case "Unknown" :
|
|
36
|
+
return "JSON.t";
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
switch (irType.TAG) {
|
|
40
|
+
case "String" :
|
|
41
|
+
return "string";
|
|
42
|
+
case "Number" :
|
|
43
|
+
return "float";
|
|
44
|
+
case "Integer" :
|
|
45
|
+
return "int";
|
|
46
|
+
case "Array" :
|
|
47
|
+
return `array<` + recurseInline(irType.items) + `>`;
|
|
48
|
+
case "Object" :
|
|
49
|
+
let additionalProperties = irType.additionalProperties;
|
|
50
|
+
let properties = irType.properties;
|
|
51
|
+
if (properties.length === 0) {
|
|
52
|
+
if (additionalProperties !== undefined) {
|
|
53
|
+
return `dict<` + recurseInline(additionalProperties) + `>`;
|
|
54
|
+
} else {
|
|
55
|
+
return "dict<JSON.t>";
|
|
56
|
+
}
|
|
81
57
|
}
|
|
82
|
-
if (
|
|
83
|
-
|
|
58
|
+
if (inline) {
|
|
59
|
+
let baseName = Stdlib_Option.getOr(ctx.path.split(".")[ctx.path.split(".").length - 1 | 0], "item");
|
|
60
|
+
return GenerationContext.extractType(ctx, baseName, undefined, irType);
|
|
84
61
|
}
|
|
85
|
-
let
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
62
|
+
let fields = properties.map(param => {
|
|
63
|
+
let fieldType = param[1];
|
|
64
|
+
let name = param[0];
|
|
65
|
+
let typeCode = recurseInline(fieldType);
|
|
66
|
+
let alreadyNullable = true;
|
|
67
|
+
if (!typeCode.startsWith("option<")) {
|
|
68
|
+
let tmp;
|
|
69
|
+
if (typeof fieldType !== "object") {
|
|
70
|
+
tmp = false;
|
|
71
|
+
} else {
|
|
72
|
+
switch (fieldType.TAG) {
|
|
73
|
+
case "Union" :
|
|
74
|
+
tmp = fieldType._0.some(t => {
|
|
75
|
+
if (typeof t !== "object") {
|
|
76
|
+
return t === "Null";
|
|
77
|
+
}
|
|
78
|
+
if (t.TAG !== "Literal") {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
let tmp = t._0;
|
|
82
|
+
return typeof tmp !== "object";
|
|
83
|
+
});
|
|
84
|
+
break;
|
|
85
|
+
case "Option" :
|
|
86
|
+
tmp = true;
|
|
87
|
+
break;
|
|
88
|
+
default:
|
|
89
|
+
tmp = false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
alreadyNullable = tmp;
|
|
93
|
+
}
|
|
94
|
+
let finalType = param[2] || alreadyNullable ? typeCode : `option<` + typeCode + `>`;
|
|
95
|
+
let camelName = JsConvertCase.toCamelCase(name);
|
|
96
|
+
let escapedName = CodegenUtils.escapeKeyword(camelName);
|
|
97
|
+
let aliasAnnotation = escapedName !== name ? `@as("` + name + `") ` : "";
|
|
98
|
+
return ` ` + aliasAnnotation + escapedName + `: ` + finalType + `,`;
|
|
99
|
+
}).join("\n");
|
|
100
|
+
return `{\n` + fields + `\n}`;
|
|
101
|
+
case "Literal" :
|
|
102
|
+
let tmp = irType._0;
|
|
103
|
+
if (typeof tmp !== "object") {
|
|
104
|
+
return "unit";
|
|
116
105
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
106
|
+
switch (tmp.TAG) {
|
|
107
|
+
case "StringLiteral" :
|
|
108
|
+
return "string";
|
|
109
|
+
case "NumberLiteral" :
|
|
110
|
+
return "float";
|
|
111
|
+
case "BooleanLiteral" :
|
|
112
|
+
return "bool";
|
|
113
|
+
}
|
|
114
|
+
case "Union" :
|
|
115
|
+
let types = irType._0;
|
|
116
|
+
let nonNullTypes = types.filter(t => {
|
|
123
117
|
if (typeof t !== "object") {
|
|
124
|
-
return
|
|
118
|
+
return t !== "Null";
|
|
125
119
|
}
|
|
126
120
|
if (t.TAG !== "Literal") {
|
|
127
|
-
return
|
|
121
|
+
return true;
|
|
128
122
|
}
|
|
129
123
|
let tmp = t._0;
|
|
130
|
-
|
|
131
|
-
|
|
124
|
+
return typeof tmp === "object";
|
|
125
|
+
});
|
|
126
|
+
let hasNull = nonNullTypes.length < types.length;
|
|
127
|
+
if (hasNull && nonNullTypes.length === 1) {
|
|
128
|
+
let inner = generateTypeWithContext(ctx, depth + 1 | 0, true, nonNullTypes[0]);
|
|
129
|
+
return `option<` + inner + `>`;
|
|
130
|
+
}
|
|
131
|
+
let effectiveTypes = hasNull ? nonNullTypes : types;
|
|
132
|
+
let match = Stdlib_Array.reduce(effectiveTypes, [
|
|
133
|
+
false,
|
|
134
|
+
false,
|
|
135
|
+
undefined,
|
|
136
|
+
undefined
|
|
137
|
+
], (param, t) => {
|
|
138
|
+
let arrItem = param[2];
|
|
139
|
+
let hArr = param[0];
|
|
140
|
+
if (typeof t !== "object" || t.TAG !== "Array") {
|
|
141
|
+
return [
|
|
142
|
+
hArr,
|
|
143
|
+
true,
|
|
144
|
+
arrItem,
|
|
145
|
+
t
|
|
146
|
+
];
|
|
132
147
|
} else {
|
|
133
|
-
return
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
if (t.TAG !== "Literal") {
|
|
141
|
-
return "#Unknown";
|
|
148
|
+
return [
|
|
149
|
+
true,
|
|
150
|
+
param[1],
|
|
151
|
+
t.items,
|
|
152
|
+
param[3]
|
|
153
|
+
];
|
|
142
154
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
});
|
|
156
|
+
let arrayItemType = match[2];
|
|
157
|
+
let result;
|
|
158
|
+
if (match[0] && match[1] && effectiveTypes.length === 2 && SchemaIR.equals(Stdlib_Option.getOr(arrayItemType, "Unknown"), Stdlib_Option.getOr(match[3], "Unknown"))) {
|
|
159
|
+
result = `array<` + recurseInline(Stdlib_Option.getOr(arrayItemType, "Unknown")) + `>`;
|
|
160
|
+
} else if (effectiveTypes.every(t => {
|
|
161
|
+
if (typeof t !== "object") {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
if (t.TAG !== "Literal") {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
let tmp = t._0;
|
|
168
|
+
if (typeof tmp !== "object") {
|
|
169
|
+
return false;
|
|
170
|
+
} else {
|
|
171
|
+
return tmp.TAG === "StringLiteral";
|
|
172
|
+
}
|
|
173
|
+
}) && effectiveTypes.length !== 0 && effectiveTypes.length <= 50) {
|
|
174
|
+
let variants = effectiveTypes.map(t => {
|
|
175
|
+
if (typeof t !== "object") {
|
|
176
|
+
return "#Unknown";
|
|
177
|
+
}
|
|
178
|
+
if (t.TAG !== "Literal") {
|
|
179
|
+
return "#Unknown";
|
|
180
|
+
}
|
|
181
|
+
let s = t._0;
|
|
182
|
+
if (typeof s !== "object" || s.TAG !== "StringLiteral") {
|
|
183
|
+
return "#Unknown";
|
|
184
|
+
} else {
|
|
185
|
+
return `#` + JsConvertCase.toPascalCase(s._0);
|
|
186
|
+
}
|
|
187
|
+
}).join(" | ");
|
|
188
|
+
result = `[` + variants + `]`;
|
|
189
|
+
} else if (effectiveTypes.length !== 0) {
|
|
190
|
+
let runtimeKinds = {};
|
|
191
|
+
effectiveTypes.forEach(t => {
|
|
192
|
+
let kind;
|
|
193
|
+
if (typeof t !== "object") {
|
|
194
|
+
switch (t) {
|
|
195
|
+
case "Boolean" :
|
|
196
|
+
kind = "boolean";
|
|
197
|
+
break;
|
|
198
|
+
case "Null" :
|
|
199
|
+
kind = "null";
|
|
200
|
+
break;
|
|
201
|
+
default:
|
|
202
|
+
kind = "unknown";
|
|
203
|
+
}
|
|
204
|
+
} else {
|
|
205
|
+
switch (t.TAG) {
|
|
206
|
+
case "String" :
|
|
207
|
+
kind = "string";
|
|
208
|
+
break;
|
|
209
|
+
case "Number" :
|
|
210
|
+
case "Integer" :
|
|
211
|
+
kind = "number";
|
|
212
|
+
break;
|
|
213
|
+
case "Array" :
|
|
214
|
+
kind = "array";
|
|
215
|
+
break;
|
|
216
|
+
case "Literal" :
|
|
217
|
+
let tmp = t._0;
|
|
218
|
+
if (typeof tmp !== "object") {
|
|
219
|
+
kind = "null";
|
|
220
|
+
} else {
|
|
221
|
+
switch (tmp.TAG) {
|
|
222
|
+
case "StringLiteral" :
|
|
223
|
+
kind = "string";
|
|
224
|
+
break;
|
|
225
|
+
case "NumberLiteral" :
|
|
226
|
+
kind = "number";
|
|
227
|
+
break;
|
|
228
|
+
case "BooleanLiteral" :
|
|
229
|
+
kind = "boolean";
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
break;
|
|
234
|
+
case "Object" :
|
|
235
|
+
case "Intersection" :
|
|
236
|
+
case "Reference" :
|
|
237
|
+
kind = "object";
|
|
238
|
+
break;
|
|
239
|
+
default:
|
|
240
|
+
kind = "unknown";
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
let count = Stdlib_Option.getOr(runtimeKinds[kind], 0);
|
|
244
|
+
runtimeKinds[kind] = count + 1 | 0;
|
|
245
|
+
});
|
|
246
|
+
let canUnbox = Object.values(runtimeKinds).every(count => count <= 1);
|
|
247
|
+
if (canUnbox) {
|
|
248
|
+
let extractIR = hasNull ? ({
|
|
249
|
+
TAG: "Union",
|
|
250
|
+
_0: effectiveTypes
|
|
251
|
+
}) : irType;
|
|
252
|
+
let baseName$1 = Stdlib_Option.getOr(ctx.path.split(".")[ctx.path.split(".").length - 1 | 0], "union");
|
|
253
|
+
result = GenerationContext.extractType(ctx, baseName$1, true, extractIR);
|
|
146
254
|
} else {
|
|
147
|
-
|
|
255
|
+
result = recurseInline(effectiveTypes[effectiveTypes.length - 1 | 0]);
|
|
148
256
|
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
"Bool",
|
|
163
|
-
"bool"
|
|
164
|
-
];
|
|
257
|
+
} else {
|
|
258
|
+
result = "JSON.t";
|
|
259
|
+
}
|
|
260
|
+
if (hasNull) {
|
|
261
|
+
return `option<` + result + `>`;
|
|
262
|
+
} else {
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
case "Intersection" :
|
|
266
|
+
let types$1 = irType._0;
|
|
267
|
+
if (types$1.every(t => {
|
|
268
|
+
if (typeof t !== "object") {
|
|
269
|
+
return false;
|
|
165
270
|
} else {
|
|
166
|
-
|
|
271
|
+
return t.TAG === "Reference";
|
|
167
272
|
}
|
|
273
|
+
}) && types$1.length !== 0) {
|
|
274
|
+
_irType = Stdlib_Option.getOr(types$1[types$1.length - 1 | 0], "Unknown");
|
|
275
|
+
_inlineOpt = inline;
|
|
276
|
+
_depthOpt = depth + 1 | 0;
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (inline) {
|
|
280
|
+
let baseName$2 = Stdlib_Option.getOr(ctx.path.split(".")[ctx.path.split(".").length - 1 | 0], "intersection");
|
|
281
|
+
return GenerationContext.extractType(ctx, baseName$2, undefined, irType);
|
|
282
|
+
}
|
|
283
|
+
let match$1 = Stdlib_Array.reduce(types$1, [
|
|
284
|
+
[],
|
|
285
|
+
[]
|
|
286
|
+
], (param, t) => {
|
|
287
|
+
let nonObj = param[1];
|
|
288
|
+
let props = param[0];
|
|
289
|
+
if (typeof t !== "object") {
|
|
290
|
+
return [
|
|
291
|
+
props,
|
|
292
|
+
nonObj.concat([t])
|
|
293
|
+
];
|
|
294
|
+
} else if (t.TAG === "Object") {
|
|
295
|
+
return [
|
|
296
|
+
props.concat(t.properties),
|
|
297
|
+
nonObj
|
|
298
|
+
];
|
|
168
299
|
} else {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
match = [
|
|
173
|
-
"String",
|
|
174
|
-
"string"
|
|
175
|
-
];
|
|
176
|
-
break;
|
|
177
|
-
case "Number" :
|
|
178
|
-
hasPrimitives.contents = true;
|
|
179
|
-
match = [
|
|
180
|
-
"Float",
|
|
181
|
-
"float"
|
|
182
|
-
];
|
|
183
|
-
break;
|
|
184
|
-
case "Integer" :
|
|
185
|
-
hasPrimitives.contents = true;
|
|
186
|
-
match = [
|
|
187
|
-
"Int",
|
|
188
|
-
"int"
|
|
189
|
-
];
|
|
190
|
-
break;
|
|
191
|
-
case "Array" :
|
|
192
|
-
match = [
|
|
193
|
-
"Array",
|
|
194
|
-
`array<` + recurse(t.items) + `>`
|
|
195
|
-
];
|
|
196
|
-
break;
|
|
197
|
-
case "Object" :
|
|
198
|
-
match = [
|
|
199
|
-
"Object",
|
|
200
|
-
recurse(t)
|
|
201
|
-
];
|
|
202
|
-
break;
|
|
203
|
-
case "Reference" :
|
|
204
|
-
let ref = t._0;
|
|
205
|
-
let name = Stdlib_Option.getOr(ref.split("/")[ref.split("/").length - 1 | 0], "");
|
|
206
|
-
match = [
|
|
207
|
-
JsConvertCase.toPascalCase(name),
|
|
208
|
-
recurse(t)
|
|
209
|
-
];
|
|
210
|
-
break;
|
|
211
|
-
default:
|
|
212
|
-
exit = 1;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (exit === 1) {
|
|
216
|
-
match = [
|
|
217
|
-
`V` + i.toString(),
|
|
218
|
-
recurse(t)
|
|
300
|
+
return [
|
|
301
|
+
props,
|
|
302
|
+
nonObj.concat([t])
|
|
219
303
|
];
|
|
220
304
|
}
|
|
221
|
-
return ` | ` + match[0] + `(` + match[1] + `)`;
|
|
222
305
|
});
|
|
223
|
-
let
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
306
|
+
let nonObjectTypes = match$1[1];
|
|
307
|
+
let objectProps = match$1[0];
|
|
308
|
+
if (objectProps.length !== 0 && nonObjectTypes.length === 0) {
|
|
309
|
+
let fields$1 = objectProps.map(param => {
|
|
310
|
+
let fieldType = param[1];
|
|
311
|
+
let name = param[0];
|
|
312
|
+
let typeCode = recurseInline(fieldType);
|
|
313
|
+
let alreadyNullable = true;
|
|
314
|
+
if (!typeCode.startsWith("option<")) {
|
|
315
|
+
let tmp;
|
|
316
|
+
if (typeof fieldType !== "object") {
|
|
317
|
+
tmp = false;
|
|
318
|
+
} else {
|
|
319
|
+
switch (fieldType.TAG) {
|
|
320
|
+
case "Union" :
|
|
321
|
+
tmp = fieldType._0.some(t => {
|
|
322
|
+
if (typeof t !== "object") {
|
|
323
|
+
return t === "Null";
|
|
324
|
+
}
|
|
325
|
+
if (t.TAG !== "Literal") {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
let tmp = t._0;
|
|
329
|
+
return typeof tmp !== "object";
|
|
330
|
+
});
|
|
331
|
+
break;
|
|
332
|
+
case "Option" :
|
|
333
|
+
tmp = true;
|
|
334
|
+
break;
|
|
335
|
+
default:
|
|
336
|
+
tmp = false;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
alreadyNullable = tmp;
|
|
340
|
+
}
|
|
341
|
+
let finalType = param[2] || alreadyNullable ? typeCode : `option<` + typeCode + `>`;
|
|
342
|
+
let camelName = JsConvertCase.toCamelCase(name);
|
|
343
|
+
let escapedName = CodegenUtils.escapeKeyword(camelName);
|
|
344
|
+
let aliasAnnotation = escapedName !== name ? `@as("` + name + `") ` : "";
|
|
345
|
+
return ` ` + aliasAnnotation + escapedName + `: ` + finalType + `,`;
|
|
346
|
+
}).join("\n");
|
|
347
|
+
return `{\n` + fields$1 + `\n}`;
|
|
348
|
+
}
|
|
349
|
+
if (nonObjectTypes.length !== 0 && objectProps.length === 0) {
|
|
350
|
+
_irType = Stdlib_Option.getOr(types$1[types$1.length - 1 | 0], "Unknown");
|
|
351
|
+
_inlineOpt = inline;
|
|
352
|
+
_depthOpt = depth + 1 | 0;
|
|
353
|
+
continue;
|
|
265
354
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
355
|
+
GenerationContext.addWarning(ctx, {
|
|
356
|
+
TAG: "IntersectionNotFullySupported",
|
|
357
|
+
location: ctx.path,
|
|
358
|
+
note: "Mixed object/non-object intersection"
|
|
359
|
+
});
|
|
360
|
+
let fields$2 = objectProps.map(param => {
|
|
361
|
+
let fieldType = param[1];
|
|
271
362
|
let name = param[0];
|
|
272
|
-
let typeCode =
|
|
273
|
-
let
|
|
363
|
+
let typeCode = recurseInline(fieldType);
|
|
364
|
+
let alreadyNullable = true;
|
|
365
|
+
if (!typeCode.startsWith("option<")) {
|
|
366
|
+
let tmp;
|
|
367
|
+
if (typeof fieldType !== "object") {
|
|
368
|
+
tmp = false;
|
|
369
|
+
} else {
|
|
370
|
+
switch (fieldType.TAG) {
|
|
371
|
+
case "Union" :
|
|
372
|
+
tmp = fieldType._0.some(t => {
|
|
373
|
+
if (typeof t !== "object") {
|
|
374
|
+
return t === "Null";
|
|
375
|
+
}
|
|
376
|
+
if (t.TAG !== "Literal") {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
let tmp = t._0;
|
|
380
|
+
return typeof tmp !== "object";
|
|
381
|
+
});
|
|
382
|
+
break;
|
|
383
|
+
case "Option" :
|
|
384
|
+
tmp = true;
|
|
385
|
+
break;
|
|
386
|
+
default:
|
|
387
|
+
tmp = false;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
alreadyNullable = tmp;
|
|
391
|
+
}
|
|
392
|
+
let finalType = param[2] || alreadyNullable ? typeCode : `option<` + typeCode + `>`;
|
|
274
393
|
let camelName = JsConvertCase.toCamelCase(name);
|
|
275
394
|
let escapedName = CodegenUtils.escapeKeyword(camelName);
|
|
276
395
|
let aliasAnnotation = escapedName !== name ? `@as("` + name + `") ` : "";
|
|
277
396
|
return ` ` + aliasAnnotation + escapedName + `: ` + finalType + `,`;
|
|
278
397
|
}).join("\n");
|
|
279
|
-
return `{\n` + fields$
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
398
|
+
return `{\n` + fields$2 + `\n}`;
|
|
399
|
+
case "Reference" :
|
|
400
|
+
let ref = irType._0;
|
|
401
|
+
let refName = ref.includes("/") ? Stdlib_Option.getOr(ref.split("/")[ref.split("/").length - 1 | 0], "") : ref;
|
|
402
|
+
let selfName = ctx.selfRefName;
|
|
403
|
+
let isSelfRef = selfName !== undefined ? refName === selfName : false;
|
|
404
|
+
if (isSelfRef) {
|
|
405
|
+
return "t";
|
|
406
|
+
}
|
|
407
|
+
let available = ctx.availableSchemas;
|
|
408
|
+
let typePath = available !== undefined ? (
|
|
409
|
+
available.includes(refName) ? JsConvertCase.toPascalCase(refName) + `.t` : `ComponentSchemas.` + JsConvertCase.toPascalCase(refName) + `.t`
|
|
410
|
+
) : Stdlib_Option.getOr(ReferenceResolver.refToTypePath(ctx.insideComponentSchemas, ctx.modulePrefix, ref), "JSON.t");
|
|
411
|
+
if (typePath === "JSON.t") {
|
|
412
|
+
GenerationContext.addWarning(ctx, {
|
|
413
|
+
TAG: "FallbackToJson",
|
|
414
|
+
reason: `Unresolved ref: ` + ref,
|
|
415
|
+
context: {
|
|
416
|
+
path: ctx.path,
|
|
417
|
+
operation: "gen ref",
|
|
418
|
+
schema: undefined
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
return typePath;
|
|
423
|
+
case "Option" :
|
|
424
|
+
return `option<` + recurseInline(irType._0) + `>`;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function generateUnboxedVariantBody(ctx, types) {
|
|
431
|
+
let rawNames = types.map(CodegenUtils.variantConstructorName);
|
|
432
|
+
let names = CodegenUtils.deduplicateNames(rawNames);
|
|
433
|
+
return types.map((irType, i) => {
|
|
434
|
+
let constructorName = names[i];
|
|
435
|
+
let payloadType;
|
|
436
|
+
let exit = 0;
|
|
437
|
+
if (typeof irType !== "object" || irType.TAG !== "Object") {
|
|
438
|
+
exit = 1;
|
|
439
|
+
} else {
|
|
440
|
+
let additionalProperties = irType.additionalProperties;
|
|
441
|
+
let properties = irType.properties;
|
|
442
|
+
if (properties.length === 0) {
|
|
443
|
+
if (additionalProperties !== undefined) {
|
|
444
|
+
let innerType = generateTypeWithContext(ctx, 1, true, additionalProperties);
|
|
445
|
+
payloadType = `(dict<` + innerType + `>)`;
|
|
446
|
+
} else {
|
|
447
|
+
payloadType = `(dict<JSON.t>)`;
|
|
283
448
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
note: "Mixed object/non-object intersection"
|
|
288
|
-
});
|
|
289
|
-
let fields$2 = objectProps.map(param => {
|
|
449
|
+
} else {
|
|
450
|
+
let fields = properties.map(param => {
|
|
451
|
+
let fieldType = param[1];
|
|
290
452
|
let name = param[0];
|
|
291
|
-
let typeCode =
|
|
292
|
-
let
|
|
453
|
+
let typeCode = generateTypeWithContext(ctx, 1, true, fieldType);
|
|
454
|
+
let alreadyNullable = true;
|
|
455
|
+
if (!typeCode.startsWith("option<")) {
|
|
456
|
+
let tmp;
|
|
457
|
+
if (typeof fieldType !== "object") {
|
|
458
|
+
tmp = false;
|
|
459
|
+
} else {
|
|
460
|
+
switch (fieldType.TAG) {
|
|
461
|
+
case "Union" :
|
|
462
|
+
tmp = fieldType._0.some(t => {
|
|
463
|
+
if (typeof t !== "object") {
|
|
464
|
+
return t === "Null";
|
|
465
|
+
}
|
|
466
|
+
if (t.TAG !== "Literal") {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
let tmp = t._0;
|
|
470
|
+
return typeof tmp !== "object";
|
|
471
|
+
});
|
|
472
|
+
break;
|
|
473
|
+
case "Option" :
|
|
474
|
+
tmp = true;
|
|
475
|
+
break;
|
|
476
|
+
default:
|
|
477
|
+
tmp = false;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
alreadyNullable = tmp;
|
|
481
|
+
}
|
|
482
|
+
let finalType = param[2] || alreadyNullable ? typeCode : `option<` + typeCode + `>`;
|
|
293
483
|
let camelName = JsConvertCase.toCamelCase(name);
|
|
294
484
|
let escapedName = CodegenUtils.escapeKeyword(camelName);
|
|
295
485
|
let aliasAnnotation = escapedName !== name ? `@as("` + name + `") ` : "";
|
|
296
|
-
return
|
|
297
|
-
}).join("
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
let name = Stdlib_Option.getOr(ref.split("/")[ref.split("/").length - 1 | 0], "");
|
|
305
|
-
typePath = available.includes(name) ? JsConvertCase.toPascalCase(name) + `.t` : `ComponentSchemas.` + JsConvertCase.toPascalCase(name) + `.t`;
|
|
306
|
-
} else {
|
|
307
|
-
typePath = Stdlib_Option.getOr(ReferenceResolver.refToTypePath(ctx.insideComponentSchemas, ctx.modulePrefix, ref), "JSON.t");
|
|
308
|
-
}
|
|
309
|
-
if (typePath === "JSON.t") {
|
|
310
|
-
GenerationContext.addWarning(ctx, {
|
|
311
|
-
TAG: "FallbackToJson",
|
|
312
|
-
reason: `Unresolved ref: ` + ref,
|
|
313
|
-
context: {
|
|
314
|
-
path: ctx.path,
|
|
315
|
-
operation: "gen ref",
|
|
316
|
-
schema: undefined
|
|
317
|
-
}
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
return typePath;
|
|
321
|
-
case "Option" :
|
|
322
|
-
return `option<` + recurse(irType._0) + `>`;
|
|
486
|
+
return aliasAnnotation + escapedName + `: ` + finalType;
|
|
487
|
+
}).join(", ");
|
|
488
|
+
payloadType = `({` + fields + `})`;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (exit === 1) {
|
|
492
|
+
let innerType$1 = generateTypeWithContext(ctx, 1, true, irType);
|
|
493
|
+
payloadType = `(` + innerType$1 + `)`;
|
|
323
494
|
}
|
|
324
|
-
|
|
495
|
+
return constructorName + payloadType;
|
|
496
|
+
}).join(" | ");
|
|
325
497
|
}
|
|
326
498
|
|
|
327
499
|
function generateType(depthOpt, pathOpt, insideComponentSchemasOpt, availableSchemas, modulePrefixOpt, irType) {
|
|
@@ -329,9 +501,9 @@ function generateType(depthOpt, pathOpt, insideComponentSchemasOpt, availableSch
|
|
|
329
501
|
let path = pathOpt !== undefined ? pathOpt : "";
|
|
330
502
|
let insideComponentSchemas = insideComponentSchemasOpt !== undefined ? insideComponentSchemasOpt : false;
|
|
331
503
|
let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
|
|
332
|
-
let ctx = GenerationContext.make(path, insideComponentSchemas, availableSchemas, modulePrefix, undefined);
|
|
504
|
+
let ctx = GenerationContext.make(path, insideComponentSchemas, availableSchemas, modulePrefix, undefined, undefined);
|
|
333
505
|
return [
|
|
334
|
-
generateTypeWithContext(ctx, depth, irType),
|
|
506
|
+
generateTypeWithContext(ctx, depth, undefined, irType),
|
|
335
507
|
ctx.warnings
|
|
336
508
|
];
|
|
337
509
|
}
|
|
@@ -339,12 +511,45 @@ function generateType(depthOpt, pathOpt, insideComponentSchemasOpt, availableSch
|
|
|
339
511
|
function generateNamedType(namedSchema, insideComponentSchemasOpt, availableSchemas, modulePrefixOpt) {
|
|
340
512
|
let insideComponentSchemas = insideComponentSchemasOpt !== undefined ? insideComponentSchemasOpt : false;
|
|
341
513
|
let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
|
|
342
|
-
let ctx = GenerationContext.make(`type.` + namedSchema.name, insideComponentSchemas, availableSchemas, modulePrefix, undefined);
|
|
514
|
+
let ctx = GenerationContext.make(`type.` + namedSchema.name, insideComponentSchemas, availableSchemas, modulePrefix, undefined, undefined);
|
|
343
515
|
let d = namedSchema.description;
|
|
344
516
|
let doc = d !== undefined ? CodegenUtils.generateDocString(undefined, d, undefined) : "";
|
|
517
|
+
let mainType = generateTypeWithContext(ctx, 0, undefined, namedSchema.type_);
|
|
518
|
+
let processed = 0;
|
|
519
|
+
while (processed < ctx.extractedTypes.length) {
|
|
520
|
+
let idx = processed;
|
|
521
|
+
let match = ctx.extractedTypes[idx];
|
|
522
|
+
let irType = match.irType;
|
|
523
|
+
if (match.isUnboxed && typeof irType === "object" && irType.TAG === "Union") {
|
|
524
|
+
irType._0.forEach(memberType => {
|
|
525
|
+
generateTypeWithContext(ctx, 0, true, memberType);
|
|
526
|
+
});
|
|
527
|
+
} else {
|
|
528
|
+
generateTypeWithContext(ctx, 0, false, irType);
|
|
529
|
+
}
|
|
530
|
+
processed = idx + 1 | 0;
|
|
531
|
+
};
|
|
532
|
+
let allExtracted = ctx.extractedTypes.slice();
|
|
533
|
+
let extractedDefs = allExtracted.map(param => {
|
|
534
|
+
let irType = param.irType;
|
|
535
|
+
let typeName = param.typeName;
|
|
536
|
+
if (param.isUnboxed) {
|
|
537
|
+
if (typeof irType === "object" && irType.TAG === "Union") {
|
|
538
|
+
let body = generateUnboxedVariantBody(ctx, irType._0);
|
|
539
|
+
return `@unboxed type ` + typeName + ` = ` + body;
|
|
540
|
+
}
|
|
541
|
+
let auxType = generateTypeWithContext(ctx, 0, undefined, irType);
|
|
542
|
+
return `type ` + typeName + ` = ` + auxType;
|
|
543
|
+
}
|
|
544
|
+
let auxType$1 = generateTypeWithContext(ctx, 0, undefined, irType);
|
|
545
|
+
return `type ` + typeName + ` = ` + auxType$1;
|
|
546
|
+
});
|
|
547
|
+
let reversedExtracted = allExtracted.toReversed();
|
|
548
|
+
let allDefs = extractedDefs.toReversed().concat([doc + `type ` + namedSchema.name + ` = ` + mainType]);
|
|
345
549
|
return [
|
|
346
|
-
|
|
347
|
-
ctx.warnings
|
|
550
|
+
allDefs.join("\n\n"),
|
|
551
|
+
ctx.warnings,
|
|
552
|
+
reversedExtracted
|
|
348
553
|
];
|
|
349
554
|
}
|
|
350
555
|
|
|
@@ -363,7 +568,7 @@ function generateAllTypes(context) {
|
|
|
363
568
|
|
|
364
569
|
function generateTypeAndSchema(namedSchema) {
|
|
365
570
|
let match = generateNamedType(namedSchema, undefined, undefined, undefined);
|
|
366
|
-
let match$1 = IRToSuryGenerator.generateNamedSchema(namedSchema, undefined, undefined, undefined);
|
|
571
|
+
let match$1 = IRToSuryGenerator.generateNamedSchema(namedSchema, undefined, undefined, undefined, match[2]);
|
|
367
572
|
return [
|
|
368
573
|
[
|
|
369
574
|
match[0],
|
|
@@ -378,6 +583,7 @@ let addWarning = GenerationContext.addWarning;
|
|
|
378
583
|
export {
|
|
379
584
|
addWarning,
|
|
380
585
|
generateTypeWithContext,
|
|
586
|
+
generateUnboxedVariantBody,
|
|
381
587
|
generateType,
|
|
382
588
|
generateNamedType,
|
|
383
589
|
generateAllTypes,
|