@f3liz/rescript-autogen-openapi 0.1.7 → 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 +348 -38
- package/lib/es6/src/generators/IRToTypeGenerator.mjs +503 -152
- 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 +5 -3
- 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 +254 -67
- package/src/generators/IRToTypeGenerator.res +308 -84
- 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,173 +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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
true,
|
|
90
|
-
arrItem,
|
|
91
|
-
t
|
|
92
|
-
];
|
|
93
|
-
} else {
|
|
94
|
-
return [
|
|
95
|
-
true,
|
|
96
|
-
param[1],
|
|
97
|
-
t.items,
|
|
98
|
-
param[3]
|
|
99
|
-
];
|
|
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
|
+
}
|
|
100
57
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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);
|
|
61
|
+
}
|
|
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";
|
|
105
|
+
}
|
|
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 => {
|
|
107
117
|
if (typeof t !== "object") {
|
|
108
|
-
return
|
|
118
|
+
return t !== "Null";
|
|
109
119
|
}
|
|
110
120
|
if (t.TAG !== "Literal") {
|
|
111
|
-
return
|
|
121
|
+
return true;
|
|
112
122
|
}
|
|
113
123
|
let tmp = t._0;
|
|
114
|
-
|
|
115
|
-
|
|
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
|
+
];
|
|
116
147
|
} else {
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
148
|
+
return [
|
|
149
|
+
true,
|
|
150
|
+
param[1],
|
|
151
|
+
t.items,
|
|
152
|
+
param[3]
|
|
153
|
+
];
|
|
123
154
|
}
|
|
124
|
-
|
|
125
|
-
|
|
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);
|
|
254
|
+
} else {
|
|
255
|
+
result = recurseInline(effectiveTypes[effectiveTypes.length - 1 | 0]);
|
|
126
256
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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;
|
|
270
|
+
} else {
|
|
271
|
+
return t.TAG === "Reference";
|
|
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
|
+
];
|
|
130
299
|
} else {
|
|
131
|
-
return
|
|
300
|
+
return [
|
|
301
|
+
props,
|
|
302
|
+
nonObj.concat([t])
|
|
303
|
+
];
|
|
132
304
|
}
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
305
|
+
});
|
|
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;
|
|
354
|
+
}
|
|
147
355
|
GenerationContext.addWarning(ctx, {
|
|
148
356
|
TAG: "IntersectionNotFullySupported",
|
|
149
357
|
location: ctx.path,
|
|
150
|
-
note: "
|
|
358
|
+
note: "Mixed object/non-object intersection"
|
|
151
359
|
});
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
360
|
+
let fields$2 = objectProps.map(param => {
|
|
361
|
+
let fieldType = param[1];
|
|
362
|
+
let name = param[0];
|
|
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 + `>`;
|
|
393
|
+
let camelName = JsConvertCase.toCamelCase(name);
|
|
394
|
+
let escapedName = CodegenUtils.escapeKeyword(camelName);
|
|
395
|
+
let aliasAnnotation = escapedName !== name ? `@as("` + name + `") ` : "";
|
|
396
|
+
return ` ` + aliasAnnotation + escapedName + `: ` + finalType + `,`;
|
|
397
|
+
}).join("\n");
|
|
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 + `>)`;
|
|
161
446
|
} else {
|
|
162
|
-
|
|
447
|
+
payloadType = `(dict<JSON.t>)`;
|
|
163
448
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
449
|
+
} else {
|
|
450
|
+
let fields = properties.map(param => {
|
|
451
|
+
let fieldType = param[1];
|
|
452
|
+
let name = param[0];
|
|
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
|
+
}
|
|
172
479
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
480
|
+
alreadyNullable = tmp;
|
|
481
|
+
}
|
|
482
|
+
let finalType = param[2] || alreadyNullable ? typeCode : `option<` + typeCode + `>`;
|
|
483
|
+
let camelName = JsConvertCase.toCamelCase(name);
|
|
484
|
+
let escapedName = CodegenUtils.escapeKeyword(camelName);
|
|
485
|
+
let aliasAnnotation = escapedName !== name ? `@as("` + name + `") ` : "";
|
|
486
|
+
return aliasAnnotation + escapedName + `: ` + finalType;
|
|
487
|
+
}).join(", ");
|
|
488
|
+
payloadType = `({` + fields + `})`;
|
|
489
|
+
}
|
|
178
490
|
}
|
|
179
|
-
|
|
491
|
+
if (exit === 1) {
|
|
492
|
+
let innerType$1 = generateTypeWithContext(ctx, 1, true, irType);
|
|
493
|
+
payloadType = `(` + innerType$1 + `)`;
|
|
494
|
+
}
|
|
495
|
+
return constructorName + payloadType;
|
|
496
|
+
}).join(" | ");
|
|
180
497
|
}
|
|
181
498
|
|
|
182
499
|
function generateType(depthOpt, pathOpt, insideComponentSchemasOpt, availableSchemas, modulePrefixOpt, irType) {
|
|
@@ -184,9 +501,9 @@ function generateType(depthOpt, pathOpt, insideComponentSchemasOpt, availableSch
|
|
|
184
501
|
let path = pathOpt !== undefined ? pathOpt : "";
|
|
185
502
|
let insideComponentSchemas = insideComponentSchemasOpt !== undefined ? insideComponentSchemasOpt : false;
|
|
186
503
|
let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
|
|
187
|
-
let ctx = GenerationContext.make(path, insideComponentSchemas, availableSchemas, modulePrefix, undefined);
|
|
504
|
+
let ctx = GenerationContext.make(path, insideComponentSchemas, availableSchemas, modulePrefix, undefined, undefined);
|
|
188
505
|
return [
|
|
189
|
-
generateTypeWithContext(ctx, depth, irType),
|
|
506
|
+
generateTypeWithContext(ctx, depth, undefined, irType),
|
|
190
507
|
ctx.warnings
|
|
191
508
|
];
|
|
192
509
|
}
|
|
@@ -194,12 +511,45 @@ function generateType(depthOpt, pathOpt, insideComponentSchemasOpt, availableSch
|
|
|
194
511
|
function generateNamedType(namedSchema, insideComponentSchemasOpt, availableSchemas, modulePrefixOpt) {
|
|
195
512
|
let insideComponentSchemas = insideComponentSchemasOpt !== undefined ? insideComponentSchemasOpt : false;
|
|
196
513
|
let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
|
|
197
|
-
let ctx = GenerationContext.make(`type.` + namedSchema.name, insideComponentSchemas, availableSchemas, modulePrefix, undefined);
|
|
514
|
+
let ctx = GenerationContext.make(`type.` + namedSchema.name, insideComponentSchemas, availableSchemas, modulePrefix, undefined, undefined);
|
|
198
515
|
let d = namedSchema.description;
|
|
199
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]);
|
|
200
549
|
return [
|
|
201
|
-
|
|
202
|
-
ctx.warnings
|
|
550
|
+
allDefs.join("\n\n"),
|
|
551
|
+
ctx.warnings,
|
|
552
|
+
reversedExtracted
|
|
203
553
|
];
|
|
204
554
|
}
|
|
205
555
|
|
|
@@ -218,7 +568,7 @@ function generateAllTypes(context) {
|
|
|
218
568
|
|
|
219
569
|
function generateTypeAndSchema(namedSchema) {
|
|
220
570
|
let match = generateNamedType(namedSchema, undefined, undefined, undefined);
|
|
221
|
-
let match$1 = IRToSuryGenerator.generateNamedSchema(namedSchema, undefined, undefined, undefined);
|
|
571
|
+
let match$1 = IRToSuryGenerator.generateNamedSchema(namedSchema, undefined, undefined, undefined, match[2]);
|
|
222
572
|
return [
|
|
223
573
|
[
|
|
224
574
|
match[0],
|
|
@@ -233,6 +583,7 @@ let addWarning = GenerationContext.addWarning;
|
|
|
233
583
|
export {
|
|
234
584
|
addWarning,
|
|
235
585
|
generateTypeWithContext,
|
|
586
|
+
generateUnboxedVariantBody,
|
|
236
587
|
generateType,
|
|
237
588
|
generateNamedType,
|
|
238
589
|
generateAllTypes,
|