@f3liz/rescript-autogen-openapi 0.3.1

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.
Files changed (72) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +111 -0
  3. package/lib/es6/src/Codegen.d.ts +28 -0
  4. package/lib/es6/src/Codegen.mjs +423 -0
  5. package/lib/es6/src/Types.d.ts +286 -0
  6. package/lib/es6/src/Types.mjs +20 -0
  7. package/lib/es6/src/bindings/Toposort.mjs +12 -0
  8. package/lib/es6/src/core/CodegenUtils.mjs +261 -0
  9. package/lib/es6/src/core/DocOverride.mjs +399 -0
  10. package/lib/es6/src/core/FileSystem.d.ts +4 -0
  11. package/lib/es6/src/core/FileSystem.mjs +78 -0
  12. package/lib/es6/src/core/IRBuilder.mjs +201 -0
  13. package/lib/es6/src/core/OpenAPIParser.mjs +168 -0
  14. package/lib/es6/src/core/Pipeline.d.ts +6 -0
  15. package/lib/es6/src/core/Pipeline.mjs +150 -0
  16. package/lib/es6/src/core/ReferenceResolver.mjs +41 -0
  17. package/lib/es6/src/core/Result.mjs +378 -0
  18. package/lib/es6/src/core/SchemaIR.mjs +425 -0
  19. package/lib/es6/src/core/SchemaIRParser.mjs +683 -0
  20. package/lib/es6/src/core/SchemaRefResolver.mjs +146 -0
  21. package/lib/es6/src/core/SchemaRegistry.mjs +92 -0
  22. package/lib/es6/src/core/SpecDiffer.mjs +251 -0
  23. package/lib/es6/src/core/SpecMerger.mjs +237 -0
  24. package/lib/es6/src/generators/ComponentSchemaGenerator.mjs +207 -0
  25. package/lib/es6/src/generators/DiffReportGenerator.mjs +155 -0
  26. package/lib/es6/src/generators/EndpointGenerator.mjs +173 -0
  27. package/lib/es6/src/generators/IRToSuryGenerator.mjs +543 -0
  28. package/lib/es6/src/generators/IRToTypeGenerator.mjs +592 -0
  29. package/lib/es6/src/generators/IRToTypeScriptGenerator.mjs +143 -0
  30. package/lib/es6/src/generators/ModuleGenerator.mjs +285 -0
  31. package/lib/es6/src/generators/SchemaCodeGenerator.mjs +77 -0
  32. package/lib/es6/src/generators/ThinWrapperGenerator.mjs +97 -0
  33. package/lib/es6/src/generators/TypeScriptDtsGenerator.mjs +172 -0
  34. package/lib/es6/src/generators/TypeScriptWrapperGenerator.mjs +145 -0
  35. package/lib/es6/src/types/CodegenError.d.ts +66 -0
  36. package/lib/es6/src/types/CodegenError.mjs +79 -0
  37. package/lib/es6/src/types/Config.d.ts +31 -0
  38. package/lib/es6/src/types/Config.mjs +42 -0
  39. package/lib/es6/src/types/GenerationContext.mjs +47 -0
  40. package/package.json +53 -0
  41. package/rescript.json +26 -0
  42. package/src/Codegen.res +231 -0
  43. package/src/Types.res +222 -0
  44. package/src/bindings/Toposort.res +16 -0
  45. package/src/core/CodegenUtils.res +180 -0
  46. package/src/core/DocOverride.res +504 -0
  47. package/src/core/FileSystem.res +63 -0
  48. package/src/core/IRBuilder.res +66 -0
  49. package/src/core/OpenAPIParser.res +144 -0
  50. package/src/core/Pipeline.res +52 -0
  51. package/src/core/ReferenceResolver.res +41 -0
  52. package/src/core/Result.res +187 -0
  53. package/src/core/SchemaIR.res +291 -0
  54. package/src/core/SchemaIRParser.res +454 -0
  55. package/src/core/SchemaRefResolver.res +143 -0
  56. package/src/core/SchemaRegistry.res +107 -0
  57. package/src/core/SpecDiffer.res +270 -0
  58. package/src/core/SpecMerger.res +245 -0
  59. package/src/generators/ComponentSchemaGenerator.res +210 -0
  60. package/src/generators/DiffReportGenerator.res +152 -0
  61. package/src/generators/EndpointGenerator.res +176 -0
  62. package/src/generators/IRToSuryGenerator.res +386 -0
  63. package/src/generators/IRToTypeGenerator.res +423 -0
  64. package/src/generators/IRToTypeScriptGenerator.res +77 -0
  65. package/src/generators/ModuleGenerator.res +363 -0
  66. package/src/generators/SchemaCodeGenerator.res +84 -0
  67. package/src/generators/ThinWrapperGenerator.res +124 -0
  68. package/src/generators/TypeScriptDtsGenerator.res +193 -0
  69. package/src/generators/TypeScriptWrapperGenerator.res +166 -0
  70. package/src/types/CodegenError.res +85 -0
  71. package/src/types/Config.res +95 -0
  72. package/src/types/GenerationContext.res +56 -0
@@ -0,0 +1,143 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
+ import * as SchemaIRParser from "../core/SchemaIRParser.mjs";
5
+ import * as JsConvertCase from "js-convert-case";
6
+
7
+ function generateType(_irType, _isOptionalOpt) {
8
+ while (true) {
9
+ let isOptionalOpt = _isOptionalOpt;
10
+ let irType = _irType;
11
+ let isOptional = isOptionalOpt !== undefined ? isOptionalOpt : false;
12
+ if (typeof irType !== "object") {
13
+ switch (irType) {
14
+ case "Boolean" :
15
+ return "boolean";
16
+ case "Null" :
17
+ return "null";
18
+ case "Unknown" :
19
+ return "unknown";
20
+ }
21
+ } else {
22
+ switch (irType.TAG) {
23
+ case "String" :
24
+ return "string";
25
+ case "Number" :
26
+ case "Integer" :
27
+ return "number";
28
+ case "Array" :
29
+ return generateType(irType.items, undefined) + `[]`;
30
+ case "Object" :
31
+ return generateObjectType(irType.properties, irType.additionalProperties);
32
+ case "Literal" :
33
+ let literal = irType._0;
34
+ if (typeof literal !== "object") {
35
+ return "null";
36
+ }
37
+ switch (literal.TAG) {
38
+ case "StringLiteral" :
39
+ return `"` + literal._0 + `"`;
40
+ case "NumberLiteral" :
41
+ return literal._0.toString();
42
+ case "BooleanLiteral" :
43
+ if (literal._0) {
44
+ return "true";
45
+ } else {
46
+ return "false";
47
+ }
48
+ }
49
+ case "Union" :
50
+ return irType._0.map(t => generateType(t, undefined)).join(" | ");
51
+ case "Intersection" :
52
+ return irType._0.map(t => generateType(t, undefined)).join(" & ");
53
+ case "Reference" :
54
+ let ref = irType._0;
55
+ let match = ref.split("/");
56
+ if (match.length !== 4) {
57
+ return ref;
58
+ }
59
+ let match$1 = match[1];
60
+ if (match$1 !== "components") {
61
+ return ref;
62
+ }
63
+ let match$2 = match[2];
64
+ if (match$2 !== "schemas") {
65
+ return ref;
66
+ }
67
+ let name = match[3];
68
+ return `ComponentSchemas.` + name;
69
+ case "Option" :
70
+ let inner = irType._0;
71
+ if (!isOptional) {
72
+ return generateType(inner, undefined) + ` | undefined`;
73
+ }
74
+ _isOptionalOpt = true;
75
+ _irType = inner;
76
+ continue;
77
+ }
78
+ }
79
+ };
80
+ }
81
+
82
+ function generateObjectType(properties, additionalProperties) {
83
+ let propertyLines = properties.map(param => {
84
+ let isRequired = param[2];
85
+ let fieldType = param[1];
86
+ let match;
87
+ match = typeof fieldType !== "object" ? [
88
+ fieldType,
89
+ !isRequired
90
+ ] : (
91
+ fieldType.TAG === "Option" ? [
92
+ fieldType._0,
93
+ true
94
+ ] : [
95
+ fieldType,
96
+ !isRequired
97
+ ]
98
+ );
99
+ return ` ` + param[0] + (
100
+ match[1] ? "?" : ""
101
+ ) + `: ` + generateType(match[0], true) + `;`;
102
+ });
103
+ let additionalPropertiesLines = Stdlib_Option.mapOr(additionalProperties, [], valueType => [` [key: string]: ` + generateType(valueType, undefined) + `;`]);
104
+ let allLines = propertyLines.concat(additionalPropertiesLines);
105
+ if (allLines.length === 0) {
106
+ return "Record<string, never>";
107
+ } else {
108
+ return `{\n` + allLines.join("\n") + `\n}`;
109
+ }
110
+ }
111
+
112
+ function generateNamedType(namedSchema) {
113
+ let docComment = Stdlib_Option.mapOr(namedSchema.description, "", description => `/** ` + description + ` */\n`);
114
+ let typeCode = generateType(namedSchema.type_, undefined);
115
+ let match = namedSchema.type_;
116
+ let declaration;
117
+ let exit = 0;
118
+ if (typeof match !== "object" || match.TAG !== "Object") {
119
+ exit = 1;
120
+ } else {
121
+ declaration = typeCode === "Record<string, never>" ? `export type ` + namedSchema.name + ` = ` + typeCode + `;` : `export interface ` + namedSchema.name + ` ` + typeCode;
122
+ }
123
+ if (exit === 1) {
124
+ declaration = `export type ` + namedSchema.name + ` = ` + typeCode + `;`;
125
+ }
126
+ return docComment + declaration;
127
+ }
128
+
129
+ function generateParameterType(name, schema) {
130
+ let match = SchemaIRParser.parseJsonSchema(undefined, schema);
131
+ return [
132
+ JsConvertCase.toCamelCase(name),
133
+ generateType(match[0], undefined)
134
+ ];
135
+ }
136
+
137
+ export {
138
+ generateType,
139
+ generateObjectType,
140
+ generateNamedType,
141
+ generateParameterType,
142
+ }
143
+ /* js-convert-case Not a pure module */
@@ -0,0 +1,285 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Pipeline from "../core/Pipeline.mjs";
4
+ import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
5
+ import * as FileSystem from "../core/FileSystem.mjs";
6
+ import * as CodegenUtils from "../core/CodegenUtils.mjs";
7
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
8
+ import * as OpenAPIParser from "../core/OpenAPIParser.mjs";
9
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
10
+ import * as SchemaIRParser from "../core/SchemaIRParser.mjs";
11
+ import * as JsConvertCase from "js-convert-case";
12
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
13
+ import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
14
+ import * as EndpointGenerator from "./EndpointGenerator.mjs";
15
+ import * as IRToSuryGenerator from "./IRToSuryGenerator.mjs";
16
+ import * as IRToTypeGenerator from "./IRToTypeGenerator.mjs";
17
+ import * as ComponentSchemaGenerator from "./ComponentSchemaGenerator.mjs";
18
+
19
+ function generateSchemaCodeForDict(schemaDict) {
20
+ return Object.entries(schemaDict).toSorted((param, param$1) => Primitive_string.compare(param[0], param$1[0])).flatMap(param => {
21
+ let schema = param[1];
22
+ let name = param[0];
23
+ let match = SchemaIRParser.parseJsonSchema(undefined, schema);
24
+ let ir = match[0];
25
+ let match$1 = IRToTypeGenerator.generateNamedType({
26
+ name: name,
27
+ description: schema.description,
28
+ type_: ir
29
+ }, undefined, undefined, undefined);
30
+ let match$2 = IRToSuryGenerator.generateNamedSchema({
31
+ name: name + `Schema`,
32
+ description: schema.description,
33
+ type_: ir
34
+ }, undefined, undefined, undefined, match$1[2]);
35
+ return [
36
+ CodegenUtils.indent(match$1[0], 2),
37
+ CodegenUtils.indent(match$2[0], 2),
38
+ ""
39
+ ];
40
+ });
41
+ }
42
+
43
+ function generateTagModulesCode(endpoints, overrideDir, indentOpt) {
44
+ let indent = indentOpt !== undefined ? indentOpt : 2;
45
+ let groupedByTag = OpenAPIParser.groupByTag(endpoints);
46
+ let indentStr = " ".repeat(indent);
47
+ return Stdlib_Array.filterMap(Object.keys(groupedByTag).toSorted(Primitive_string.compare), tag => Stdlib_Option.map(groupedByTag[tag], tagEndpoints => {
48
+ let moduleName = JsConvertCase.toPascalCase(tag);
49
+ let endpointLines = tagEndpoints.flatMap(endpoint => [
50
+ CodegenUtils.indent(EndpointGenerator.generateEndpointCode(endpoint, overrideDir, moduleName, undefined), indent + 2 | 0),
51
+ ""
52
+ ]);
53
+ return [indentStr + `module ` + moduleName + ` = {`].concat(endpointLines.concat([
54
+ indentStr + `}`,
55
+ ""
56
+ ]));
57
+ })).flatMap(lines => lines);
58
+ }
59
+
60
+ function generateTagModuleFile(tag, endpoints, $staropt$star, $staropt$star$1, overrideDir) {
61
+ if ($staropt$star === undefined) {
62
+ true;
63
+ }
64
+ let wrapInModule = $staropt$star$1 !== undefined ? $staropt$star$1 : false;
65
+ let moduleName = JsConvertCase.toPascalCase(tag);
66
+ let header = CodegenUtils.generateFileHeader(`API endpoints for ` + tag);
67
+ let body = endpoints.map(endpoint => EndpointGenerator.generateEndpointCode(endpoint, overrideDir, moduleName, undefined)).join("\n\n");
68
+ if (wrapInModule) {
69
+ return CodegenUtils.trimMargin(`
70
+ |` + header.trimEnd() + `
71
+ |
72
+ |module ` + moduleName + ` = {
73
+ |` + CodegenUtils.indent(body, 2) + `
74
+ |}
75
+ |`, undefined);
76
+ } else {
77
+ return CodegenUtils.trimMargin(`
78
+ |` + header.trimEnd() + `
79
+ |
80
+ |` + body + `
81
+ |`, undefined);
82
+ }
83
+ }
84
+
85
+ function generateAllTagModules(endpoints, includeSchemasOpt, wrapInModuleOpt, overrideDir) {
86
+ let includeSchemas = includeSchemasOpt !== undefined ? includeSchemasOpt : true;
87
+ let wrapInModule = wrapInModuleOpt !== undefined ? wrapInModuleOpt : false;
88
+ let groupedByTag = OpenAPIParser.groupByTag(endpoints);
89
+ return Object.entries(groupedByTag).toSorted((param, param$1) => Primitive_string.compare(param[0], param$1[0])).map(param => {
90
+ let tag = param[0];
91
+ return [
92
+ tag,
93
+ generateTagModuleFile(tag, param[1], includeSchemas, wrapInModule, overrideDir)
94
+ ];
95
+ });
96
+ }
97
+
98
+ function generateIndexModule(tags, moduleNameOpt) {
99
+ let moduleName = moduleNameOpt !== undefined ? moduleNameOpt : "API";
100
+ let header = CodegenUtils.generateFileHeader("Main API module index");
101
+ let modules = tags.toSorted(Primitive_string.compare).map(tag => {
102
+ let m = JsConvertCase.toPascalCase(tag);
103
+ return ` module ` + m + ` = ` + m;
104
+ }).join("\n");
105
+ return CodegenUtils.trimMargin(`
106
+ |` + header.trimEnd() + `
107
+ |
108
+ |module ` + moduleName + ` = {
109
+ |` + modules + `
110
+ |}
111
+ |`, undefined);
112
+ }
113
+
114
+ function generateFlatModuleCode(moduleName, endpoints, overrideDir) {
115
+ let header = CodegenUtils.generateFileHeader(`All API endpoints in ` + moduleName);
116
+ let body = endpoints.map(endpoint => CodegenUtils.indent(EndpointGenerator.generateEndpointCode(endpoint, overrideDir, moduleName, undefined), 2)).join("\n\n");
117
+ return CodegenUtils.trimMargin(`
118
+ |` + header.trimEnd() + `
119
+ |
120
+ |module ` + moduleName + ` = {
121
+ |` + body + `
122
+ |}
123
+ |`, undefined);
124
+ }
125
+
126
+ function internalGenerateIntegratedModule(name, description, endpoints, schemas, overrideDir, isExtensionOpt, includeHeaderOpt) {
127
+ let isExtension = isExtensionOpt !== undefined ? isExtensionOpt : false;
128
+ let includeHeader = includeHeaderOpt !== undefined ? includeHeaderOpt : true;
129
+ let lines = [];
130
+ if (includeHeader) {
131
+ lines.push(CodegenUtils.generateFileHeader(description), "");
132
+ }
133
+ lines.push(`module ` + name + ` = {`);
134
+ Stdlib_Option.forEach(schemas, schemaDict => {
135
+ if (Object.keys(schemaDict).length !== 0) {
136
+ lines.push(...Belt_Array.concatMany([
137
+ [
138
+ ` // ` + (
139
+ isExtension ? "Extension" : "Component"
140
+ ) + ` Schemas`,
141
+ ""
142
+ ],
143
+ generateSchemaCodeForDict(schemaDict)
144
+ ]));
145
+ return;
146
+ }
147
+ });
148
+ if (endpoints.length !== 0) {
149
+ if (isExtension) {
150
+ lines.push(" // Extension Endpoints", "");
151
+ }
152
+ lines.push(...generateTagModulesCode(endpoints, overrideDir, undefined));
153
+ }
154
+ lines.push("}");
155
+ return lines.join("\n");
156
+ }
157
+
158
+ function generateSharedModule(endpoints, schemas, overrideDir, includeHeaderOpt) {
159
+ let includeHeader = includeHeaderOpt !== undefined ? includeHeaderOpt : true;
160
+ return internalGenerateIntegratedModule("Shared", "Shared API code", endpoints, schemas, overrideDir, undefined, includeHeader);
161
+ }
162
+
163
+ function generateExtensionModule(forkName, endpoints, schemas, overrideDir, includeHeaderOpt) {
164
+ let includeHeader = includeHeaderOpt !== undefined ? includeHeaderOpt : true;
165
+ return internalGenerateIntegratedModule(JsConvertCase.toPascalCase(forkName) + `Extensions`, forkName + ` extensions`, endpoints, schemas, overrideDir, true, includeHeader);
166
+ }
167
+
168
+ function generateCombinedModule(forkName, sharedEndpoints, extensionEndpoints, sharedSchemas, extensionSchemas, overrideDir) {
169
+ let header = CodegenUtils.generateFileHeader(`Combined Shared and ` + forkName + ` extensions`);
170
+ let shared = generateSharedModule(sharedEndpoints, sharedSchemas, overrideDir, false);
171
+ let extension = generateExtensionModule(forkName, extensionEndpoints, extensionSchemas, overrideDir, false);
172
+ return CodegenUtils.trimMargin(`
173
+ |` + header.trimEnd() + `
174
+ |
175
+ |` + shared + `
176
+ |
177
+ |` + extension + `
178
+ |`, undefined);
179
+ }
180
+
181
+ function generateTagModuleFiles(endpoints, outputDir, wrapInModuleOpt, overrideDir) {
182
+ let wrapInModule = wrapInModuleOpt !== undefined ? wrapInModuleOpt : false;
183
+ let files = generateAllTagModules(endpoints, true, wrapInModule, overrideDir).map(param => {
184
+ let path = FileSystem.makePath(outputDir, JsConvertCase.toPascalCase(param[0]) + `.res`);
185
+ return {
186
+ path: path,
187
+ content: param[1]
188
+ };
189
+ });
190
+ return Pipeline.fromFilesAndWarnings(files, []);
191
+ }
192
+
193
+ function generateFlatModuleFile(moduleName, endpoints, outputDir, overrideDir) {
194
+ let path = FileSystem.makePath(outputDir, moduleName + `.res`);
195
+ let content = generateFlatModuleCode(moduleName, endpoints, overrideDir);
196
+ return Pipeline.fromFile({
197
+ path: path,
198
+ content: content
199
+ });
200
+ }
201
+
202
+ function generateInstanceTagModules(instanceName, modulePrefix, endpoints, schemas, outputDir, overrideDir) {
203
+ let apiDir = FileSystem.makePath(FileSystem.makePath(outputDir, instanceName), "api");
204
+ let schemaFiles = Stdlib_Option.mapOr(schemas, [], schemaDict => {
205
+ if (Object.keys(schemaDict).length === 0) {
206
+ return [];
207
+ }
208
+ let result = ComponentSchemaGenerator.generate({
209
+ openapi: "3.1.0",
210
+ info: {
211
+ title: instanceName,
212
+ version: "1.0.0",
213
+ description: undefined
214
+ },
215
+ paths: {},
216
+ components: {
217
+ schemas: schemaDict
218
+ }
219
+ }, apiDir);
220
+ return result.files.map(file => {
221
+ if (file.path.endsWith("ComponentSchemas.res")) {
222
+ return {
223
+ path: file.path.replace("ComponentSchemas.res", modulePrefix + `ComponentSchemas.res`),
224
+ content: file.content
225
+ };
226
+ } else {
227
+ return file;
228
+ }
229
+ });
230
+ });
231
+ let groupedByTag = OpenAPIParser.groupByTag(endpoints);
232
+ let endpointFiles = Stdlib_Array.filterMap(Object.entries(groupedByTag).toSorted((param, param$1) => Primitive_string.compare(param[0], param$1[0])), param => {
233
+ let tag = param[0];
234
+ let moduleName = modulePrefix + JsConvertCase.toPascalCase(tag);
235
+ let endpointCodes = param[1].flatMap(endpoint => [
236
+ EndpointGenerator.generateEndpointCode(endpoint, overrideDir, moduleName, modulePrefix),
237
+ ""
238
+ ]);
239
+ let content = Belt_Array.concatMany([
240
+ [
241
+ CodegenUtils.generateFileHeader(instanceName + ` API for ` + tag),
242
+ ""
243
+ ],
244
+ endpointCodes
245
+ ]).join("\n");
246
+ let path = FileSystem.makePath(apiDir, moduleName + `.res`);
247
+ return {
248
+ path: path,
249
+ content: content
250
+ };
251
+ });
252
+ return Pipeline.fromFilesAndWarnings(schemaFiles.concat(endpointFiles), []);
253
+ }
254
+
255
+ let generateBaseTagModules = generateInstanceTagModules;
256
+
257
+ let generateForkTagModules = generateInstanceTagModules;
258
+
259
+ function generateSeparatePerTagModules(baseName, basePrefix, forkName, forkPrefixOpt, sharedEndpoints, extensionEndpoints, sharedSchemas, extensionSchemas, outputDir, overrideDir) {
260
+ let forkPrefix = forkPrefixOpt !== undefined ? Primitive_option.valFromOption(forkPrefixOpt) : undefined;
261
+ return Pipeline.combine([
262
+ generateBaseTagModules(baseName, basePrefix, sharedEndpoints, sharedSchemas, outputDir, overrideDir),
263
+ generateForkTagModules(forkName, Stdlib_Option.getOr(forkPrefix, JsConvertCase.toPascalCase(forkName)), extensionEndpoints, extensionSchemas, outputDir, overrideDir)
264
+ ]);
265
+ }
266
+
267
+ export {
268
+ generateSchemaCodeForDict,
269
+ generateTagModulesCode,
270
+ generateTagModuleFile,
271
+ generateAllTagModules,
272
+ generateIndexModule,
273
+ generateFlatModuleCode,
274
+ internalGenerateIntegratedModule,
275
+ generateSharedModule,
276
+ generateExtensionModule,
277
+ generateCombinedModule,
278
+ generateTagModuleFiles,
279
+ generateFlatModuleFile,
280
+ generateInstanceTagModules,
281
+ generateBaseTagModules,
282
+ generateForkTagModules,
283
+ generateSeparatePerTagModules,
284
+ }
285
+ /* FileSystem Not a pure module */
@@ -0,0 +1,77 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as CodegenUtils from "../core/CodegenUtils.mjs";
4
+ import * as OpenAPIParser from "../core/OpenAPIParser.mjs";
5
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
+ import * as SchemaIRParser from "../core/SchemaIRParser.mjs";
7
+ import * as JsConvertCase from "js-convert-case";
8
+ import * as IRToSuryGenerator from "./IRToSuryGenerator.mjs";
9
+ import * as IRToTypeGenerator from "./IRToTypeGenerator.mjs";
10
+
11
+ function generateTypeCodeAndSchemaCode(name, schema) {
12
+ let match = SchemaIRParser.parseJsonSchema(undefined, schema);
13
+ let ir = match[0];
14
+ let match$1 = IRToTypeGenerator.generateNamedType({
15
+ name: name,
16
+ description: schema.description,
17
+ type_: ir
18
+ }, undefined, undefined, undefined);
19
+ let match$2 = IRToSuryGenerator.generateNamedSchema({
20
+ name: name + `Schema`,
21
+ description: schema.description,
22
+ type_: ir
23
+ }, undefined, undefined, undefined, match$1[2]);
24
+ return match$1[0] + `\n\n` + match$2[0];
25
+ }
26
+
27
+ let generateTypeAndSchema = generateTypeCodeAndSchemaCode;
28
+
29
+ function generateComponentSchemas(components) {
30
+ return Stdlib_Option.mapOr(Stdlib_Option.flatMap(components, c => c.schemas), "// No component schemas\n", schemas => {
31
+ let sections = Object.entries(schemas).map(param => generateTypeCodeAndSchemaCode(param[0], param[1])).join("\n\n");
32
+ return `// Component Schemas\n\n` + sections;
33
+ });
34
+ }
35
+
36
+ function generateOperationSchemas(operationId, operation) {
37
+ let generatePart = (suffix, schemaOpt) => Stdlib_Option.mapOr(schemaOpt, "", schema => generateTypeCodeAndSchemaCode(JsConvertCase.toPascalCase(operationId) + suffix, schema));
38
+ let requestBodySchema = Stdlib_Option.flatMap(Stdlib_Option.flatMap(operation.requestBody, body => body.content["application/json"]), mediaType => mediaType.schema);
39
+ let responses = operation.responses;
40
+ let successResponseSchema = Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Option.orElse(responses["200"], responses["201"]), response => response.content), content => content["application/json"]), mediaType => mediaType.schema);
41
+ return [
42
+ generatePart("Request", requestBodySchema),
43
+ generatePart("Response", successResponseSchema)
44
+ ].filter(code => code !== "").join("\n\n");
45
+ }
46
+
47
+ function generateEndpointModule(path, method, operation) {
48
+ let operationId = OpenAPIParser.getOperationId(path, method, operation);
49
+ let docComment = CodegenUtils.generateDocComment(operation.summary, operation.description, undefined);
50
+ let methodStr = method === "GET" ? "GET" : (
51
+ method === "PUT" ? "PUT" : (
52
+ method === "DELETE" ? "DELETE" : (
53
+ method === "HEAD" ? "HEAD" : (
54
+ method === "POST" ? "POST" : (
55
+ method === "PATCH" ? "PATCH" : "OPTIONS"
56
+ )
57
+ )
58
+ )
59
+ )
60
+ );
61
+ let schemasCode = generateOperationSchemas(operationId, operation);
62
+ return docComment + `module ` + JsConvertCase.toPascalCase(operationId) + ` = {
63
+ ` + CodegenUtils.indent(schemasCode, 2) + `
64
+
65
+ let endpoint = "` + path + `"
66
+ let method = #` + methodStr + `
67
+ }`;
68
+ }
69
+
70
+ export {
71
+ generateTypeCodeAndSchemaCode,
72
+ generateTypeAndSchema,
73
+ generateComponentSchemas,
74
+ generateOperationSchemas,
75
+ generateEndpointModule,
76
+ }
77
+ /* CodegenUtils Not a pure module */
@@ -0,0 +1,97 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Pipeline from "../core/Pipeline.mjs";
4
+ import * as FileSystem from "../core/FileSystem.mjs";
5
+ import * as CodegenUtils from "../core/CodegenUtils.mjs";
6
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
7
+ import * as OpenAPIParser from "../core/OpenAPIParser.mjs";
8
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
9
+ import * as JsConvertCase from "js-convert-case";
10
+
11
+ let clientTypeCode = CodegenUtils.trimMargin(`
12
+ |type client = {
13
+ | baseUrl: string,
14
+ | token: option<string>,
15
+ | fetch: ` + CodegenUtils.fetchTypeSignature + `,
16
+ |}
17
+ |`, undefined);
18
+
19
+ function generateConnectFunction(title) {
20
+ return CodegenUtils.trimMargin(`
21
+ |/** Create a client for ` + title + ` */
22
+ |let connect = (~baseUrl: string, ~token: option<string>=?, ~fetch: ` + CodegenUtils.fetchTypeSignature + `, ()): client => {
23
+ | baseUrl,
24
+ | token,
25
+ | fetch,
26
+ |}
27
+ |`, undefined);
28
+ }
29
+
30
+ function generateWrapperFunction(endpoint, generatedModuleName) {
31
+ let operationName = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method);
32
+ let hasRequestBody = Stdlib_Option.isSome(endpoint.requestBody);
33
+ let docComment = Stdlib_Option.mapOr(endpoint.summary, "", summary => {
34
+ let descriptionPart = Stdlib_Option.mapOr(endpoint.description, "", description => {
35
+ if (description === summary) {
36
+ return "";
37
+ } else {
38
+ return " - " + description;
39
+ }
40
+ });
41
+ return ` /** ` + summary + descriptionPart + ` */\n`;
42
+ });
43
+ let signature = hasRequestBody ? `let ` + operationName + ` = (request: ` + generatedModuleName + `.` + operationName + `Request, ~client: client)` : `let ` + operationName + ` = (~client: client)`;
44
+ let callArguments = hasRequestBody ? "~body=request, " : "";
45
+ return docComment + ` ` + signature + `: promise<` + generatedModuleName + `.` + operationName + `Response> =>
46
+ ` + generatedModuleName + `.` + operationName + `(` + callArguments + `~fetch=client.fetch)`;
47
+ }
48
+
49
+ function generateWrapper(spec, endpoints, extensionEndpointsOpt, outputDir, wrapperModuleNameOpt, generatedModulePrefixOpt, baseModulePrefixOpt) {
50
+ let extensionEndpoints = extensionEndpointsOpt !== undefined ? extensionEndpointsOpt : [];
51
+ let wrapperModuleName = wrapperModuleNameOpt !== undefined ? wrapperModuleNameOpt : "Wrapper";
52
+ let generatedModulePrefix = generatedModulePrefixOpt !== undefined ? generatedModulePrefixOpt : "";
53
+ let baseModulePrefix = baseModulePrefixOpt !== undefined ? baseModulePrefixOpt : "";
54
+ let extensionOperationIds = Stdlib_Array.reduce(extensionEndpoints, {}, (acc, endpoint) => {
55
+ let name = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method);
56
+ acc[name] = true;
57
+ return acc;
58
+ });
59
+ let hasExtensions = extensionEndpoints.length !== 0;
60
+ let allEndpoints = (
61
+ hasExtensions ? endpoints.filter(endpoint => {
62
+ let name = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method);
63
+ return !(name in extensionOperationIds);
64
+ }) : endpoints
65
+ ).concat(extensionEndpoints);
66
+ let endpointsByTag = OpenAPIParser.groupByTag(allEndpoints);
67
+ let modulesCode = Object.keys(endpointsByTag).map(tag => {
68
+ let moduleName = JsConvertCase.toPascalCase(tag);
69
+ let wrapperFunctions = Stdlib_Option.getOr(endpointsByTag[tag], []).map(endpoint => {
70
+ let operationName = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method);
71
+ let isExtension = hasExtensions && operationName in extensionOperationIds;
72
+ let prefix = !isExtension && baseModulePrefix !== "" ? baseModulePrefix : generatedModulePrefix;
73
+ let targetModuleName = prefix !== "" ? prefix + moduleName : moduleName;
74
+ return generateWrapperFunction(endpoint, targetModuleName);
75
+ }).join("\n\n");
76
+ return `module ` + moduleName + ` = {\n` + wrapperFunctions + `\n}`;
77
+ }).join("\n\n");
78
+ let fileContent = `// Generated thin wrapper
79
+
80
+ ` + clientTypeCode + `
81
+
82
+ ` + generateConnectFunction(spec.info.title) + `
83
+
84
+ ` + modulesCode;
85
+ return Pipeline.fromFilesAndWarnings([{
86
+ path: FileSystem.makePath(outputDir, wrapperModuleName + `.res`),
87
+ content: fileContent
88
+ }], []);
89
+ }
90
+
91
+ export {
92
+ clientTypeCode,
93
+ generateConnectFunction,
94
+ generateWrapperFunction,
95
+ generateWrapper,
96
+ }
97
+ /* clientTypeCode Not a pure module */